>From f9ec9a62b8e386c7918b0b9ea628023ed9bd505e Mon Sep 17 00:00:00 2001 From: Nathan Kinder Date: Tue, 1 Dec 2009 16:27:23 -0800 Subject: [PATCH] Bug 195302 - Allow fine-grained password storage scheme to be set This patch makes the server use the password storage scheme set in the appropriate fine-grained password policy (if it is set). The previous code was always using the global storage scheme. This fix was based off of a fix contributed by Ulf Weltman of Hewlett Packard. --- ldap/servers/slapd/add.c | 10 +++- ldap/servers/slapd/modify.c | 10 +++- ldap/servers/slapd/pw.c | 100 +++++++++++++++++++++++++++--------- ldap/servers/slapd/pw.h | 9 +++- ldap/servers/slapd/slap.h | 9 +++- ldap/servers/slapd/slapi-plugin.h | 11 ++++- 6 files changed, 117 insertions(+), 32 deletions(-) diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c index df683a9..1a1f867 100644 --- a/ldap/servers/slapd/add.c +++ b/ldap/servers/slapd/add.c @@ -32,8 +32,14 @@ * * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. - * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. * All rights reserved. + * + * Contributors: + * Hewlett-Packard Development Company, L.P. + * Bugfix for bug #195302 + * * END COPYRIGHT BLOCK **/ #ifdef HAVE_CONFIG_H @@ -512,7 +518,7 @@ static void op_shared_add (Slapi_PBlock *pb) Slapi_Value **vals= NULL; valuearray_add_valuearray(&unhashed_password_vals, present_values, 0); valuearray_add_valuearray(&vals, present_values, 0); - pw_encodevals(vals); + pw_encodevals_ext(pb, slapi_entry_get_sdn (e), vals); add_password_attrs(pb, operation, e); slapi_entry_attr_replace_sv(e, SLAPI_USERPWD_ATTR, vals); valuearray_free(&vals); diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c index 1eac848..40646b2 100644 --- a/ldap/servers/slapd/modify.c +++ b/ldap/servers/slapd/modify.c @@ -32,8 +32,14 @@ * * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. - * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. * All rights reserved. + * + * Contributors: + * Hewlett-Packard Development Company, L.P. + * Bugfix for bug #195302 + * * END COPYRIGHT BLOCK **/ #ifdef HAVE_CONFIG_H @@ -712,7 +718,7 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char *old_pw) valuearray_init_bervalarray(pw_mod->mod_bvalues, &va); /* encode password */ - pw_encodevals(va); + pw_encodevals_ext(pb, &sdn, va); /* remove current clear value of userpassword */ ber_bvecfree(pw_mod->mod_bvalues); diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c index cafdfd6..09bb96c 100644 --- a/ldap/servers/slapd/pw.c +++ b/ldap/servers/slapd/pw.c @@ -32,8 +32,14 @@ * * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. - * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. * All rights reserved. + * + * Contributors: + * Hewlett-Packard Development Company, L.P. + * Bugfix for bug #195302 + * * END COPYRIGHT BLOCK **/ #ifdef HAVE_CONFIG_H @@ -177,17 +183,23 @@ int slapi_is_encoded (char *value) char* slapi_encode (char *value, char *alg) { + return( slapi_encode_ext( NULL, NULL, value, alg ) ); +} + +char* slapi_encode_ext (Slapi_PBlock *pb, const Slapi_DN *sdn, char *value, char *alg) +{ struct pw_scheme *enc_scheme = NULL; + char *(*pws_enc) ( char *pwd ) = NULL; char *hashedval = NULL; - int need_to_free = 0; + passwdPolicy *pwpolicy=NULL; - if (alg == NULL) /* use server encoding scheme */ + if (alg == NULL) /* use local scheme, or global if we can't fetch local */ { - slapdFrontendConfig_t * slapdFrontendConfig = getFrontendConfig(); - - enc_scheme = slapdFrontendConfig->pw_storagescheme; + pwpolicy = new_passwdPolicy(pb, (char*)slapi_sdn_get_ndn(sdn) ); + pws_enc = pwpolicy->pw_storagescheme->pws_enc; + delete_passwdPolicy(&pwpolicy); - if (enc_scheme == NULL) + if (pws_enc == NULL) { slapi_log_error( SLAPI_LOG_FATAL, NULL, "slapi_encode: no server scheme\n" ); @@ -212,12 +224,11 @@ char* slapi_encode (char *value, char *alg) } return NULL; } - need_to_free = 1; + pws_enc = enc_scheme->pws_enc; + free_pw_scheme(enc_scheme); } - hashedval = enc_scheme->pws_enc(value); - if (need_to_free) - free_pw_scheme(enc_scheme); + hashedval = (*pws_enc)(value); return hashedval; } @@ -318,18 +329,39 @@ pw_val2scheme( char *val, char **valpwdp, int first_is_default ) int pw_encodevals( Slapi_Value **vals ) { + return( pw_encodevals_ext( NULL, NULL, vals ) ); +} + +/* + * Same as pw_encodevals, except if a pb and sdn are passed in, we will try + * to check the password scheme specified by local password policy. + */ +int +pw_encodevals_ext( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals ) +{ int i; - slapdFrontendConfig_t * slapdFrontendConfig = getFrontendConfig(); + passwdPolicy *pwpolicy=NULL; + char *dn; + char *(*pws_enc) ( char *pwd ) = NULL; + if ( vals == NULL ) { + return( 0 ); + } + + /* new_passwdPolicy gives us a local policy if sdn and pb are set and + can be used to find a local policy, else we get the global policy */ + pwpolicy = new_passwdPolicy(pb, (char*)slapi_sdn_get_ndn(sdn) ); + pws_enc = pwpolicy->pw_storagescheme->pws_enc; + delete_passwdPolicy(&pwpolicy); - if ( vals == NULL || slapdFrontendConfig->pw_storagescheme == NULL || - slapdFrontendConfig->pw_storagescheme->pws_enc == NULL ) { + /* Password scheme encryption function was not found */ + if ( pws_enc == NULL ) { return( 0 ); } for ( i = 0; vals[ i ] != NULL; ++i ) { - struct pw_scheme *pwsp; - char *enc = NULL; + struct pw_scheme *pwsp = NULL; + char *enc = NULL; if ( (pwsp=pw_val2scheme( (char*)slapi_value_get_string(vals[ i ]), NULL, 0)) != NULL ) { /* JCM Innards */ /* If the value already specifies clear storage, call the * clear storage plug-in */ @@ -340,14 +372,14 @@ pw_encodevals( Slapi_Value **vals ) continue; /* don't touch pre-encoded values */ } } - if ((!enc) && (( enc = (*slapdFrontendConfig->pw_storagescheme->pws_enc)( (char*)slapi_value_get_string(vals[ i ]) )) /* JCM Innards */ - == NULL )) { - free_pw_scheme( pwsp ); + free_pw_scheme( pwsp ); + + if ((!enc) && (( enc = (*pws_enc)( (char*)slapi_value_get_string(vals[ i ]) )) == NULL )) { return( -1 ); } + slapi_value_free(&vals[ i ]); vals[ i ] = slapi_value_new_string_passin(enc); - free_pw_scheme( pwsp ); } return( 0 ); @@ -1460,6 +1492,7 @@ new_passwdPolicy(Slapi_PBlock *pb, char *dn) int attr_free_flags = 0; int rc=0; passwdPolicy *pwdpolicy = NULL; + struct pw_scheme *pwdscheme = NULL; Slapi_Attr *attr; char *attr_name; Slapi_Value **sval; @@ -1471,10 +1504,12 @@ new_passwdPolicy(Slapi_PBlock *pb, char *dn) slapdFrontendConfig = getFrontendConfig(); pwdpolicy = (passwdPolicy *)slapi_ch_calloc(1, sizeof(passwdPolicy)); - slapi_pblock_get( pb, SLAPI_OPERATION, &op); - slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &optype ); + if (pb) { + slapi_pblock_get( pb, SLAPI_OPERATION, &op); + slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &optype ); + } - if (dn && (slapdFrontendConfig->pwpolicy_local == 1)) { + if (pb && dn && (slapdFrontendConfig->pwpolicy_local == 1)) { /* If we're doing an add, COS does not apply yet so we check parents for the pwdpolicysubentry. We look only for virtual attributes, because real ones are for single-target policy. */ @@ -1701,13 +1736,20 @@ new_passwdPolicy(Slapi_PBlock *pb, char *dn) pwdpolicy->pw_gracelimit = slapi_value_get_int(*sval); } } + else + if (!strcasecmp(attr_name, "passwordstoragescheme")) { + if ((sval = attr_get_present_values(attr))) { + pwdpolicy->pw_storagescheme = + pw_name2scheme((char*)slapi_value_get_string(*sval)); + } + } } /* end of for() loop */ if (pw_entry) { slapi_entry_free(pw_entry); } return pwdpolicy; - } else if ( e ) { + } else if ( e ) { slapi_entry_free( e ); } } @@ -1718,6 +1760,11 @@ done: */ *pwdpolicy = slapdFrontendConfig->pw_policy; + pwdscheme = (struct pw_scheme *)slapi_ch_calloc(1, sizeof(struct pw_scheme)); + *pwdscheme = *slapdFrontendConfig->pw_storagescheme; + pwdscheme->pws_name = strdup( slapdFrontendConfig->pw_storagescheme->pws_name ); + pwdpolicy->pw_storagescheme = pwdscheme; + return pwdpolicy; } /* End of new_passwdPolicy() */ @@ -1725,7 +1772,10 @@ done: void delete_passwdPolicy( passwdPolicy **pwpolicy) { - slapi_ch_free((void **)pwpolicy); + if (pwpolicy && *pwpolicy) { + free_pw_scheme( (*(*pwpolicy)).pw_storagescheme ); + slapi_ch_free((void **)pwpolicy); + } } /* diff --git a/ldap/servers/slapd/pw.h b/ldap/servers/slapd/pw.h index 5f5eb1b..38c7faf 100644 --- a/ldap/servers/slapd/pw.h +++ b/ldap/servers/slapd/pw.h @@ -32,8 +32,14 @@ * * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. - * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. * All rights reserved. + * + * Contributors: + * Hewlett-Packard Development Company, L.P. + * Bugfix for bug #195302 + * * END COPYRIGHT BLOCK **/ #ifdef HAVE_CONFIG_H @@ -76,6 +82,7 @@ struct pw_scheme { struct pw_scheme *pw_name2scheme( char *name ); struct pw_scheme *pw_val2scheme( char *val, char **valpwdp, int first_is_default ); int pw_encodevals( Slapi_Value **vals ); +int pw_encodevals_ext( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals ); int checkPrefix(char *cipher, char *schemaName, char **encrypt); struct passwordpolicyarray *new_passwdPolicy ( Slapi_PBlock *pb, char *dn ); void delete_passwdPolicy( struct passwordpolicyarray **pwpolicy); diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index 5860350..0e37c85 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -32,8 +32,14 @@ * * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. - * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. * All rights reserved. + * + * Contributors: + * Hewlett-Packard Development Company, L.P. + * Bugfix for bug #195302 + * * END COPYRIGHT BLOCK **/ #ifdef HAVE_CONFIG_H @@ -1874,6 +1880,7 @@ typedef struct passwordpolicyarray { long pw_lockduration; long pw_resetfailurecount; int pw_gracelimit; + struct pw_scheme *pw_storagescheme; } passwdPolicy; typedef struct _slapdFrontendConfig { diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index 1d545a0..09f18e7 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -32,8 +32,14 @@ * * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. - * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. * All rights reserved. + * + * Contributors: + * Hewlett-Packard Development Company, L.P. + * Bugfix for bug #195302 + * * END COPYRIGHT BLOCK */ #ifdef HAVE_CONFIG_H @@ -2274,6 +2280,9 @@ int slapi_pw_find_sv( Slapi_Value **vals, const Slapi_Value *v ); int slapi_is_encoded(char *value); /* encode value with the specified algorithm */ char* slapi_encode(char *value, char *alg); +/* encode value with the specified algorithm, or with local algorithm if pb + * and sdn are specified instead, or global algorithm if pb and sdn are null */ +char* slapi_encode_ext(Slapi_PBlock *pb, const Slapi_DN *sdn, char *value, char *alg); /* UTF8 related */ -- 1.6.2.5