summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Kinder <nkinder@redhat.com>2006-08-18 23:03:10 +0000
committerNathan Kinder <nkinder@redhat.com>2006-08-18 23:03:10 +0000
commit596d83cfe6711aca60a303e48bed08a0ad15148a (patch)
treeaad77e272ee81ecb3e81a4d6c7b46447160f0cbc
parent52ba2c0aceed9611e14ab9677e6e61f16b3acc11 (diff)
downloadds-596d83cfe6711aca60a303e48bed08a0ad15148a.tar.gz
ds-596d83cfe6711aca60a303e48bed08a0ad15148a.tar.xz
ds-596d83cfe6711aca60a303e48bed08a0ad15148a.zip
203043 - Support password generation when using the password modify extended operation
-rw-r--r--ldap/servers/slapd/passwd_extop.c164
1 files changed, 122 insertions, 42 deletions
diff --git a/ldap/servers/slapd/passwd_extop.c b/ldap/servers/slapd/passwd_extop.c
index 40eb1626..d996d06e 100644
--- a/ldap/servers/slapd/passwd_extop.c
+++ b/ldap/servers/slapd/passwd_extop.c
@@ -68,6 +68,12 @@
#define LDAP_EXTOP_PASSMOD_TAG_OLDPWD 0x81U
#define LDAP_EXTOP_PASSMOD_TAG_NEWPWD 0x82U
+/* ber tags for the PasswdModifyResponseValue sequence */
+#define LDAP_EXTOP_PASSMOD_TAG_GENPWD 0x80U
+
+/* number of bytes used for random password generation */
+#define LDAP_EXTOP_PASSMOD_GEN_PASSWD_LEN 8
+
/* OID of the extended operation handled by this plug-in */
#define EXOP_PASSWD_OID "1.3.6.1.4.1.4203.1.11.1"
@@ -191,6 +197,34 @@ static int passwd_modify_userpassword(Slapi_Entry *targetEntry, const char *newP
return ret;
}
+/* Generate a new random password */
+static int passwd_modify_generate_passwd(char **genpasswd)
+{
+ unsigned char data[ LDAP_EXTOP_PASSMOD_GEN_PASSWD_LEN ];
+ char enc[ 1 + LDIF_BASE64_LEN( LDAP_EXTOP_PASSMOD_GEN_PASSWD_LEN) ];
+
+ if (genpasswd == NULL) {
+ return LDAP_OPERATIONS_ERROR;
+ }
+
+ /* get 8 random bytes from NSS */
+ PK11_GenerateRandom( data, LDAP_EXTOP_PASSMOD_GEN_PASSWD_LEN );
+
+ /* b64 encode the 8 bytes to get a password made up of
+ * printable characters. ldif_base64_encode() will
+ * zero-terminate the string */
+ (void)ldif_base64_encode( data, enc, LDAP_EXTOP_PASSMOD_GEN_PASSWD_LEN, -1 );
+
+ /* This will get freed by the caller */
+ *genpasswd = slapi_ch_malloc( 1 + LDAP_EXTOP_PASSMOD_GEN_PASSWD_LEN);
+
+ /* trim the password to the proper length. */
+ PL_strncpyz( *genpasswd, enc, 1 + LDAP_EXTOP_PASSMOD_GEN_PASSWD_LEN );
+
+ return LDAP_SUCCESS;
+}
+
+
/* Password Modify Extended operation plugin function */
int
passwd_modify_extop( Slapi_PBlock *pb )
@@ -205,22 +239,14 @@ passwd_modify_extop( Slapi_PBlock *pb )
int ret=0, rc=0, sasl_ssf=0;
unsigned long tag=0, len=-1;
struct berval *extop_value = NULL;
+ struct berval *gen_passwd = NULL;
BerElement *ber = NULL;
+ BerElement *response_ber = NULL;
Slapi_Entry *targetEntry=NULL;
Connection *conn = NULL;
/* Slapi_DN sdn; */
LDAPDebug( LDAP_DEBUG_TRACE, "=> passwd_modify_extop\n", 0, 0, 0 );
- /* Get the pb ready for sending Password Modify Extended Responses back to the client.
- * The only requirement is to set the LDAP OID of the extended response to the EXOP_PASSWD_OID. */
-
- if ( slapi_pblock_set( pb, SLAPI_EXT_OP_RET_OID, EXOP_PASSWD_OID ) != 0 ) {
- errMesg = "Could not set extended response oid.\n";
- rc = LDAP_OPERATIONS_ERROR;
- slapi_log_error( SLAPI_LOG_PLUGIN, "passwd_modify_extop",
- errMesg );
- goto free_and_return;
- }
/* Before going any further, we'll make sure that the right extended operation plugin
* has been called: i.e., the OID shipped whithin the extended operation request must
@@ -278,22 +304,25 @@ passwd_modify_extop( Slapi_PBlock *pb )
}
/* Format of request to parse
- *
- * PasswdModifyRequestValue ::= SEQUENCE {
- * userIdentity [0] OCTET STRING OPTIONAL
- * oldPasswd [1] OCTET STRING OPTIONAL
- * newPasswd [2] OCTET STRING OPTIONAL }
- */
- slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
+ *
+ * PasswdModifyRequestValue ::= SEQUENCE {
+ * userIdentity [0] OCTET STRING OPTIONAL
+ * oldPasswd [1] OCTET STRING OPTIONAL
+ * newPasswd [2] OCTET STRING OPTIONAL }
+ *
+ * The request value field is optional. If it is
+ * provided, at least one field must be filled in.
+ */
/* ber parse code */
if ( ber_scanf( ber, "{") == LBER_ERROR )
{
- LDAPDebug( LDAP_DEBUG_ANY,
- "ber_scanf failed :{\n", 0, 0, 0 );
- errMesg = "ber_scanf failed\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
+ /* The request field wasn't provided. We'll
+ * now try to determine the userid and verify
+ * knowledge of the old password via other
+ * means.
+ */
+ goto parse_req_done;
} else {
tag = ber_peek_tag( ber, &len);
}
@@ -343,12 +372,9 @@ passwd_modify_extop( Slapi_PBlock *pb )
rc = LDAP_PROTOCOL_ERROR;
goto free_and_return;
}
- } else {
- errMesg = "New passwd must be supplied by the user.\n";
- rc = LDAP_PARAM_ERROR;
- goto free_and_return;
}
-
+
+parse_req_done:
/* Uncomment for debugging, otherwise we don't want to leak the password values into the log... */
/* LDAPDebug( LDAP_DEBUG_ARGS, "passwd: dn (%s), oldPasswd (%s) ,newPasswd (%s)\n",
dn, oldPasswd, newPasswd); */
@@ -376,13 +402,60 @@ passwd_modify_extop( Slapi_PBlock *pb )
}
}
- /* We don't implement password generation, so if the request implies
- * that they asked us to do that, we must refuse to process it */
- if (newPasswd == NULL || *newPasswd == '\0') {
- /* Refuse to handle this operation because we don't allow password generation */
- errMesg = "New passwd must be supplied by the user.\n";
- rc = LDAP_PARAM_ERROR;
- goto free_and_return;
+ /* A new password was not supplied in the request, so we need to generate
+ * a random one and return it to the user in a response.
+ */
+ if (newPasswd == NULL || *newPasswd == '\0') {
+ /* Do a free of newPasswd here to be safe, otherwise we may leak 1 byte */
+ slapi_ch_free_string( &newPasswd );
+
+ /* Generate a new password */
+ if (passwd_modify_generate_passwd( &newPasswd ) != LDAP_SUCCESS) {
+ errMesg = "Error generating new password.\n";
+ rc = LDAP_OPERATIONS_ERROR;
+ goto free_and_return;
+ }
+
+ /* Make sure a passwd was actually generated */
+ if (newPasswd == NULL || *newPasswd == '\0') {
+ errMesg = "Error generating new password.\n";
+ rc = LDAP_OPERATIONS_ERROR;
+ goto free_and_return;
+ }
+
+ /*
+ * Create the response message since we generated a new password.
+ *
+ * PasswdModifyResponseValue ::= SEQUENCE {
+ * genPasswd [0] OCTET STRING OPTIONAL }
+ */
+ if ( (response_ber = ber_alloc()) == NULL ) {
+ rc = LDAP_NO_MEMORY;
+ goto free_and_return;
+ }
+
+ if ( LBER_ERROR == ( ber_printf( response_ber, "{" ) ) ) {
+ ber_free( response_ber, 1 );
+ rc = LDAP_ENCODING_ERROR;
+ goto free_and_return;
+ }
+
+ if ( LBER_ERROR == ( ber_printf( response_ber, "ts", LDAP_EXTOP_PASSMOD_TAG_GENPWD,
+ newPasswd ) ) ) {
+ ber_free( response_ber, 1 );
+ rc = LDAP_ENCODING_ERROR;
+ goto free_and_return;
+ }
+
+ if ( LBER_ERROR == ( ber_printf( response_ber, "}" ) ) ) {
+ ber_free( response_ber, 1 );
+ rc = LDAP_ENCODING_ERROR;
+ }
+
+ ber_flatten(response_ber, &gen_passwd);
+
+ /* We're done with response_ber now, so free it */
+ ber_free( response_ber, 1 );
}
@@ -463,21 +536,25 @@ passwd_modify_extop( Slapi_PBlock *pb )
rc = ret;
goto free_and_return;
}
+
+ if (gen_passwd && (gen_passwd->bv_val != '\0')) {
+ /* Set the reponse to let the user know the generated password */
+ slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, gen_passwd);
+ }
LDAPDebug( LDAP_DEBUG_TRACE, "<= passwd_modify_extop: %d\n", rc, 0, 0 );
/* Free anything that we allocated above */
free_and_return:
-
- slapi_ch_free_string(&oldPasswd);
- slapi_ch_free_string(&newPasswd);
- /* Either this is the same pointer that we allocated and set above,
- or whoever used it should have freed it and allocated a new
- value that we need to free here */
+ slapi_ch_free_string(&oldPasswd);
+ slapi_ch_free_string(&newPasswd);
+ /* Either this is the same pointer that we allocated and set above,
+ * or whoever used it should have freed it and allocated a new
+ * value that we need to free here */
slapi_pblock_get( pb, SLAPI_ORIGINAL_TARGET, &dn );
- slapi_ch_free_string(&dn);
+ slapi_ch_free_string(&dn);
slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, NULL );
- slapi_ch_free_string(&authmethod);
+ slapi_ch_free_string(&authmethod);
if ( targetEntry != NULL ){
slapi_entry_free (targetEntry);
@@ -493,6 +570,9 @@ passwd_modify_extop( Slapi_PBlock *pb )
send_ldap_result( pb, rc, NULL, errMesg, 0, NULL );
+ /* We can free the generated password bval now */
+ ber_bvfree(gen_passwd);
+
return( SLAPI_PLUGIN_EXTENDED_SENT_RESULT );
}/* passwd_modify_extop */