Add controls to extended ops API signatures, need impl.
Update password to support optional server side generation of
new password, verification of old password, and changing of
non-bound user's passwords.
" -n\t\tmake no modifications\n"
" -p port\tldap port\n"
" -s secret\tnew password\n"
+ " -S\t\tprompt for new password\n"
" -v\t\tincrease verbosity\n"
" -W\t\tprompt for bind password\n"
" -w passwd\tbind password (for simple authentication)\n"
main( int argc, char *argv[] )
{
int rc;
+ char *ldaphost = NULL;
+
char *dn = NULL;
char *binddn = NULL;
+
char *bindpw = NULL;
- char *ldaphost = NULL;
char *newpw = NULL;
+ char *oldpw = NULL;
+
+ int want_bindpw = 0;
+ int want_newpw = 0;
+ int want_oldpw = 0;
+
int noupdates = 0;
int i;
int ldapport = 0;
int debug = 0;
int version = -1;
- int want_bindpw = 0;
LDAP *ld;
struct berval *bv = NULL;
- BerElement *ber;
char *retoid;
struct berval *retdata;
usage (argv[0]);
while( (i = getopt( argc, argv,
- "D:d:h:np:s:vWw:" )) != EOF )
+ "Aa:D:d:h:np:Ss:vWw:" )) != EOF )
{
switch (i) {
+ case 'A': /* prompt for oldr password */
+ want_oldpw++;
+ break;
+ case 'a': /* old password (secret) */
+ oldpw = strdup (optarg);
+
+ {
+ char* p;
+
+ for( p = optarg; *p == '\0'; p++ ) {
+ *p = '*';
+ }
+ }
+ break;
case 'D': /* bind distinguished name */
binddn = strdup (optarg);
break;
ldapport = strtol( optarg, NULL, 10 );
break;
+ case 'S': /* prompt for user password */
+ want_newpw++;
+ break;
+
case 's': /* new password (secret) */
newpw = strdup (optarg);
+
+ {
+ char* p;
+
+ for( p = optarg; *p == '\0'; p++ ) {
+ *p = '*';
+ }
+ }
break;
case 'v': /* verbose */
case 'w': /* bind password */
bindpw = strdup (optarg);
+
{
char* p;
dn = strdup( argv[optind] );
- if( newpw == NULL ) {
+ if( want_oldpw && oldpw == NULL ) {
+ /* prompt for old password */
+ char *ckoldpw;
+ newpw = strdup(getpass("Old password: "));
+ ckoldpw = getpass("Re-enter old password: ");
+
+ if( strncmp( oldpw, ckoldpw, strlen(oldpw) )) {
+ fprintf( stderr, "passwords do not match\n" );
+ return EXIT_FAILURE;
+ }
+ }
+
+ if( want_newpw && newpw == NULL ) {
/* prompt for new password */
char *cknewpw;
newpw = strdup(getpass("New password: "));
}
}
- if( binddn == NULL ) {
+ if( binddn == NULL && dn != NULL ) {
binddn = dn;
dn = NULL;
+
+ if( bindpw == NULL ) bindpw = oldpw;
}
- /* handle bind password */
- if (want_bindpw) {
+ if (want_bindpw && bindpw == NULL ) {
+ /* handle bind password */
fprintf( stderr, "Bind DN: %s\n", binddn );
bindpw = strdup( getpass("Enter bind password: "));
}
return EXIT_FAILURE;
}
- /* build change password control */
- ber = ber_alloc_t( LBER_USE_DER );
+ if( dn != NULL || oldpw != NULL || newpw != NULL ) {
+ /* build change password control */
+ BerElement *ber = ber_alloc_t( LBER_USE_DER );
- if( ber == NULL ) {
- perror( "ber_alloc_t" );
- ldap_unbind( ld );
- return EXIT_FAILURE;
- }
+ if( ber == NULL ) {
+ perror( "ber_alloc_t" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
+ }
- if( dn != NULL ) {
- ber_printf( ber, "{tsts}",
- LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, dn,
- LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
+ if( dn != NULL ) {
+ ber_printf( ber, "ts",
+ LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, dn );
+ free(dn);
+ }
- free(dn);
+ if( oldpw != NULL ) {
+ ber_printf( ber, "ts",
+ LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, oldpw );
+ free(oldpw);
+ }
- } else {
- ber_printf( ber, "{ts}",
- LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
- }
+ if( newpw != NULL ) {
+ ber_printf( ber, "ts",
+ LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
+ free(newpw);
+ }
- free(newpw);
+ rc = ber_flatten( ber, &bv );
- rc = ber_flatten( ber, &bv );
+ if( rc < 0 ) {
+ perror( "ber_flatten" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
+ }
- if( rc < 0 ) {
- perror( "ber_flatten" );
- ldap_unbind( ld );
- return EXIT_FAILURE;
+ ber_free( ber, 1 );
}
- ber_free( ber, 1 );
-
rc = ldap_extended_operation_s( ld,
LDAP_EXOP_X_MODIFY_PASSWD, bv,
NULL, NULL,
ber_bvfree( bv );
+ if( retdata != NULL ) {
+ ber_tag_t tag;
+ char *s;
+ BerElement *ber = ber_init( retdata );
+
+ if( ber == NULL ) {
+ perror( "ber_init" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
+ }
+
+ /* we should check the tag */
+ tag = ber_scanf( ber, "a", &s);
+
+ if( tag == LBER_ERROR ) {
+ perror( "ber_scanf" );
+ } else {
+ printf("New password: %s\n", s);
+ free( s );
+ }
+
+ ber_free( ber, 1 );
+ }
+
if ( rc != LDAP_SUCCESS ) {
ldap_perror( ld, "ldap_extended_operation" );
ldap_unbind( ld );
const char **methods ));
LIBLUTIL_F( struct berval * )
-lutil_passwd_generate LDAP_P((
+lutil_passwd_generate LDAP_P(( int ));
+
+LIBLUTIL_F( struct berval * )
+lutil_passwd_hash LDAP_P((
const struct berval *passwd,
const char *method ));
}
rc = ber_scanf( ber, "{iaa" /*}*/, &errcode,
- &ld->ld_matched, &ld->ld_matched );
+ &ld->ld_matched, &ld->ld_error );
if( rc == LBER_ERROR ) {
ld->ld_errno = LDAP_DECODING_ERROR;
if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
/* we have a resdata */
- if( ber_scanf( ber, "O", &resoid ) == LBER_ERROR ) {
+ if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
ld->ld_errno = LDAP_DECODING_ERROR;
ber_free( ber, 0 );
if( resoid != NULL ) LDAP_FREE( resoid );
# include <pwd.h>
#endif
+static const unsigned char crypt64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
+
struct pw_scheme;
typedef int (*PASSWD_CHK_FUNC)(
const struct berval *passwd,
const struct berval *cred );
-typedef struct berval * (*PASSWD_GEN_FUNC) (
+typedef struct berval * (*PASSWD_HASH_FUNC) (
const struct pw_scheme *scheme,
const struct berval *passwd );
struct pw_scheme {
struct berval name;
PASSWD_CHK_FUNC chk_fn;
- PASSWD_GEN_FUNC gen_fn;
+ PASSWD_HASH_FUNC hash_fn;
};
/* password check routines */
const struct berval *cred );
-/* password generation routines */
-static struct berval *gen_sha1(
+/* password hash routines */
+static struct berval *hash_sha1(
const struct pw_scheme *scheme,
const struct berval *passwd );
-static struct berval *gen_ssha1(
+static struct berval *hash_ssha1(
const struct pw_scheme *scheme,
const struct berval *passwd );
-static struct berval *gen_smd5(
+static struct berval *hash_smd5(
const struct pw_scheme *scheme,
const struct berval *passwd );
-static struct berval *gen_md5(
+static struct berval *hash_md5(
const struct pw_scheme *scheme,
const struct berval *passwd );
-static struct berval *gen_crypt(
+static struct berval *hash_crypt(
const struct pw_scheme *scheme,
const struct berval *passwd );
static const struct pw_scheme pw_schemes[] =
{
- { {sizeof("{SSHA}")-1, "{SSHA}"}, chk_ssha1, gen_ssha1 },
- { {sizeof("{SHA}")-1, "{SHA}"}, chk_sha1, gen_sha1 },
+ { {sizeof("{SSHA}")-1, "{SSHA}"}, chk_ssha1, hash_ssha1 },
+ { {sizeof("{SHA}")-1, "{SHA}"}, chk_sha1, hash_sha1 },
- { {sizeof("{SMD5}")-1, "{SMD5}"}, chk_smd5, gen_smd5 },
- { {sizeof("{MD5}")-1, "{MD5}"}, chk_md5, gen_md5 },
+ { {sizeof("{SMD5}")-1, "{SMD5}"}, chk_smd5, hash_smd5 },
+ { {sizeof("{MD5}")-1, "{MD5}"}, chk_md5, hash_md5 },
#ifdef SLAPD_CRYPT
- { {sizeof("{CRYPT}")-1, "{CRYPT}"}, chk_crypt, gen_crypt },
+ { {sizeof("{CRYPT}")-1, "{CRYPT}"}, chk_crypt, hash_crypt },
#endif
# if defined( HAVE_GETSPNAM ) \
|| ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
}
-struct berval * lutil_passwd_generate(
+struct berval * lutil_passwd_generate( int len )
+{
+ struct berval *pw;
+
+ if( len < 1 ) return NULL;
+
+ pw = ber_memalloc( sizeof( struct berval ) );
+ if( pw == NULL ) return NULL;
+
+ pw->bv_len = len;
+ pw->bv_val = ber_memalloc( len + 1 );
+
+ if( pw->bv_val == NULL ) {
+ ber_memfree( pw );
+ return NULL;
+ }
+
+ if( lutil_entropy( pw->bv_val, pw->bv_len) < 0 ) {
+ ber_bvfree( pw );
+ return NULL;
+ }
+
+ for( len = 0; len < pw->bv_len; len++ ) {
+ pw->bv_val[len] = crypt64[
+ pw->bv_val[len] % (sizeof(crypt64)-1) ];
+ }
+
+ pw->bv_val[len] = '\0';
+
+ return pw;
+}
+
+struct berval * lutil_passwd_hash(
const struct berval * passwd,
const char * method )
{
const struct pw_scheme *sc = get_scheme( method );
if( sc == NULL ) return NULL;
- if( ! sc->gen_fn ) return NULL;
+ if( ! sc->hash_fn ) return NULL;
- return (sc->gen_fn)( sc, passwd );
+ return (sc->hash_fn)( sc, passwd );
}
static struct berval * pw_string(
#endif
/* PASSWORD CHECK ROUTINES */
-static struct berval *gen_ssha1(
+static struct berval *hash_ssha1(
const struct pw_scheme *scheme,
const struct berval *passwd )
{
return pw_string64( scheme, &digest, &salt);
}
-static struct berval *gen_sha1(
+static struct berval *hash_sha1(
const struct pw_scheme *scheme,
const struct berval *passwd )
{
return pw_string64( scheme, &digest, NULL);
}
-static struct berval *gen_smd5(
+static struct berval *hash_smd5(
const struct pw_scheme *scheme,
const struct berval *passwd )
{
return pw_string64( scheme, &digest, &salt );
}
-static struct berval *gen_md5(
+static struct berval *hash_md5(
const struct pw_scheme *scheme,
const struct berval *passwd )
{
}
#ifdef SLAPD_CRYPT
-static struct berval *gen_crypt(
+static struct berval *hash_crypt(
const struct pw_scheme *scheme,
const struct berval *passwd )
{
- static const unsigned char crypt64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
-
struct berval hash;
unsigned char salt[3];
int i;
char *oid,
struct berval *reqdata,
struct berval **rspdata,
+ LDAPControl *** rspctrls,
char** text
)
{
for( i=0; exop_table[i].oid != NULL; i++ ) {
if( strcmp( exop_table[i].oid, oid ) == 0 ) {
return (exop_table[i].extended)(
- be, conn, op,
- oid, reqdata, rspdata, text );
+ be, conn, op, oid,
+ reqdata, rspdata, rspctrls, text );
}
}
char *reqoid,
struct berval *reqdata,
struct berval **rspdata,
+ LDAPControl *** rspctrls,
char **text ));
extern int ldbm_back_bind LDAP_P(( BackendDB *bd,
char *oid,
struct berval *reqdata,
struct berval **rspdata,
+ LDAPControl *** rspctrls,
char** text
)
{
}
if( new == NULL || new->bv_len == 0 ) {
- *text = ch_strdup("no password provided");
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
+ new = slap_passwd_generate();
+
+ if( new == NULL || new->bv_len == 0 ) {
+ *text = ch_strdup("password generation failed.");
+ rc = LDAP_OPERATIONS_ERROR;
+ goto done;
+ }
+
+ *rspdata = slap_passwd_return( new );
}
- hash = slap_passwd_generate( new );
+ hash = slap_passwd_hash( new );
if( hash == NULL || hash->bv_len == 0 ) {
- *text = ch_strdup("password generation failed");
+ *text = ch_strdup("password hash failed");
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
goto done;
}
- e = dn2entry_w( be,
- id ? id->bv_val : op->o_dn,
- NULL );
+ e = dn2entry_w( be, dn, NULL );
if( e == NULL ) {
*text = ch_strdup("could not locate authorization entry");
char *oid,
struct berval *reqdata,
struct berval **rspdata,
+ LDAPControl ***rspctrls,
char **text ));
extop_list_t *ext;
char *text;
struct berval *rspdata;
+ LDAPControl **rspctrls;
Debug( LDAP_DEBUG_TRACE, "do_extended\n", 0, 0, 0 );
Debug( LDAP_DEBUG_ARGS, "do_extended: oid=%s\n", oid, 0 ,0 );
rspdata = NULL;
+ rspctrls = NULL;
text = NULL;
rc = (ext->ext_main)( extop_callback, conn, op,
- oid, reqdata, &rspdata, &text );
+ oid, reqdata, &rspdata, &rspctrls, &text );
if( rc != SLAPD_ABANDON ) {
send_ldap_extended( conn, op, rc, NULL, text,
- oid, rspdata );
+ oid, rspdata, rspctrls );
}
if ( rspdata != NULL )
int passwd_extop(
SLAP_EXTOP_CALLBACK_FN ext_callback,
Connection *conn, Operation *op, char *oid,
- struct berval *reqdata, struct berval **rspdata, char **text )
+ struct berval *reqdata,
+ struct berval **rspdata,
+ LDAPControl ***rspctrls,
+ char **text )
{
int rc;
return LDAP_STRONG_AUTH_REQUIRED;
}
- if( reqdata == NULL || reqdata->bv_len == 0 ) {
- *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 );
+ conn, op, oid, reqdata, rspdata, rspctrls, text );
} else {
*text = ch_strdup("operation not supported for current user");
ber_len_t len;
BerElement *ber;
- assert( reqdata != NULL );
+ if( reqdata == NULL ) {
+ return LDAP_SUCCESS;
+ }
ber = ber_init( reqdata );
return LDAP_PROTOCOL_ERROR;
}
- tag = ber_scanf(ber, "{" /*}*/);
-
- if( tag == LBER_ERROR ) {
- goto decoding_error;
- }
-
tag = ber_peek_tag( ber, &len );
if( tag == LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID ) {
return rc;
}
+struct berval * slap_passwd_return(
+ struct berval *cred )
+{
+ int rc;
+ struct berval *bv;
+ BerElement *ber = ber_alloc_t(LBER_USE_DER);
+
+ assert( cred != NULL );
+
+ Debug( LDAP_DEBUG_TRACE, "slap_passwd_return: %ld\n",
+ (long) cred->bv_len, 0, 0 );
+
+ if( ber == NULL ) return NULL;
+
+ rc = ber_printf( ber, "tO",
+ LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, cred );
+
+ if( rc == -1 ) {
+ ber_free( ber, 1 );
+ return NULL;
+ }
+
+ (void) ber_flatten( ber, &bv );
+
+ ber_free( ber, 1 );
+
+ return bv;
+}
+
int
slap_passwd_check(
Attribute *a,
return( 1 );
}
-struct berval * slap_passwd_generate(
+struct berval * slap_passwd_generate( void )
+{
+ Debug( LDAP_DEBUG_TRACE, "slap_passwd_generate\n", 0, 0, 0 );
+ return lutil_passwd_generate( 8 );
+}
+
+struct berval * slap_passwd_hash(
struct berval * cred )
{
char* hash = default_passwd_hash ? default_passwd_hash : "{SSHA}";
ldap_pvt_thread_mutex_lock( &crypt_mutex );
#endif
- new = lutil_passwd_generate( cred , hash );
+ new = lutil_passwd_hash( cred , hash );
#ifdef SLAPD_CRYPT
ldap_pvt_thread_mutex_unlock( &crypt_mutex );
char * oid,
struct berval * reqdata,
struct berval ** rspdata,
+ LDAPControl *** rspctrls,
char ** text ));
typedef int (*SLAP_EXTOP_GETOID_FN) LDAP_P((
Connection *conn, Operation *op,
ber_int_t err, const char *matched,
const char *text,
+ LDAPControl **ctrls,
struct berval *cred ));
LIBSLAPD_F (void) send_ldap_disconnect LDAP_P((
Connection *conn, Operation *op,
ber_int_t err, const char *matched,
const char *text,
- char *rspoid, struct berval *rspdata ));
+ char *rspoid, struct berval *rspdata,
+ LDAPControl **ctrls ));
LIBSLAPD_F (void) send_search_result LDAP_P((
Connection *conn, Operation *op,
char * oid,
struct berval * reqdata,
struct berval ** rspdata,
+ LDAPControl ***rspctrls,
char ** text ));
char * oid,
struct berval * reqdata,
struct berval ** rspdata,
+ LDAPControl *** rspctrls,
char ** text ));
LIBSLAPD_F (int) slap_passwd_check(
Attribute *attr,
struct berval *cred );
-LIBSLAPD_F (struct berval *) slap_passwd_generate(
+LIBSLAPD_F (struct berval *) slap_passwd_generate( void );
+
+LIBSLAPD_F (struct berval *) slap_passwd_hash(
+ struct berval *cred );
+
+LIBSLAPD_F (struct berval *) slap_passwd_return(
struct berval *cred );
LIBSLAPD_F (int) slap_passwd_parse(
const char *text,
struct berval **ref,
const char *resoid,
- struct berval *data,
+ struct berval *resdata,
+ struct berval *sasldata,
LDAPControl **ctrls
)
{
rc = ber_printf( ber, "{V}", ref );
}
+ if( rc != -1 && sasldata != NULL ) {
+ rc = ber_printf( ber, "tO",
+ LDAP_TAG_SASL_RES_CREDS, sasldata );
+ }
+
if( rc != -1 && resoid != NULL ) {
- rc = ber_printf( ber, "s", resoid );
+ rc = ber_printf( ber, "ts",
+ LDAP_TAG_EXOP_RES_OID, resoid );
}
- if( rc != -1 && data != NULL ) {
- rc = ber_printf( ber, "O", data );
+ if( rc != -1 && resdata != NULL ) {
+ rc = ber_printf( ber, "tO",
+ LDAP_TAG_EXOP_RES_VALUE, resdata );
}
if( rc != -1 ) {
0 );
}
#endif
+
send_ldap_response( conn, op, tag, msgid,
err, NULL, text, NULL,
- reqoid, NULL, NULL );
+ reqoid, NULL, NULL, NULL );
Statslog( LDAP_DEBUG_STATS,
"conn=%ld op=%ld DISCONNECT err=%ld tag=%lu text=%s\n",
send_ldap_response( conn, op, tag, msgid,
err, matched, text, ref,
- NULL, NULL, ctrls );
+ NULL, NULL, NULL, ctrls );
Statslog( LDAP_DEBUG_STATS,
"conn=%ld op=%ld RESULT tag=%lu err=%ld text=%s\n",
ber_int_t err,
const char *matched,
const char *text,
+ LDAPControl **ctrls,
struct berval *cred
)
{
send_ldap_response( conn, op, tag, msgid,
err, matched, text, NULL,
- NULL, cred, NULL );
+ NULL, NULL, cred, ctrls );
}
void
const char *matched,
const char *text,
char *rspoid,
- struct berval *rspdata
+ struct berval *rspdata,
+ LDAPControl **ctrls
)
{
ber_tag_t tag;
ber_int_t msgid;
Debug( LDAP_DEBUG_TRACE,
- "send_ldap_extended %ld:%s\n",
- (long) err, rspoid ? rspoid : "", NULL );
+ "send_ldap_extended %ld:%s (%ld)\n",
+ (long) err,
+ rspoid ? rspoid : "",
+ rspdata != NULL ? (long) rspdata->bv_len : (long) 0 );
tag = req2res( op->o_tag );
msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
0 );
}
#endif
+
send_ldap_response( conn, op, tag, msgid,
err, matched, text, NULL,
- rspoid, rspdata, NULL );
+ rspoid, rspdata, NULL, ctrls );
}
send_ldap_response( conn, op, tag, msgid,
err, matched, text, refs,
- NULL, NULL, ctrls );
+ NULL, NULL, NULL, ctrls );
Statslog( LDAP_DEBUG_STATS,
"conn=%ld op=%ld SEARCH RESULT tag=%lu err=%ld text=%s\n",
char *oid,
struct berval * reqdata,
struct berval ** rspdata,
+ LDAPControl ***rspctrls,
char** text ));
struct slap_backend_info {
char * oid,
struct berval * reqdata,
struct berval ** rspdata,
+ LDAPControl ***rspctrls,
char ** text )
{
if ( reqdata != NULL ) {
conn->c_is_tls = 1;
conn->c_needs_tls_accept = 1;
+
return(LDAP_SUCCESS);
}
const char *matched,
const char *text,
char *rspoid,
- struct berval *rspdata
+ struct berval *rspdata,
+ LDAPControl **ctrls
)
{
assert(0);
ber_int_t err,
const char *matched,
const char *text,
+ LDAPControl **ctrls,
struct berval *cred
)
{