]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/sasl.c
Added op->o_is_auth_check; use ACL_AUTH instead of ACL_SEARCH/ACL_READ
[openldap] / servers / slapd / sasl.c
index c97c144321a76faea1c861e18cf10d7d85a213c2..518db4ec92b08b6362daedab1ade8d101d323956 100644 (file)
@@ -1,6 +1,6 @@
 /* $OpenLDAP$ */
 /*
- * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
  */
 
@@ -425,7 +425,7 @@ slap_auxprop_lookup(
                Backend *be;
                Operation op = {0};
                slap_callback cb = { slap_cb_null_response,
-                       slap_cb_null_sresult, sasl_ap_lookup, NULL };
+                       slap_cb_null_sresult, sasl_ap_lookup, slap_cb_null_sreference, NULL };
 
                cb.sc_private = &sl;
 
@@ -438,6 +438,7 @@ slap_auxprop_lookup(
                        op.o_callback = &cb;
                        op.o_time = slap_get_time();
                        op.o_do_not_cache = 1;
+                       op.o_is_auth_check = 1;
                        op.o_threadctx = conn->c_sasl_bindop->o_threadctx;
 
                        (*be->be_search)( be, conn, &op, NULL, &dn,
@@ -551,7 +552,7 @@ slap_sasl_checkpass(
        if ( be && be->be_search ) {
                Operation op = {0};
                slap_callback cb = { slap_cb_null_response,
-                       slap_cb_null_sresult, sasl_cb_checkpass, NULL };
+                       slap_cb_null_sresult, sasl_cb_checkpass, slap_cb_null_sreference, NULL };
 
                ci.cred.bv_val = (char *)pass;
                ci.cred.bv_len = passlen;
@@ -563,6 +564,7 @@ slap_sasl_checkpass(
                op.o_callback = &cb;
                op.o_time = slap_get_time();
                op.o_do_not_cache = 1;
+               op.o_is_auth_check = 1;
                op.o_threadctx = conn->c_sasl_bindop->o_threadctx;
 
                (*be->be_search)( be, conn, &op, NULL, &dn,
@@ -610,13 +612,13 @@ slap_sasl_canonicalize(
        LDAP_LOG( TRANSPORT, ENTRY, 
                "slap_sasl_canonicalize: conn %d %s=\"%s\"\n",
                conn ? conn->c_connid : -1,
-               (flags & SASL_CU_AUTHID) ? "authcid" : "authzid", in ? in : "<empty>");
+               (flags & SASL_CU_AUTHID) ? "authcid" : "authzid",
+               in ? in : "<empty>");
 #else
-       Debug( LDAP_DEBUG_ARGS, "SASL Canonicalize [conn=%ld]: "
-               "%s=\"%s\"\n",
-                       conn ? conn->c_connid : -1,
-                       (flags & SASL_CU_AUTHID) ? "authcid" : "authzid",
-                       in ? in : "<empty>" );
+       Debug( LDAP_DEBUG_ARGS, "SASL Canonicalize [conn=%ld]: %s=\"%s\"\n",
+               conn ? conn->c_connid : -1,
+               (flags & SASL_CU_AUTHID) ? "authcid" : "authzid",
+               in ? in : "<empty>");
 #endif
 
        /* If name is too big, just truncate. We don't care, we're
@@ -656,8 +658,12 @@ slap_sasl_canonicalize(
         * the authcID temporarily in conn->c_sasl_dn. We necessarily
         * finish Canonicalizing before Authorizing, so there is no
         * conflict with slap_sasl_authorize's use of this temp var.
+        *
+        * The SASL EXTERNAL mech is backwards from all the other mechs,
+        * it does authzID before the authcID. If we see that authzID
+        * has already been done, don't do anything special with authcID.
         */
-       if ( flags == SASL_CU_AUTHID ) {
+       if ( flags == SASL_CU_AUTHID && !auxvals[PROP_AUTHZ].values ) {
                conn->c_sasl_dn.bv_val = (char *) in;
        } else if ( flags == SASL_CU_AUTHZID && conn->c_sasl_dn.bv_val ) {
                rc = strcmp( in, conn->c_sasl_dn.bv_val );
@@ -681,14 +687,16 @@ slap_sasl_canonicalize(
 #ifdef NEW_LOGGING
        LDAP_LOG( TRANSPORT, ENTRY, 
                "slap_sasl_canonicalize: conn %d %s=\"%s\"\n",
-               conn ? conn->c_connid : -1, names[0]+1, dn.bv_val );
+               conn ? conn->c_connid : -1, names[0]+1,
+               dn.bv_val ? dn.bv_val : "<EMPTY>" );
 #else
-       Debug( LDAP_DEBUG_ARGS, "SASL Canonicalize [conn=%ld]: "
-               "%s=\"%s\"\n",
-                       conn ? conn->c_connid : -1,
-                       names[0]+1, dn.bv_val );
+       Debug( LDAP_DEBUG_ARGS, "SASL Canonicalize [conn=%ld]: %s=\"%s\"\n",
+               conn ? conn->c_connid : -1, names[0]+1,
+               dn.bv_val ? dn.bv_val : "<EMPTY>" );
 #endif
-done:  AC_MEMCPY( out, in, inlen );
+
+done:
+       AC_MEMCPY( out, in, inlen );
        out[inlen] = '\0';
 
        *out_len = inlen;
@@ -736,7 +744,7 @@ slap_sasl_authorize(
        /* Nothing to do if no authzID was given */
        if ( !auxvals[1].name || !auxvals[1].values ) {
                conn->c_sasl_dn = authcDN;
-               return SASL_OK;
+               goto ok;
        }
        
        AC_MEMCPY( &authzDN, auxvals[1].values[0], sizeof(authzDN) );
@@ -760,6 +768,13 @@ slap_sasl_authorize(
        }
 
        conn->c_sasl_dn = authzDN;
+ok:
+       if (conn->c_sasl_bindop) {
+               Statslog( LDAP_DEBUG_STATS,
+                       "conn=%lu op=%lu BIND authcid=\"%s\"\n",
+                       conn->c_connid, conn->c_sasl_bindop->o_opid, 
+                       auth_identity, 0, 0);
+       }
 
 #ifdef NEW_LOGGING
        LDAP_LOG( TRANSPORT, ENTRY, 
@@ -839,8 +854,7 @@ slap_sasl_authorize(
 #endif
 
                conn->c_sasl_dn = authcDN;
-               *errstr = NULL;
-               return SASL_OK;
+               goto ok;
        }
        rc = slap_sasl_getdn( conn, (char *)authzid, 0, realm,
                &authzDN, SLAP_GETDN_AUTHZID );
@@ -867,7 +881,9 @@ slap_sasl_authorize(
                ch_free( authzDN.bv_val );
                return SASL_NOAUTHZ;
        }
+       conn->c_sasl_dn = authzDN;
 
+ok:
 #ifdef NEW_LOGGING
        LDAP_LOG( TRANSPORT, RESULTS, 
                "slap_sasl_authorize: conn %d authorization allowed\n",
@@ -878,7 +894,13 @@ slap_sasl_authorize(
                (long) (conn ? conn->c_connid : -1), 0, 0 );
 #endif
 
-       conn->c_sasl_dn = authzDN;
+       if (conn->c_sasl_bindop) {
+               Statslog( LDAP_DEBUG_STATS,
+                       "conn=%lu op=%lu BIND authcid=\"%s\"\n",
+                       conn->c_connid, conn->c_sasl_bindop->o_opid, 
+                       authcid, 0, 0);
+       }
+
        *errstr = NULL;
        return SASL_OK;
 }
@@ -1416,7 +1438,7 @@ int
 slap_sasl_setpass(
        Connection      *conn,
        Operation       *op,
-       const char      *reqoid,
+       struct berval   *reqoid,
        struct berval   *reqdata,
        char            **rspoid,
        struct berval   **rspdata,
@@ -1429,7 +1451,7 @@ slap_sasl_setpass(
        struct berval old = { 0, NULL };
 
        assert( reqoid != NULL );
-       assert( strcmp( LDAP_EXOP_MODIFY_PASSWD, reqoid ) == 0 );
+       assert( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, reqoid ) == 0 );
 
        rc = sasl_getprop( conn->c_sasl_context, SASL_USERNAME,
                (SASL_CONST void **)&id.bv_val );
@@ -1508,8 +1530,9 @@ done:
    -Howard Chu, Symas Corp.
 */
 
-#define        SET_DN  1
-#define        SET_U   2
+#define SET_NONE       0
+#define        SET_DN          1
+#define        SET_U           2
 
 static struct berval ext_bv = BER_BVC( "EXTERNAL" );
 
@@ -1517,16 +1540,16 @@ int slap_sasl_getdn( Connection *conn, char *id, int len,
        char *user_realm, struct berval *dn, int flags )
 {
        char *c1;
-       int rc, is_dn = 0, do_norm = 1;
+       int rc, is_dn = SET_NONE, do_norm = 1;
        struct berval dn2;
 
 #ifdef NEW_LOGGING
        LDAP_LOG( TRANSPORT, ENTRY, 
-               "slap_sasl_getdn: conn %d id=%s\n",
-               conn ? conn->c_connid : -1, id ? (*id ? id : "<empty>") : "NULL", 0 );
+               "slap_sasl_getdn: conn %d id=%s [len=%d]\n",
+               conn ? conn->c_connid : -1, id ? (*id ? id : "<empty>") : "NULL", len );
 #else
-       Debug( LDAP_DEBUG_ARGS, "slap_sasl_getdn: id=%s\n", 
-      id?(*id?id:"<empty>"):"NULL",0,0 );
+       Debug( LDAP_DEBUG_ARGS, "slap_sasl_getdn: id=%s [len=%d]\n", 
+               id ? ( *id ? id : "<empty>" ) : "NULL", len, 0 );
 #endif
 
        dn->bv_val = NULL;
@@ -1550,26 +1573,22 @@ int slap_sasl_getdn( Connection *conn, char *id, int len,
         * is already normalized, so copy it and skip normalization.
         */
        if( flags & SLAP_GETDN_AUTHCID ) {
-#ifdef HAVE_TLS
-               if( conn->c_is_tls &&
-                       conn->c_sasl_bind_mech.bv_len == ext_bv.bv_len &&
+               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 )
                {
-                       /* X.509 DN is already normalized */
+                       /* EXTERNAL DNs are already normalized */
                        do_norm = 0;
                        is_dn = SET_DN;
                        ber_str2bv( id, len, 1, dn );
 
-               } else
-#endif
-               {
+               } else {
                        /* convert to u:<username> form */
                        is_dn = SET_U;
                        dn->bv_val = id;
                        dn->bv_len = len;
                }
        }
-       if( !is_dn ) {
+       if( is_dn == SET_NONE ) {
                if( !strncasecmp( id, "u:", sizeof("u:")-1 )) {
                        is_dn = SET_U;
                        dn->bv_val = id+2;
@@ -1582,7 +1601,7 @@ int slap_sasl_getdn( Connection *conn, char *id, int len,
        }
 
        /* No other possibilities from here */
-       if( !is_dn ) {
+       if( is_dn == SET_NONE ) {
                dn->bv_val = NULL;
                dn->bv_len = 0;
                return( LDAP_INAPPROPRIATE_AUTH );
@@ -1644,6 +1663,13 @@ int slap_sasl_getdn( Connection *conn, char *id, int len,
 #else
                Debug( LDAP_DEBUG_TRACE, "getdn: u:id converted to %s\n", dn->bv_val,0,0 );
 #endif
+       } else {
+               
+               /* Dup the DN in any case, so we don't risk 
+                * leaks or dangling pointers later,
+                * and the DN value is '\0' terminated */
+               ber_dupbv( &dn2, dn );
+               dn->bv_val = dn2.bv_val;
        }
 
        /* All strings are in DN form now. Normalize if needed. */
@@ -1651,8 +1677,7 @@ int slap_sasl_getdn( Connection *conn, char *id, int len,
                rc = dnNormalize2( NULL, dn, &dn2 );
 
                /* User DNs were constructed above and must be freed now */
-               if ( is_dn == SET_U )
-                       ch_free( dn->bv_val );
+               ch_free( dn->bv_val );
 
                if ( rc != LDAP_SUCCESS ) {
                        dn->bv_val = NULL;