]> git.sur5r.net Git - openldap/commitdiff
Modify password code such that backend end routine calls into
authorKurt Zeilenga <kurt@openldap.org>
Thu, 9 Dec 1999 21:30:32 +0000 (21:30 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Thu, 9 Dec 1999 21:30:32 +0000 (21:30 +0000)
frontend to complete parsing of extended op reqdata.
Modify password extended operation to allow optional id (DN)
entry to change (not tested).  Also, provide room to allow
server side password generation (not implemented).  Added optional old
password field to support proxying (not implemented).
Need to implement replog() support.

clients/tools/ldappasswd.c
libraries/liblber/decode.c
servers/slapd/back-ldbm/passwd.c
servers/slapd/passwd.c
servers/slapd/proto-slap.h

index d87730bf986411d6835e812ce0384c7928ecb73f..5e9737347976ea81bb7e03cbe0fd4aa90e5e129e 100644 (file)
@@ -27,8 +27,8 @@ static void
 usage(const char *s)
 {
        fprintf(stderr,
-               "Usage: %s [options]\n"
-               "  -D binddn\tbind dn\tREQUIRED\n"
+               "Usage: %s [options] dn\n"
+               "  -D binddn\tbind dn\n"
                "  -d level\tdebugging level\n"
                "  -h host\tldap server (default: localhost)\n"
                "  -n\t\tmake no modifications\n"
@@ -46,6 +46,7 @@ int
 main( int argc, char *argv[] )
 {
        int rc;
+       char    *dn = NULL;
        char    *binddn = NULL;
        char    *bindpw = NULL;
        char    *ldaphost = NULL;
@@ -119,6 +120,12 @@ main( int argc, char *argv[] )
                }
        }
 
+       if( argc - optind != 1 ) {
+               usage( argv[0] );
+       } 
+
+       dn = strdup( argv[optind] );
+
        if( newpw == NULL ) {
                /* prompt for new password */
                char *cknewpw;
@@ -132,8 +139,8 @@ main( int argc, char *argv[] )
        }
 
        if( binddn == NULL ) {
-               fprintf( stderr, "no bind DN specified\n" );
-               return EXIT_FAILURE;
+               binddn = dn;
+               dn = NULL;
        }
 
        /* handle bind password */
@@ -188,9 +195,19 @@ main( int argc, char *argv[] )
                return EXIT_FAILURE;
        }
 
-       ber_printf( ber, "{es}",
-               (ber_int_t) 0,
-               newpw );
+       if( dn != NULL ) {
+               ber_printf( ber, "{tsts}",
+                       LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, dn,
+                       LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
+
+               free(dn);
+
+       } else {
+               ber_printf( ber, "{ts}",
+                       LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
+       }
+
+       free(newpw);
 
        rc = ber_flatten( ber, &bv );
 
index 4af3a38d514f3fc5b9d2f12a62dab5ea9435d8f0..57d33b9e54ed02440b08c28ba561a6743d305e64 100644 (file)
@@ -96,6 +96,8 @@ ber_skip_tag( BerElement *ber, ber_len_t *len )
         *      2) primitive encodings used whenever possible
         */
 
+       *len = 0;
+
        /*
         * First, we read the tag.
         */
@@ -110,8 +112,6 @@ ber_skip_tag( BerElement *ber, ber_len_t *len )
         * greater than what we can hold in a ber_len_t.
         */
 
-       *len = 0;
-
        if ( ber_read( ber, (char *) &lc, 1 ) != 1 )
                return( LBER_DEFAULT );
 
@@ -149,6 +149,8 @@ ber_peek_tag(
        assert( ber_in != NULL );
        assert( BER_VALID( ber_in ) );
 
+       *len = 0;
+
        ber = ber_dup( ber_in );
 
        if( ber == NULL ) {
index 355405bbda2890335bdc1d974e83f7407bd7147e..c8980768b63ac50ab231a7bc87e3d9ee77ac47d8 100644 (file)
@@ -28,30 +28,61 @@ ldbm_back_exop_passwd(
 )
 {
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
-       int rc = LDAP_OPERATIONS_ERROR;
-       Entry *e;
-       struct berval *cred = NULL;
+       int rc;
+       Entry *e = NULL;
+       struct berval *hash = NULL;
+
+       struct berval *id = NULL;
+       struct berval *new = NULL;
+
+       char *dn;
 
        assert( oid != NULL );
        assert( strcmp( LDAP_EXOP_X_MODIFY_PASSWD, oid ) == 0 );
 
-       Debug( LDAP_DEBUG_ARGS, "==> ldbm_back_exop_passwd: dn: %s\n",
-               op->o_dn, 0, 0 );
+       rc = slap_passwd_parse( reqdata,
+               &id, NULL, &new, text );
+
+       Debug( LDAP_DEBUG_ARGS, "==> ldbm_back_exop_passwd: \"%s\"\n",
+               id ? id->bv_val : "", 0, 0 );
 
+       if( rc != LDAP_SUCCESS ) {
+               goto done;
+       }
 
-       cred = slap_passwd_generate( reqdata );
-       if( cred == NULL || cred->bv_len == 0 ) {
+       if( new == NULL || new->bv_len == 0 ) {
+               *text = ch_strdup("no password provided");
+               rc = LDAP_OPERATIONS_ERROR;
+               goto done;
+       }
+
+       hash = slap_passwd_generate( new );
+
+       if( hash == NULL || hash->bv_len == 0 ) {
                *text = ch_strdup("password generation failed");
-               return LDAP_OPERATIONS_ERROR;
+               rc = LDAP_OPERATIONS_ERROR;
+               goto done;
        }
 
-       Debug( LDAP_DEBUG_TRACE, "passwd: %s\n", cred->bv_val, 0, 0 );
+       dn = id ? id->bv_val : op->o_dn;
 
-       e = dn2entry_w( be, op->o_ndn, NULL );
+       Debug( LDAP_DEBUG_TRACE, "passwd: \"%s\"%s\n",
+               dn, id ? " (proxy)" : "", 0 );
+
+       if( dn == NULL || dn[0] == NULL ) {
+               *text = ch_strdup("No password is associated with the Root DSE");
+               rc = LDAP_OPERATIONS_ERROR;
+               goto done;
+       }
+
+       e = dn2entry_w( be,
+               id ? id->bv_val : op->o_dn,
+               NULL );
 
        if( e == NULL ) {
                *text = ch_strdup("could not locate authorization entry");
-               return LDAP_OPERATIONS_ERROR;
+               rc = LDAP_OPERATIONS_ERROR;
+               goto done;
        }
 
        if( ! access_allowed( be, conn, op, e, "entry", NULL, ACL_WRITE ) ) {
@@ -67,6 +98,8 @@ ldbm_back_exop_passwd(
                goto done;
        }
 
+       rc = LDAP_OPERATIONS_ERROR;
+
        if( is_entry_referral( e ) ) {
                /* entry is an referral, don't allow operation */
                *text = ch_strdup("authorization entry is referral");
@@ -77,7 +110,7 @@ ldbm_back_exop_passwd(
                LDAPModList ml;
                struct berval *vals[2];
 
-               vals[0] = cred;
+               vals[0] = hash;
                vals[1] = NULL;
 
                ml.ml_type = ch_strdup("userPassword");
@@ -99,10 +132,20 @@ ldbm_back_exop_passwd(
        }
        
 done:
-       cache_return_entry_w( &li->li_cache, e );
+       if( e != NULL ) {
+               cache_return_entry_w( &li->li_cache, e );
+       }
+
+       if( id != NULL ) {
+               ber_bvfree( id );
+       }
+
+       if( new != NULL ) {
+               ber_bvfree( new );
+       }
 
-       if( cred != NULL ) {
-               ber_bvfree( cred );
+       if( hash != NULL ) {
+               ber_bvfree( hash );
        }
 
        return rc;
index 1152e81b0fb4a235af391b53d50880f7c15ef790..bfeec38bf92a4ebb2f994da9ca1de60a0fa02c44 100644 (file)
@@ -24,9 +24,6 @@ static int passwd_main(
        struct berval *reqdata, struct berval **rspdata, char **text )
 {
        int rc;
-       BerElement *ber;
-       struct berval *cred = NULL;
-       ber_int_t type;
 
        assert( oid != NULL );
        assert( strcmp( LDAP_EXOP_X_MODIFY_PASSWD, oid ) == 0 );
@@ -37,50 +34,144 @@ static int passwd_main(
        }
 
        if( reqdata == NULL || reqdata->bv_len == 0 ) {
-               *text = ch_strdup("data missing");
+               *text = ch_strdup("request data missing");
                return LDAP_PROTOCOL_ERROR;
        }
 
+       if( conn->c_authz_backend != NULL &&
+               conn->c_authz_backend->be_extended )
+       {
+               rc = conn->c_authz_backend->be_extended(
+                       conn->c_authz_backend,
+                       conn, op, oid, reqdata, rspdata, text );
+
+       } else {
+               *text = ch_strdup("operation not supported for current user");
+               rc = LDAP_UNWILLING_TO_PERFORM;
+       }
+
+       return rc;
+}
+
+int slap_passwd_parse( struct berval *reqdata,
+       struct berval **id,
+       struct berval **old,
+       struct berval **new,
+       char **text )
+{
+       int rc = LDAP_SUCCESS;
+       ber_tag_t tag;
+       ber_len_t len;
+       BerElement *ber;
+
+       assert( reqdata != NULL );
+
        ber = ber_init( reqdata );
 
        if( ber == NULL ) {
+               Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ber_init failed\n",
+                       0, 0, 0 );
                *text = ch_strdup("password decoding error");
                return LDAP_PROTOCOL_ERROR;
        }
 
-       rc = ber_scanf(ber, "{iO}", &type, &cred );
-       ber_free( ber, 1 );
+       tag = ber_scanf(ber, "{" /*}*/);
 
-       if( rc == LBER_ERROR ) {
-               *text = ch_strdup("data decoding error");
-               return LDAP_PROTOCOL_ERROR;
+       if( tag == LBER_ERROR ) {
+               goto decoding_error;
        }
 
-       if( cred == NULL || cred->bv_len == 0 ) {
-               *text = ch_strdup("password missing");
-               return LDAP_PROTOCOL_ERROR;
+       tag = ber_peek_tag( ber, &len );
+
+       if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID ) {
+               if( id == NULL ) {
+                       Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID not allowed.\n",
+                               0, 0, 0 );
+                       *text = "user must change own password";
+                       rc = LDAP_UNWILLING_TO_PERFORM;
+                       goto done;
+               }
+
+               tag = ber_scanf( ber, "O", id );
+
+               if( tag == LBER_ERROR ) {
+                       Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
+                               0, 0, 0 );
+                       goto decoding_error;
+               }
+
+               tag = ber_peek_tag( ber, &len);
        }
 
-       if( type != 0 ) {
-               ber_bvfree( cred );
-               *text = ch_strdup("password type unknown");
-               return LDAP_PROTOCOL_ERROR;
+       if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_OLD ) {
+               if( old == NULL ) {
+                       Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD not allowed.\n",
+                               0, 0, 0 );
+                       *text = "use bind to verify old password";
+                       rc = LDAP_UNWILLING_TO_PERFORM;
+                       goto done;
+               }
+
+               tag = ber_scanf( ber, "O", old );
+
+               if( tag == LBER_ERROR ) {
+                       Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: ID parse failed.\n",
+                               0, 0, 0 );
+                       goto decoding_error;
+               }
+
+               tag = ber_peek_tag( ber, &len);
        }
 
-       if( conn->c_authz_backend != NULL &&
-               conn->c_authz_backend->be_extended )
-       {
-               rc = conn->c_authz_backend->be_extended(
-                       conn->c_authz_backend,
-                       conn, op,
-                       oid, cred, rspdata, text );
+       if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW ) {
+               if( new == NULL ) {
+                       Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: NEW not allowed.\n",
+                               0, 0, 0 );
+                       *text = "user specified passwords disallowed";
+                       rc = LDAP_UNWILLING_TO_PERFORM;
+                       goto done;
+               }
 
-       } else {
-               *text = ch_strdup("operation not supported for current user");
-               rc = LDAP_UNWILLING_TO_PERFORM;
+               tag = ber_scanf( ber, "O", new );
+
+               if( tag == LBER_ERROR ) {
+                       Debug( LDAP_DEBUG_TRACE, "slap_passwd_parse: OLD parse failed.\n",
+                               0, 0, 0 );
+                       goto decoding_error;
+               }
+
+               tag = ber_peek_tag( ber, &len );
+       }
+
+       if( len != 0 ) {
+decoding_error:
+               Debug( LDAP_DEBUG_TRACE,
+                       "slap_passwd_parse: decoding error, len=%ld\n",
+                       (long) len, 0, 0 );
+
+               *text = ch_strdup("data decoding error");
+               rc = LDAP_PROTOCOL_ERROR;
        }
 
-       ber_bvfree( cred );
+done:
+       if( rc != LDAP_SUCCESS ) {
+               if( id != NULL ) {
+                       ber_bvfree( *id );
+                       *id = NULL;
+               }
+
+               if( old != NULL ) {
+                       ber_bvfree( *old );
+                       *old = NULL;
+               }
+
+               if( new != NULL ) {
+                       ber_bvfree( *new );
+                       *new = NULL;
+               }
+       }
+
+       ber_free( ber, 1 );
        return rc;
 }
 
index a07804d754b136dbab481edf77e1ca1096739c9e..07ea38c3156141ffad38d1e1728f6f9110fb88fb 100644 (file)
@@ -480,12 +480,22 @@ LIBSLAPD_F (void) slap_init_user LDAP_P(( char *username, char *groupname ));
 /*
  * passwd.c
  */
+LIBSLAPD_F (int) slap_passwd_init( void );
+
 LIBSLAPD_F (int) slap_passwd_check(
        Attribute                       *attr,
        struct berval           *cred );
+
 LIBSLAPD_F (struct berval *) slap_passwd_generate(
        struct berval           *cred );
-LIBSLAPD_F (int) slap_passwd_init( void );
+
+LIBSLAPD_F (int) slap_passwd_parse(
+       struct berval *reqdata,
+       struct berval **id,
+       struct berval **old,
+       struct berval **new,
+       char **text );
+
 /*
  * kerberos.c
  */