From 80e5e3fead0f0af54f54cb49bc8d5981538f2588 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Mon, 28 Jun 1999 22:19:21 +0000 Subject: [PATCH] First cut at SASL routines. --- libraries/libldap/libldap.dsp | 8 + libraries/libldap/sasl.c | 333 ++++++++++++++++++++++++++++++++++ 2 files changed, 341 insertions(+) create mode 100644 libraries/libldap/sasl.c diff --git a/libraries/libldap/libldap.dsp b/libraries/libldap/libldap.dsp index 7f073efee9..3d440bf9f4 100644 --- a/libraries/libldap/libldap.dsp +++ b/libraries/libldap/libldap.dsp @@ -291,6 +291,10 @@ SOURCE=.\print.c # End Source File # Begin Source File +SOURCE=.\references.c +# End Source File +# Begin Source File + SOURCE=.\request.c # End Source File # Begin Source File @@ -299,6 +303,10 @@ SOURCE=.\result.c # End Source File # Begin Source File +SOURCE=.\sasl.c +# End Source File +# Begin Source File + SOURCE=.\sbind.c # End Source File # Begin Source File diff --git a/libraries/libldap/sasl.c b/libraries/libldap/sasl.c new file mode 100644 index 0000000000..eaf32b1a80 --- /dev/null +++ b/libraries/libldap/sasl.c @@ -0,0 +1,333 @@ +/* + * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +/* + * BindRequest ::= SEQUENCE { + * version INTEGER, + * name DistinguishedName, -- who + * authentication CHOICE { + * simple [0] OCTET STRING -- passwd +#ifdef HAVE_KERBEROS + * krbv42ldap [1] OCTET STRING + * krbv42dsa [2] OCTET STRING +#endif + * sasl [3] SaslCredentials -- LDAPv3 + * } + * } + * + * BindResponse ::= SEQUENCE { + * COMPONENTS OF LDAPResult, + * serverSaslCreds OCTET STRING OPTIONAL -- LDAPv3 + * } + * + */ + +#include "portable.h" + +#include + +#include +#include +#include + +#include "ldap-int.h" + + +/* + * ldap_sasl_bind - bind to the ldap server (and X.500). The dn, mechanism, and + * credentials of the entry to which to bind are supplied. The message id + * of the request initiated is provided upon successful (LDAP_SUCCESS) return. + * + * Example: + * ldap_sasl_bind( ld, "cn=manager, o=university of michigan, c=us", + * "mechanism", "secret", NULL, NULL, &msgid ) + */ + +int +ldap_sasl_bind( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *mechanism, + struct berval *cred, + LDAPControl **sctrls, + LDAPControl **cctrls, + int *msgidp ) +{ + BerElement *ber; + int rc; + + Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( msgidp != NULL ); + + if( msgidp == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + if( mechanism != LDAP_SASL_SIMPLE + && ld->ld_version < LDAP_VERSION3) + { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + + if ( dn == NULL ) + dn = ""; + + /* create a message to send */ + if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + assert( BER_VALID( ber ) ); + + if( mechanism == LDAP_SASL_SIMPLE ) { + /* simple bind */ + rc = ber_printf( ber, "{it{istO}" /*}*/, + ++ld->ld_msgid, LDAP_REQ_BIND, + ld->ld_version, dn, LDAP_AUTH_SIMPLE, + cred ); + + } else if ( cred == NULL ) { + /* SASL bind w/o creditials */ + rc = ber_printf( ber, "{it{ist{s}}" /*}*/, + ++ld->ld_msgid, LDAP_REQ_BIND, + ld->ld_version, dn, LDAP_AUTH_SASL, + mechanism ); + + } else { + /* SASL bind w/ creditials */ + rc = ber_printf( ber, "{it{ist{sO}}" /*}*/, + ++ld->ld_msgid, LDAP_REQ_BIND, + ld->ld_version, dn, LDAP_AUTH_SASL, + mechanism, cred ); + } + + if( rc == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return( -1 ); + } + + /* Put Server Controls */ + if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { + ber_free( ber, 1 ); + return ld->ld_errno; + } + + if ( ber_printf( ber, /*{*/ "}" ) == -1 ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + ber_free( ber, 1 ); + return ld->ld_errno; + } + +#ifndef LDAP_NOCACHE + if ( ld->ld_cache != NULL ) { + ldap_flush_cache( ld ); + } +#endif /* !LDAP_NOCACHE */ + + /* send the message */ + *msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber ); + + if(*msgidp < 0) + return ld->ld_errno; + + return LDAP_SUCCESS; +} + +/* + * ldap_sasl_bind_s - bind to the ldap server (and X.500) using simple + * authentication. The dn and password of the entry to which to bind are + * supplied. LDAP_SUCCESS is returned upon success, the ldap error code + * otherwise. + * + * Example: + * ldap_sasl_bind_s( ld, "cn=manager, o=university of michigan, c=us", + * "mechanism", "secret", NULL, NULL, &servercred ) + */ + +int +ldap_sasl_bind_s( + LDAP *ld, + LDAP_CONST char *dn, + LDAP_CONST char *mechanism, + struct berval *cred, + LDAPControl **sctrls, + LDAPControl **cctrls, + struct berval **servercredp ) +{ + int rc, msgid; + LDAPMessage *result; + struct berval *scredp = NULL; + + Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind_s\n", 0, 0, 0 ); + + /* do a quick !LDAPv3 check... ldap_sasl_bind will do the rest. */ + if( servercredp != NULL ) { + if (ld->ld_version < LDAP_VERSION3) { + ld->ld_errno = LDAP_NOT_SUPPORTED; + return ld->ld_errno; + } + *servercredp = NULL; + } + + rc = ldap_sasl_bind( ld, dn, mechanism, cred, sctrls, cctrls, &msgid ); + + if ( rc != LDAP_SUCCESS ) { + return( rc ); + } + + if ( ldap_result( ld, msgid, 1, NULL, &result ) == -1 ) { + return( ld->ld_errno ); /* ldap_result sets ld_errno */ + } + + /* parse the results */ + scredp = NULL; + if( servercredp != NULL ) { + rc = ldap_parse_sasl_bind_result( ld, result, &scredp, 0 ); + } + + if( rc != LDAP_SUCCESS ) { + ldap_msgfree( result ); + return( rc ); + } + + rc = ldap_result2error( ld, result, 1 ); + + if( rc == LDAP_SUCCESS ) { + if( servercredp != NULL ) { + *servercredp = scredp; + } + + } else if (scredp != NULL ) { + ber_bvfree(scredp); + } + + return rc; +} + + +/* + * Parse BindResponse: + * + * BindResponse ::= [APPLICATION 1] SEQUENCE { + * COMPONENTS OF LDAPResult, + * serverSaslCreds [7] OCTET STRING OPTIONAL } + * + * LDAPResult ::= SEQUENCE { + * resultCode ENUMERATED, + * matchedDN LDAPDN, + * errorMessage LDAPString, + * referral [3] Referral OPTIONAL } + */ + +int +ldap_parse_sasl_bind_result( + LDAP *ld, + LDAPMessage *res, + struct berval **servercredp, + int freeit ) +{ + ber_int_t errcode; + struct berval* scred; + + ber_tag_t tag; + BerElement *ber; + + Debug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 ); + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( res != NULL ); + + if ( ld == NULL || res == NULL ) { + return LDAP_PARAM_ERROR; + } + + if(servercredp != NULL) { + if( ld->ld_version < LDAP_VERSION2 ) { + return LDAP_NOT_SUPPORTED; + } + *servercredp = NULL; + } + + if( res->lm_msgtype == LDAP_RES_BIND ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + errcode = LDAP_SUCCESS; + scred = NULL; + + if ( ld->ld_error ) { + LDAP_FREE( ld->ld_error ); + ld->ld_error = NULL; + } + if ( ld->ld_matched ) { + LDAP_FREE( ld->ld_matched ); + ld->ld_matched = NULL; + } + + /* parse results */ + + ber = ber_dup( res->lm_ber ); + + if ( ld->ld_version < LDAP_VERSION2 ) { + tag = ber_scanf( ber, "{ia}", + &errcode, &ld->ld_error ); + + } else { + ber_len_t len; + + tag = ber_scanf( ber, "{iaa" /*}*/, + &errcode, &ld->ld_matched, &ld->ld_error ); + + if( tag != LBER_ERROR ) { + tag = ber_peek_tag(ber, &len); + } + + if( tag == LDAP_TAG_REFERRAL ) { + /* skip 'em */ + tag = ber_scanf( ber, "x" ); + + if( tag != LBER_ERROR ) { + tag = ber_peek_tag(ber, &len); + } + } + + /* need to clean out misc items */ + if( tag == LDAP_TAG_SASL_RES_CREDS ) { + tag = ber_scanf( ber, "O", &scred ); + } + } + + if ( tag == LBER_ERROR ) { + errcode = LDAP_DECODING_ERROR; + } + + if( ber != NULL ) { + ber_free( ber, 0 ); + } + + /* return */ + if ( errcode == LDAP_SUCCESS && servercredp != NULL ) { + *servercredp = scred; + + } else if ( scred != NULL ) { + ber_bvfree( scred ); + } + + if ( freeit ) { + ldap_msgfree( res ); + } + + ld->ld_errno = errcode; + return( ld->ld_errno ); +} -- 2.39.5