]> git.sur5r.net Git - openldap/commitdiff
First cut at SASL routines.
authorKurt Zeilenga <kurt@openldap.org>
Mon, 28 Jun 1999 22:19:21 +0000 (22:19 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Mon, 28 Jun 1999 22:19:21 +0000 (22:19 +0000)
libraries/libldap/libldap.dsp
libraries/libldap/sasl.c [new file with mode: 0644]

index 7f073efee9564da47f81bccf25a88f012574720b..3d440bf9f4ea1e330aa4aa5eea4daa432921dcfc 100644 (file)
@@ -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 (file)
index 0000000..eaf32b1
--- /dev/null
@@ -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 <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#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 );
+}