diff --git a/doc/man/man5/slapd.conf.5 b/doc/man/man5/slapd.conf.5 index 85ce15abcc..d61e5f7533 100644 --- a/doc/man/man5/slapd.conf.5 +++ b/doc/man/man5/slapd.conf.5 @@ -302,7 +302,7 @@ form .RS .RS .TP -.B uid=[+realm=][,cn=],cn=AUTHZ +.B uid=[,cn=][,cn=],cn=AUTHZ .RE This SASL name is then compared against the @@ -345,7 +345,7 @@ appear in the file, stopping at the first successful match. .B Caution: Because the plus sign + is a character recognized by the regular expression engine, and it will appear in SASL names that include a REALM, be careful to escape the -plus sign with a double backslash \\\\+ to remove the character's special meaning. +plus sign with a backslash \\+ to remove the character's special meaning. .RE .TP .B sasl-secprops diff --git a/servers/slapd/sasl.c b/servers/slapd/sasl.c index 15ff5e9c6e..250b2ab5ac 100644 --- a/servers/slapd/sasl.c +++ b/servers/slapd/sasl.c @@ -97,8 +97,16 @@ slap_sasl_authorize( authzid ? authzid : "" ); if ( authzid == NULL || *authzid == '\0' || + ( authzid[0] == 'u' && authzid[1] == ':' && + strcmp( authcid, &authzid[2] ) == 0 ) || strcmp( authcid, authzid ) == 0 ) { + /* authzid is: + * empty + * u:authcid + * authcid + */ + size_t len = sizeof("u:") + strlen( authcid ); cuser = ch_malloc( len ); @@ -116,12 +124,18 @@ slap_sasl_authorize( } rc = slap_sasl_authorized( conn, authcid, authzid ); - Debug( LDAP_DEBUG_TRACE, "SASL Authorization returned %d\n", rc,0,0); if( rc ) { + Debug( LDAP_DEBUG_TRACE, "SASL Authorize [conn=%ld]: " + " authorization disallowed (%d)\n", + (long) (conn ? conn->c_connid : -1), rc, 0 ); *errstr = "not authorized"; return SASL_NOAUTHZ; } + Debug( LDAP_DEBUG_TRACE, "SASL Authorize [conn=%ld]: " + " authorization allowed\n", + (long) (conn ? conn->c_connid : -1), 0, 0 ); + cuser = ch_strdup( authzid ); dn_normalize( cuser ); *errstr = NULL; @@ -465,10 +479,9 @@ int slap_sasl_bind( 0, 0, 0); } else if ( username[0] == 'u' && username[1] == ':' - && username[2] != '\0' - && strpbrk( &username[2], "+=,;\"\\ \t") == NULL ) + && username[2] != '\0' ) { - *edn = ch_malloc( sizeof( "uid= + realm=" ) + *edn = ch_malloc( sizeof( "uid=,cn=" ) + strlen( &username[2] ) + ( realm ? strlen( realm ) : 0 ) ); @@ -476,13 +489,52 @@ int slap_sasl_bind( strcat( *edn, &username[2] ); if( realm && *realm ) { - strcat( *edn, " + realm=" ); + strcat( *edn, ",cn=" ); strcat( *edn, realm ); } - Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: authzdn: \"%s\"\n", - *edn, 0, 0); + if( dn_normalize( *edn ) == NULL ) { + Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: " + "authzid (\"%s\") to authzdn failed: \"%s\"\n", + username, *edn, 0); + ch_free( *edn ); + *edn = NULL; + rc = LDAP_INAPPROPRIATE_AUTH; + errstr = "could not form a valid DN from authzid"; + } else { + Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: " + "authzdn: \"%s\"\n", + *edn, 0, 0); + } + + } else if ( username[0] == 'd' && username[1] == 'n' + && username[2] != ':' && username[3] != '\0' ) + { + *edn = ch_strdup( &username[3] ); + + if( dn_normalize( *edn ) == NULL ) { + Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: " + "authzid (\"%s\") to authzdn failed: \"%s\"\n", + username, *edn, 0); + + ch_free( *edn ); + *edn = NULL; + rc = LDAP_INAPPROPRIATE_AUTH; + errstr = "could not form a valid DN from authzid"; + + } else { + Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: " + "authzdn: \"%s\"\n", + *edn, 0, 0); + } + + } else { + Debug(LDAP_DEBUG_TRACE, "<== slap_sasl_bind: " + "authzid (\"%s\") inappropriate form\n", + username, 0, 0); + rc = LDAP_INAPPROPRIATE_AUTH; + errstr = "inappropriate authorization identity form"; } if( rc == LDAP_SUCCESS ) { diff --git a/servers/slapd/saslauthz.c b/servers/slapd/saslauthz.c index 48a3bb7a05..9599f8a973 100644 --- a/servers/slapd/saslauthz.c +++ b/servers/slapd/saslauthz.c @@ -251,7 +251,7 @@ char *slap_sasl_regexp( char *saslname ) /* - * Given a SASL name (e.g. "UID=name+REALM=company,cn=GSSAPI,cn=AUTHZ") + * Given a SASL name (e.g. "UID=name+cn=REALM,cn=MECH,cn=AUTHZ") * return the LDAP DN to which it matches. The SASL regexp rules in the config * file turn the SASL name into an LDAP URI. If the URI is just a DN (or a * search with scope=base), just return the URI (or its searchbase). Otherwise @@ -504,7 +504,7 @@ int slap_sasl_authorized( Connection *conn, sasl_getprop( conn->c_sasl_context, SASL_REALM, (void **)&realm ); /* Allocate space */ - rc = strlen("uid=+realm=,cn=,cn=AUTHZ "); + rc = strlen("uid=,cn=,cn=,cn=AUTHZ "); if ( realm ) rc += strlen( realm ); if ( authcid ) rc += strlen( authcid ); rc += strlen( conn->c_sasl_bind_mech ); @@ -516,7 +516,7 @@ int slap_sasl_authorized( Connection *conn, if ( authcid ) rc += sprintf( saslname+rc, "%sUID=%s", rc?",":"", authcid); if ( realm ) - rc += sprintf( saslname+rc, "%sREALM=%s", rc?"+":"", realm); + rc += sprintf( saslname+rc, "%sCN=%s", rc?",":"", realm); if ( conn->c_sasl_bind_mech ) rc += sprintf( saslname+rc, "%sCN=%s", rc?",":"", conn->c_sasl_bind_mech);