]> git.sur5r.net Git - openldap/commitdiff
Add ppolicy_hash_cleartext config keyword, hash Adds as well as Modifies.
authorHoward Chu <hyc@openldap.org>
Thu, 7 Oct 2004 04:07:17 +0000 (04:07 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 7 Oct 2004 04:07:17 +0000 (04:07 +0000)
Changed check_pw_quality callback to pass entry's Attributes in final arg.

doc/man/man5/slapo-ppolicy.5
servers/slapd/overlays/ppolicy.c

index e2418ca27bae25c018977cf15e6835ef6d275d0f..88df7b31474f46fcca44babc56ab14de2f3fd4fc 100644 (file)
@@ -37,6 +37,12 @@ Specify the DN of the pwdPolicy object to use when no specific policy is
 set on a given user's entry. If there is no specific policy for an entry
 and no default is given, then no policies will be enforced.
 .TP
+.B ppolicy_hash_cleartext
+Specify that cleartext passwords present in Add and Modify requests should
+be hashed before being stored in the database. This violates the X.500
+information model, but may be needed to compensate for LDAP clients that
+don't use the PasswordModify exop to manage passwords.
+.TP
 .B ppolicy_use_lockout
 A client will always receive an LDAP
 .B InvalidCredentials
@@ -419,7 +425,7 @@ function prototype:
 .RS 4
 int
 .I check_password
-(char *pPasswd, char **ppErrStr, void *pArg);
+(char *pPasswd, char **ppErrStr, Attribute *pAttrs);
 .RE
 The
 .B pPasswd
@@ -427,9 +433,10 @@ parameter contains the clear-text user password, the
 .B ppErrStr
 parameter contains a double pointer that allows the function
 to return human-readable details about any error it encounters.
-The
-.B pArg
-parameter is currently unused.
+The optional
+.B pAttr
+parameter, if non-NULL, carries a list of the attributes for the
+entry whose password is being checked.
 If
 .B ppErrStr
 is NULL, then 
@@ -441,7 +448,8 @@ indicates that the password is unacceptable.  If the password is
 unacceptable, the server will return an error to the client, and
 .B ppErrStr
 may be used to return a human-readable textual explanation of the
-error.
+error. The error string must be dynamically allocated as it will
+be free()'d by slapd.
 .LP
 .RS 4
 (  1.3.6.1.4.1.4754.1.99.1
index 958da9ee6b6327487bd80fcf8de0e04c0a447f70..845aee641f760aec9bb0de5999c964e55ea17fa2 100644 (file)
@@ -49,6 +49,7 @@
 typedef struct pp_info {
        struct berval def_policy;       /* DN of default policy subentry */
        int use_lockout;                /* send AccountLocked result? */
+       int hash_passwords;             /* transparently hash cleartext pwds */
 } pp_info;
 
 /* Our per-connection info - note, it is not per-instance, it is 
@@ -439,7 +440,7 @@ password_scheme( struct berval *cred, struct berval *sch )
 }
 
 static int
-check_password_quality( struct berval *cred, PassPolicy *pp, LDAPPasswordPolicyError *err )
+check_password_quality( struct berval *cred, PassPolicy *pp, LDAPPasswordPolicyError *err, Entry *e )
 {
        int rc = LDAP_SUCCESS, ok = LDAP_SUCCESS;
        char *ptr = cred->bv_val;
@@ -498,7 +499,7 @@ check_password_quality( struct berval *cred, PassPolicy *pp, LDAPPasswordPolicyE
                                pp->pwdCheckModule, err, 0 );
                        ok = LDAP_OTHER; /* internal error */
                } else {
-                       int (*prog)( char *passwd, char **text, void *arg );
+                       int (*prog)( char *passwd, char **text, Attribute *attrs );
 
                        if ((prog = lt_dlsym( mod, "check_password" )) == NULL) {
                                err = lt_dlerror();
@@ -511,7 +512,7 @@ check_password_quality( struct berval *cred, PassPolicy *pp, LDAPPasswordPolicyE
                                char *txt = NULL;
 
                                ldap_pvt_thread_mutex_lock( &chk_syntax_mutex );
-                               ok = prog( cred->bv_val, &txt, NULL );
+                               ok = prog( cred->bv_val, &txt, e ? e->e_attrs : NULL );
                                ldap_pvt_thread_mutex_unlock( &chk_syntax_mutex );
                                if (txt) {
                                        Debug(LDAP_DEBUG_ANY,
@@ -1073,9 +1074,11 @@ ppolicy_add(
        SlapReply *rs )
 {
        slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+       pp_info *pi = on->on_bi.bi_private;
        PassPolicy pp;
        int pw;
        Attribute *pa;
+       const char *txt;
 
        if ( ppolicy_restrict( op, rs ) != SLAP_CB_CONTINUE )
                return rs->sr_err;
@@ -1089,7 +1092,7 @@ ppolicy_add(
                 * then we need to check that the password fits in with the
                 * security policy for the new entry.
                 */
-               ppolicy_get( op, op->oq_add.rs_e, &pp );
+               ppolicy_get( op, op->ora_e, &pp );
                if (pp.pwdCheckQuality > 0 && !be_isroot( op )) {
                        struct berval *bv = &(pa->a_vals[0]);
                        int rc, i, send_ctrl = 0; 
@@ -1103,7 +1106,7 @@ ppolicy_add(
                                        break;
                                }
                        }
-                       rc = check_password_quality( bv, &pp, &pErr );
+                       rc = check_password_quality( bv, &pp, &pErr, op->ora_e );
                        if (rc != LDAP_SUCCESS) {
                                op->o_bd->bd_info = (BackendInfo *)on->on_info;
                                if ( send_ctrl ) {
@@ -1117,6 +1120,37 @@ ppolicy_add(
                                send_ldap_error( op, rs, rc, "Password fails quality checking policy" );
                                return rs->sr_err;
                        }
+                           /*
+                            * A controversial bit. We hash cleartext
+                            * passwords provided via add and modify operations
+                            * You're not really supposed to do this, since
+                            * the X.500 model says "store attributes" as they
+                            * get provided. By default, this is what we do
+                            *
+                            * But if the hash_passwords flag is set, we hash
+                            * any cleartext password attribute values via the
+                            * default password hashing scheme.
+                            */
+                       if ((pi->hash_passwords) &&
+                               (password_scheme( &(pa->a_vals[0]), NULL ) != LDAP_SUCCESS)) {
+                               struct berval hpw;
+
+                               slap_passwd_hash( &(pa->a_vals[0]), &hpw, &txt );
+                               if (hpw.bv_val == NULL) {
+                                   /*
+                                    * hashing didn't work. Emit an error.
+                                    */
+                                       rs->sr_err = LDAP_OTHER;
+                                       rs->sr_text = txt;
+                                       send_ldap_error( op, rs, LDAP_OTHER, "Password hashing failed" );
+                                       return rs->sr_err;
+                               }
+
+                               memset( pa->a_vals[0].bv_val, 0, pa->a_vals[0].bv_len);
+                               ber_memfree( pa->a_vals[0].bv_val );
+                               pa->a_vals[0].bv_val = hpw.bv_val;
+                               pa->a_vals[0].bv_len = hpw.bv_len;
+                       }
                }
                /* If password aging is in effect, set the pwdChangedTime */
                if (( pp.pwdMaxAge || pp.pwdMinAge ) && !be_isupdate( op )) {
@@ -1143,6 +1177,7 @@ static int
 ppolicy_modify( Operation *op, SlapReply *rs )
 {
        slap_overinst           *on = (slap_overinst *)op->o_bd->bd_info;
+       pp_info                 *pi = on->on_bi.bi_private;
        int                     i, rc, mod_pw_only, pwmod, pwmop, deladd,
                                hsize = 0;
        PassPolicy              pp;
@@ -1387,7 +1422,7 @@ ppolicy_modify( Operation *op, SlapReply *rs )
        bv = newpw.bv_val ? &newpw : addmod->sml_values;
        if (pp.pwdCheckQuality > 0) {
 
-               rc = check_password_quality( bv, &pp, &pErr );
+               rc = check_password_quality( bv, &pp, &pErr, e );
                if (rc != LDAP_SUCCESS) {
                        rs->sr_err = rc;
                        rs->sr_text = "Password fails quality checking policy";
@@ -1593,7 +1628,7 @@ do_modify:
                 * leave it alone.
                 */
 
-               if ((addmod) && !newpw.bv_val && 
+               if ((pi->hash_passwords) && (addmod) && !newpw.bv_val && 
                        (password_scheme( &(addmod->sml_values[0]), NULL ) != LDAP_SUCCESS)) {
                        struct berval hpw, bv;
                        
@@ -1733,6 +1768,13 @@ ppolicy_config(
                }
                pi->use_lockout = 1;
                return 0;
+       } else if ( strcasecmp( argv[0], "ppolicy_hash_cleartext" ) == 0 ) {
+               if ( argc != 1 ) {
+                       fprintf( stderr, "%s: line %d: ppolicy_hash_cleartext "
+                               "takes no arguments\n", fname, lineno );
+                       return ( 1 );
+               }
+               pi->hash_passwords = 1;
        }
        return SLAP_CONF_UNKNOWN;
 }