]> git.sur5r.net Git - openldap/commitdiff
ITS#1712, rewritten dn_openssl2ldap(). Added dnDCEnormalize(), used by
authorHoward Chu <hyc@openldap.org>
Tue, 16 Apr 2002 08:46:25 +0000 (08:46 +0000)
committerHoward Chu <hyc@openldap.org>
Tue, 16 Apr 2002 08:46:25 +0000 (08:46 +0000)
dn_openssl2ldap() and sasl_external_x509dn_convert. Fixed realm handling
for foreign Kerberos realms embedded in usernames.

servers/slapd/dn.c
servers/slapd/proto-slap.h
servers/slapd/sasl.c
servers/slapd/schema_init.c

index 450691d326a5c076b48dfc116a07b0e8f5f409b5..40064a47fa3af42d25058f4d0d76ba65e3371d52 100644 (file)
@@ -829,3 +829,40 @@ dnIsSuffix(
        /* compare */
        return( strcmp( dn->bv_val + d, suffix->bv_val ) == 0 );
 }
+
+/*
+ * Convert a DN from X.500 format into a normalized DN
+ */
+int
+dnDCEnormalize( char *dce, struct berval *out )
+{
+       int rc;
+       LDAPDN *dn = NULL;
+
+       out->bv_val = NULL;
+       out->bv_len = 0;
+
+       rc = ldap_str2dn( dce, &dn, LDAP_DN_FORMAT_DCE );
+       if  ( rc != LDAP_SUCCESS )
+               return rc;
+
+       /*
+        * Schema-aware rewrite
+        */
+       if ( LDAPDN_rewrite( dn, 0 ) != LDAP_SUCCESS ) {
+               ldap_dnfree( dn );
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       /*
+        * Back to string representation
+        */
+       rc = ldap_dn2bv( dn, out, LDAP_DN_FORMAT_LDAPV3 );
+
+       ldap_dnfree( dn );
+
+       if ( rc != LDAP_SUCCESS ) {
+               rc = LDAP_INVALID_SYNTAX;
+       }
+       return rc;
+}
index f3d6a8b0b346478505805e4e893fbcae63879699..0e0939eac9ee01c53b1621f1fae45e5139ca1fc0 100644 (file)
@@ -404,6 +404,8 @@ LDAP_SLAPD_F (void) build_new_dn LDAP_P((
 
 LDAP_SLAPD_F (void) dnParent LDAP_P(( struct berval *dn, struct berval *pdn ));
 
+LDAP_SLAPD_F (int) dnDCEnormalize LDAP_P(( char *dce, struct berval *out ));
+
 /*
  * entry.c
  */
index 4876c076f8dada7137043cdefa924744fa580e7d..bc5de313baa674e4d9fb516591e817b0b71d2b89 100644 (file)
@@ -137,11 +137,11 @@ slap_sasl_log(
 
 static struct berval ext_bv = { sizeof("EXTERNAL")-1, "EXTERNAL" };
 
-int slap_sasl_getdn( Connection *conn, char *id,
+int slap_sasl_getdn( Connection *conn, char *id, int len,
        char *user_realm, struct berval *dn, int flags )
 {
        char *c1;
-       int rc, len, is_dn = 0;
+       int rc, is_dn = 0;
        sasl_conn_t *ctx;
        struct berval dn2;
 
@@ -166,7 +166,7 @@ int slap_sasl_getdn( Connection *conn, char *id,
                return( LDAP_SUCCESS );
        }
        ctx = conn->c_sasl_context;
-       len = strlen( id );
+       if ( len == 0 ) len = strlen( id );
 
        /* An authcID needs to be converted to authzID form */
        if( flags & FLAG_GETDN_AUTHCID ) {
@@ -177,8 +177,7 @@ int slap_sasl_getdn( Connection *conn, char *id,
                {
                        /* check SASL external for X.509 style DN and */
                        /* convert to dn:<dn> form */
-                       dn->bv_val = ldap_dcedn2dn( id );
-                       dn->bv_len = strlen(dn->bv_val);
+                       dnDCEnormalize( id, dn );
                        is_dn = SET_DN;
 
                } else {
@@ -309,7 +308,7 @@ slap_sasl_checkpass(
        /* XXX do we need to check sasldb as well? */
 
        /* XXX can we do both steps at once? */
-       rc = slap_sasl_getdn( conn, (char *)username, NULL, &dn,
+       rc = slap_sasl_getdn( conn, (char *)username, 0, NULL, &dn,
                FLAG_GETDN_AUTHCID | FLAG_GETDN_FINAL );
        if ( rc != LDAP_SUCCESS ) {
                sasl_seterror( sconn, 0, ldap_err2string( rc ) );
@@ -388,7 +387,7 @@ slap_sasl_canonicalize(
                        in ? in : "<empty>" );
 #endif
 
-       rc = slap_sasl_getdn( conn, (char *)in, (char *)user_realm, &dn,
+       rc = slap_sasl_getdn( conn, (char *)in, inlen, (char *)user_realm, &dn,
                (flags == SASL_CU_AUTHID) ? FLAG_GETDN_AUTHCID : FLAG_GETDN_AUTHZID );
        if ( rc != LDAP_SUCCESS ) {
                sasl_seterror( sconn, 0, ldap_err2string( rc ) );
@@ -441,7 +440,7 @@ slap_sasl_authorize(
        Connection *conn = (Connection *)context;
        struct berval authcDN, authzDN;
        char *realm;
-       int rc, equal = 1;
+       int rc, equal = 1, ext = 0;
 
 #ifdef NEW_LOGGING
        LDAP_LOG(( "sasl", LDAP_LEVEL_ENTRY,
@@ -456,11 +455,19 @@ slap_sasl_authorize(
        if ( requested_user )
                equal = !strcmp( auth_identity, requested_user );
 
-       realm = strchr( auth_identity, '@' );
-       if ( realm )
-               *realm++ = '\0';
+       /* If using SASL-EXTERNAL, don't modify the ID in any way */
+       if ( conn->c_sasl_bind_mech.bv_len == ext_bv.bv_len
+               && ( strcasecmp( ext_bv.bv_val, conn->c_sasl_bind_mech.bv_val ) == 0 ) 
+                       && auth_identity[0] == '/' ) {
+               ext = 1;
+               realm = NULL;
+       } else {
+       /* Else look for an embedded realm in the name */
+               realm = strchr( auth_identity, '@' );
+               if ( realm ) *realm++ = '\0';
+       }
 
-       rc = slap_sasl_getdn( conn, auth_identity, realm ? realm : (char *)def_realm,
+       rc = slap_sasl_getdn( conn, auth_identity, alen, realm ? realm : (char *)def_realm,
                &authcDN, FLAG_GETDN_AUTHCID );
        if ( realm )
                realm[-1] = '@';
@@ -480,11 +487,14 @@ slap_sasl_authorize(
                return SASL_OK;
        }
 
-       realm = strchr( requested_user, '@' );
-       if ( realm )
-               *realm++ = '\0';
+       if ( ext ) {
+               realm = NULL;
+       } else {
+               realm = strchr( requested_user, '@' );
+               if ( realm ) *realm++ = '\0';
+       }
 
-       rc = slap_sasl_getdn( conn, requested_user, realm ? realm : (char *)def_realm,
+       rc = slap_sasl_getdn( conn, requested_user, rlen, realm ? realm : (char *)def_realm,
                &authzDN, FLAG_GETDN_AUTHZID );
        if ( realm )
                realm[-1] = '@';
@@ -537,15 +547,15 @@ slap_sasl_authorize(
 static int
 slap_sasl_authorize(
        void *context,
-       const char *authcid,
-       const char *authzid,
+       char *authcid,
+       char *authzid,
        const char **user,
        const char **errstr)
 {
        struct berval authcDN, authzDN;
-       int rc;
+       int rc, ext = 0;
        Connection *conn = context;
-       char *realm;
+       char *realm, *xrealm;
 
        *user = NULL;
 
@@ -579,7 +589,17 @@ slap_sasl_authorize(
 
        /* Convert the identities to DN's. If no authzid was given, client will
           be bound as the DN matching their username */
-       rc = slap_sasl_getdn( conn, (char *)authcid, realm, &authcDN, FLAG_GETDN_AUTHCID );
+       if ( conn->c_sasl_bind_mech.bv_len == ext_bv.bv_len
+               && ( strcasecmp( ext_bv.bv_val, conn->c_sasl_bind_mech.bv_val ) == 0 ) 
+                       && authcid[0] == '/' ) {
+               ext = 1;
+               xrealm = NULL;
+       } else {
+               xrealm = strchr( authcid, '@' );
+               if ( xrealm ) *xrealm++ = '\0';
+       }
+       rc = slap_sasl_getdn( conn, (char *)authcid, 0, xrealm ? xrealm : realm, &authcDN, FLAG_GETDN_AUTHCID );
+       if ( xrealm ) xrealm[-1] = '@';
        if( rc != LDAP_SUCCESS ) {
                *errstr = ldap_err2string( rc );
                return SASL_NOAUTHZ;
@@ -598,7 +618,14 @@ slap_sasl_authorize(
                *errstr = NULL;
                return SASL_OK;
        }
-       rc = slap_sasl_getdn( conn, (char *)authzid, realm, &authzDN, FLAG_GETDN_AUTHZID );
+       if ( ext ) {
+               xrealm = NULL;
+       } else {
+               xrealm = strchr( authzid, '@' );
+               if ( xrealm ) *xrealm++ = '\0';
+       }
+       rc = slap_sasl_getdn( conn, (char *)authzid, 0, xrealm ? xrealm : realm, &authzDN, FLAG_GETDN_AUTHZID );
+       if ( xrealm ) xrealm[-1] = '@';
        if( rc != LDAP_SUCCESS ) {
                ch_free( authcDN.bv_val );
                *errstr = ldap_err2string( rc );
@@ -1088,7 +1115,7 @@ int slap_sasl_bind(
                                NULL, "no SASL username", NULL, NULL );
 
                } else {
-                       rc = slap_sasl_getdn( conn, username, realm, edn, FLAG_GETDN_FINAL );
+                       rc = slap_sasl_getdn( conn, username, 0, realm, edn, FLAG_GETDN_FINAL );
 
                        if( rc == LDAP_SUCCESS ) {
                                sasl_ssf_t *ssf = NULL;
index fb82f181b35ebb3b7b97b09f5c5fa819080d48c0..85e9f2526fc379d8fc47d5b49dcf0c8cad9152e7 100644 (file)
@@ -3421,7 +3421,7 @@ char digit[] = "0123456789";
  */
 
 static struct berval *
-asn1_integer2str(ASN1_INTEGER *a)
+asn1_integer2str(ASN1_INTEGER *a, struct berval *bv)
 {
        char buf[256];
        char *p;
@@ -3477,35 +3477,17 @@ asn1_integer2str(ASN1_INTEGER *a)
                *--p = '-';
        }
 
-       return ber_bvstrdup(p);
+       return ber_str2bv( p, 0, 1, bv );
 }
 
 /* Get a DN in RFC2253 format from a X509_NAME internal struct */
-static struct berval *
-dn_openssl2ldap(X509_NAME *name)
+int
+dn_openssl2ldap(X509_NAME *name, struct berval *out)
 {
-       char issuer_dn[1024];
-       BIO *bio;
-
-       bio = BIO_new(BIO_s_mem());
-       if ( !bio ) {
-#ifdef NEW_LOGGING
-               LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
-                          "dn_openssl2ldap: error creating BIO_s_mem: %s\n",
-                          ERR_error_string(ERR_get_error(),NULL)));
-#else
-               Debug( LDAP_DEBUG_ARGS, "dn_openssl2ldap: "
-                      "error creating BIO: %s\n",
-                      ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
-#endif
-               return NULL;
-       }
-       X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
-
-       BIO_gets(bio, issuer_dn, 1024);
+       char buf[2048], *p;
 
-       BIO_free(bio);
-       return ber_bvstrdup(issuer_dn);
+       p = X509_NAME_oneline( name, buf, sizeof( buf ) );
+       return dnDCEnormalize( p, out );
 }
 
 /*
@@ -3519,9 +3501,8 @@ certificateExactConvert(
 {
        X509 *xcert;
        unsigned char *p = in->bv_val;
-       struct berval *serial;
-       struct berval *issuer_dn;
-       struct berval *bv_tmp;
+       struct berval serial;
+       struct berval issuer_dn;
 
        xcert = d2i_X509(NULL, &p, in->bv_len);
        if ( !xcert ) {
@@ -3537,39 +3518,27 @@ certificateExactConvert(
                return LDAP_INVALID_SYNTAX;
        }
 
-       serial = asn1_integer2str(xcert->cert_info->serialNumber);
-       if ( !serial ) {
+       if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) {
                X509_free(xcert);
                return LDAP_INVALID_SYNTAX;
        }
-       issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
-       if ( !issuer_dn ) {
+       if ( dn_openssl2ldap(X509_get_issuer_name(xcert), &issuer_dn ) != LDAP_SUCCESS ) {
                X509_free(xcert);
-               ber_bvfree(serial);
+               ber_memfree(serial.bv_val);
                return LDAP_INVALID_SYNTAX;
        }
-       /* Actually, dn_openssl2ldap returns in a normalized format, but
-          it is different from our normalized format */
-       bv_tmp = issuer_dn;
-       if ( dnNormalize(NULL, bv_tmp, &issuer_dn) != LDAP_SUCCESS ) {
-               X509_free(xcert);
-               ber_bvfree(serial);
-               ber_bvfree(bv_tmp);
-               return LDAP_INVALID_SYNTAX;
-       }
-       ber_bvfree(bv_tmp);
 
        X509_free(xcert);
 
-       out->bv_len = serial->bv_len + issuer_dn->bv_len + sizeof(" $ ");
+       out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ ");
        out->bv_val = ch_malloc(out->bv_len);
        p = out->bv_val;
-       AC_MEMCPY(p, serial->bv_val, serial->bv_len);
-       p += serial->bv_len;
+       AC_MEMCPY(p, serial.bv_val, serial.bv_len);
+       p += serial.bv_len;
        AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
        p += 3;
-       AC_MEMCPY(p, issuer_dn->bv_val, issuer_dn->bv_len);
-       p += issuer_dn->bv_len;
+       AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len);
+       p += issuer_dn.bv_len;
        *p++ = '\0';
 
 #ifdef NEW_LOGGING
@@ -3582,8 +3551,8 @@ certificateExactConvert(
                out->bv_val, NULL, NULL );
 #endif
 
-       ber_bvfree(serial);
-       ber_bvfree(issuer_dn);
+       ber_memfree(serial.bv_val);
+       ber_memfree(issuer_dn.bv_val);
 
        return LDAP_SUCCESS;
 }
@@ -3591,8 +3560,8 @@ certificateExactConvert(
 static int
 serial_and_issuer_parse(
        struct berval *assertion,
-       struct berval **serial,
-       struct berval **issuer_dn
+       struct berval *serial,
+       struct berval *issuer_dn
 )
 {
        char *begin;
@@ -3617,18 +3586,20 @@ serial_and_issuer_parse(
 
        bv.bv_len = end-begin+1;
        bv.bv_val = begin;
-       *serial = ber_dupbv(NULL, &bv);
+       ber_dupbv(serial, &bv);
 
        /* now extract the issuer, remember p was at the dollar sign */
-       begin = p+1;
-       end = assertion->bv_val+assertion->bv_len-1;
-       while (ASCII_SPACE(*begin))
-               begin++;
-       /* should we trim spaces at the end too? is it safe always? */
+       if ( issuer_dn ) {
+               begin = p+1;
+               end = assertion->bv_val+assertion->bv_len-1;
+               while (ASCII_SPACE(*begin))
+                       begin++;
+               /* should we trim spaces at the end too? is it safe always? */
 
-       bv.bv_len = end-begin+1;
-       bv.bv_val = begin;
-       dnNormalize( NULL, &bv, issuer_dn );
+               bv.bv_len = end-begin+1;
+               bv.bv_val = begin;
+               dnNormalize2( NULL, &bv, issuer_dn );
+       }
 
        return LDAP_SUCCESS;
 }
@@ -3644,10 +3615,10 @@ certificateExactMatch(
 {
        X509 *xcert;
        unsigned char *p = value->bv_val;
-       struct berval *serial;
-       struct berval *issuer_dn;
-       struct berval *asserted_serial;
-       struct berval *asserted_issuer_dn;
+       struct berval serial;
+       struct berval issuer_dn;
+       struct berval asserted_serial;
+       struct berval asserted_issuer_dn;
        int ret;
 
        xcert = d2i_X509(NULL, &p, value->bv_len);
@@ -3664,8 +3635,8 @@ certificateExactMatch(
                return LDAP_INVALID_SYNTAX;
        }
 
-       serial = asn1_integer2str(xcert->cert_info->serialNumber);
-       issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
+       asn1_integer2str(xcert->cert_info->serialNumber, &serial);
+       dn_openssl2ldap(X509_get_issuer_name(xcert), &issuer_dn);
 
        X509_free(xcert);
 
@@ -3678,8 +3649,8 @@ certificateExactMatch(
                flags,
                slap_schema.si_syn_integer,
                slap_schema.si_mr_integerMatch,
-               serial,
-               asserted_serial);
+               &serial,
+               &asserted_serial);
        if ( ret == LDAP_SUCCESS ) {
                if ( *matchp == 0 ) {
                        /* We need to normalize everything for dnMatch */
@@ -3688,29 +3659,29 @@ certificateExactMatch(
                                flags,
                                slap_schema.si_syn_distinguishedName,
                                slap_schema.si_mr_distinguishedNameMatch,
-                               issuer_dn,
-                               asserted_issuer_dn);
+                               &issuer_dn,
+                               &asserted_issuer_dn);
                }
        }
 
 #ifdef NEW_LOGGING
        LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
                   "certificateExactMatch: %d\n  %s $ %s\n       %s $   %s\n",
-                  *matchp, serial->bv_val, issuer_dn->bv_val,
-                  asserted_serial->bv_val, asserted_issuer_dn->bv_val));
+                  *matchp, serial.bv_val, issuer_dn.bv_val,
+                  asserted_serial.bv_val, asserted_issuer_dn.bv_val));
 #else
        Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
                "%d\n\t\"%s $ %s\"\n",
-               *matchp, serial->bv_val, issuer_dn->bv_val );
+               *matchp, serial.bv_val, issuer_dn.bv_val );
        Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
-               asserted_serial->bv_val, asserted_issuer_dn->bv_val,
+               asserted_serial.bv_val, asserted_issuer_dn.bv_val,
                NULL );
 #endif
 
-       ber_bvfree(serial);
-       ber_bvfree(issuer_dn);
-       ber_bvfree(asserted_serial);
-       ber_bvfree(asserted_issuer_dn);
+       ber_memfree(serial.bv_val);
+       ber_memfree(issuer_dn.bv_val);
+       ber_memfree(asserted_serial.bv_val);
+       ber_memfree(asserted_issuer_dn.bv_val);
 
        return ret;
 }
@@ -3733,7 +3704,7 @@ static int certificateExactIndexer(
        BerVarray keys;
        X509 *xcert;
        unsigned char *p;
-       struct berval serial;
+       struct berval serial;
 
        /* we should have at least one value at this point */
        assert( values != NULL && values[0].bv_val != NULL );
@@ -3762,12 +3733,12 @@ static int certificateExactIndexer(
                        return LDAP_INVALID_SYNTAX;
                }
 
-               serial = asn1_integer2str(xcert->cert_info->serialNumber);
+               asn1_integer2str(xcert->cert_info->serialNumber, &serial);
                X509_free(xcert);
                integerNormalize( slap_schema.si_syn_integer,
-                                 serial,
+                                 &serial,
                                  &keys[i] );
-               ber_bvfree(serial);
+               ber_memfree(serial.bv_val);
 #ifdef NEW_LOGGING
                LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
                           "certificateExactIndexer: returning: %s\n",
@@ -3797,20 +3768,18 @@ static int certificateExactFilter(
        BerVarray *keysp )
 {
        BerVarray keys;
-       struct berval *asserted_serial;
-       struct berval *asserted_issuer_dn;
+       struct berval asserted_serial;
 
        serial_and_issuer_parse(assertValue,
                                &asserted_serial,
-                               &asserted_issuer_dn);
+                               NULL);
 
        keys = ch_malloc( sizeof( struct berval ) * 2 );
-       integerNormalize( syntax, asserted_serial, &keys[0] );
+       integerNormalize( syntax, &asserted_serial, &keys[0] );
        keys[1].bv_val = NULL;
        *keysp = keys;
 
-       ber_bvfree(asserted_serial);
-       ber_bvfree(asserted_issuer_dn);
+       ber_memfree(asserted_serial.bv_val);
        return LDAP_SUCCESS;
 }
 #endif