From 648f2e2f126a982d5586323dcc47a749d72918ca Mon Sep 17 00:00:00 2001 From: Dave Storey Date: Sat, 12 Dec 1998 06:12:03 +0000 Subject: [PATCH] Added support for salted passwords. Added password auto-generation capability. Added Kerberos code. Updated salt generator to be much more random(). --- clients/tools/ldappasswd.c | 626 +++++++++++++++++++++++++------------ 1 file changed, 425 insertions(+), 201 deletions(-) diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c index d5d18e36bd..ce7e3f89a4 100644 --- a/clients/tools/ldappasswd.c +++ b/clients/tools/ldappasswd.c @@ -1,24 +1,26 @@ /* - * Copyright 1998, David E. Storey, All rights reserved. - * This software is not subject to any license of The Murphy Group, Inc. - * or George Mason University. + * Copyright 1998, David E. Storey, All rights reserved. + * This software is not subject to any license of The Murphy Group, Inc. + * or George Mason University. * - * Redistribution and use in source and binary forms are permitted only - * as authorized by the OpenLDAP Public License. A copy of this - * license is available at http://www.OpenLDAP.org/license.html or - * in file LICENSE in the top-level directory of the distribution. + * Redistribution and use in source and binary forms are permitted only + * as authorized by the OpenLDAP Public License. A copy of this + * license is available at http://www.OpenLDAP.org/license.html or + * in file LICENSE in the top-level directory of the distribution. * - * ldappasswd.c - program to modify passwords in an LDAP tree + * ldappasswd.c - program to modify passwords in an LDAP tree * - * Author: David E. Storey + * Author: David E. Storey * - * ToDo: option for referral handling - * cracklib support? - * kerberos support? (is this really necessary?) - * update "shadow" fields? - * create/view/change password policies? - * - * Note: I am totally FOR comments and suggestions! + * ToDo: + * use entry's current hash type + * output ldif update + * option for referral handling? + * salts {ssha},{smd5} + * cracklib support? + * update "shadow" fields? + * update from system? + * create/view/change password policies? */ #include "portable.h" @@ -38,217 +40,404 @@ #include "ldapconfig.h" +#define CEILING(x) ((double)x > (int)x ? (int)x + 1 : (int)x) + #define LDAP_PASSWD_ATTRIB "userPassword" +#define LDAP_PASSWD_CONF DEFAULT_SYSCONFDIR"/passwd.conf" + +#define HS_NONE 0 +#define HS_PLAIN 1 +#define HS_CONV 2 -typedef enum { +typedef enum +{ HASHTYPE_NONE, HASHTYPE_CRYPT, HASHTYPE_MD5, - HASHTYPE_SHA1 -} HashTypes; + HASHTYPE_SMD5, + HASHTYPE_SHA1, + HASHTYPE_SSHA1 +} +HashTypes; + +typedef struct salt_t +{ + unsigned char *salt; + unsigned int len; +} +Salt; -struct hash_t { +typedef struct hash_t +{ char *name; - int namesz; - int (*func)(const char *, char *); + unsigned int namesz; + char *(*func) (const char *, Salt *); + unsigned char takes_salt; HashTypes type; -}; + HashTypes type_salted; + unsigned int default_salt_len; +} +Hash; -const char crypt64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./"; -char *base = NULL; -char *binddn = NULL; -char *bindpw = NULL; -char *ldaphost = "localhost"; -char *pwattr = LDAP_PASSWD_ATTRIB; -char *targetdn = NULL; -char *filtpattern = NULL; -int ldapport = LDAP_PORT; -int noupdates = 0; -int verbose = 0; -int hashtype = HASHTYPE_CRYPT; -int scope = LDAP_SCOPE_SUBTREE; +const unsigned char crypt64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./"; +const unsigned char autogen[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890.,"; +int noupdates = 0; +int verbose = 0; +int want_entryhash = 0; +int auto_gen_pw = 0; /*** functions ***/ /* * if you'd like to write a better salt generator, please, be my guest. - * I just needed *something*. It's actually halfway effective for small, - * two character salts and it can come up with sequentially different - * salts. */ void -crypt_make_salt(char *salt) +make_salt (Salt * salt, unsigned int len) { struct timeval tv; - int i; - char t_salt[5]; - /* grab current time */ - gettimeofday(&tv, (struct timezone *) 0); - i += tv.tv_usec + (int)&salt; - strncpy(t_salt, (char *)&i, sizeof(i)); + if (!salt) + return; + + /* seed random number generator */ + gettimeofday (&tv, NULL); + srand (tv.tv_usec); - for (i = 0; i < sizeof(i); i++) - salt[i] = crypt64[t_salt[i] % (sizeof(crypt64) - 1)]; - salt[i] = '\0'; + salt->len = len; + salt->salt = (unsigned char *) malloc (len); + + for (len = 0; len < salt->len; len++) + salt->salt[len] = (tv.tv_usec ^ rand ()) & 0xff; } -int -hash_none(const char *pw_in, char *pw_out) +char * +gen_pass(unsigned int len) { - strcpy(pw_out, pw_in); - return(1); + int i; + char *newpw = NULL; + Salt salt = {NULL, 0}; + + make_salt(&salt, len); + newpw = (char *)salt.salt; + + for (i = 0; i < len; i++) + newpw[i] = autogen[newpw[i] % (sizeof(autogen) - 1)]; + + return(newpw); } -int -hash_crypt(const char *pw_in, char *pw_out) +char * +hash_none (const char *pw_in, Salt * salt) { - char salt[5]; - crypt_make_salt(salt); - strcpy(pw_out, crypt(pw_in, salt)); - return(1); + return (strdup (pw_in)); } -int -hash_md5(const char *pw_in, char *pw_out) +char * +hash_crypt (const char *pw_in, Salt * salt) +{ + char *crypted_pw = NULL; + if (salt && salt->salt && strlen ((char *) salt->salt) >= 2) + crypted_pw = crypt (pw_in, (char *) salt->salt); + else + { + Salt lsalt; + make_salt (&lsalt, 2); + lsalt.salt[0] = crypt64[lsalt.salt[0] % (sizeof (crypt64) - 1)]; + lsalt.salt[1] = crypt64[lsalt.salt[1] % (sizeof (crypt64) - 1)]; + crypted_pw = crypt (pw_in, (char *) lsalt.salt); + free (lsalt.salt); + } + return (strdup (crypted_pw)); +} + +char * +pw_encode(unsigned char *passwd, Salt *salt, unsigned int len) +{ + int salted = salt && salt->salt && salt->len; + int b64_len = 0; + char *base64digest = NULL; + unsigned char *npasswd = passwd; + + if (salted) + { + npasswd = (unsigned char *)malloc(len + salt->len); + memcpy(npasswd, passwd, len); + memcpy(&npasswd[len], salt->salt, salt->len); + len += salt->len; + } + + b64_len = CEILING (len / 3) * 4 + 1; + base64digest = (char *) malloc (b64_len); + if (lutil_b64_ntop (npasswd, len, base64digest, b64_len) < 0) + { + free(base64digest); + base64digest = NULL; + } + + if (salted) + free(npasswd); + + return(base64digest); +} + +char * +hash_md5 (const char *pw_in, Salt *salt) { lutil_MD5_CTX MD5context; unsigned char MD5digest[16]; - char base64digest[25]; /* ceiling(sizeof(input)/3) * 4 + 1 */ + unsigned char *hashing_pw = (unsigned char *)pw_in; + char *base64digest = NULL; + int tot_len = strlen (pw_in); + int salted = (salt && salt->salt && salt->len); - lutil_MD5Init(&MD5context); - lutil_MD5Update(&MD5context, (unsigned char *)pw_in, strlen(pw_in)); - lutil_MD5Final(MD5digest, &MD5context); - if (lutil_b64_ntop(MD5digest, sizeof(MD5digest), base64digest, sizeof(base64digest)) < 0) - return (0); + /* append salt to password */ + if (salted) + { + hashing_pw = (unsigned char *) malloc (tot_len + salt->len); + memcpy (hashing_pw, pw_in, tot_len); + memcpy (&hashing_pw[tot_len], salt->salt, salt->len); + tot_len += salt->len; + } + + lutil_MD5Init (&MD5context); + lutil_MD5Update (&MD5context, hashing_pw, tot_len); + lutil_MD5Final (MD5digest, &MD5context); + + base64digest = pw_encode(MD5digest, salt, sizeof(MD5digest)); - strcpy(pw_out, base64digest); - return(1); + if (salted) + free (hashing_pw); + + return (base64digest); } -int -hash_sha1(const char *pw_in, char *pw_out) +char * +hash_sha1 (const char *pw_in, Salt * salt) { lutil_SHA1_CTX SHA1context; unsigned char SHA1digest[20]; - char base64digest[29]; /* ceiling(sizeof(input)/3) * 4 + 1 */ + unsigned char *hashing_pw = (unsigned char *)pw_in; + char *base64digest = NULL; + int tot_len = strlen (pw_in); + int salted = (salt && salt->salt); - lutil_SHA1Init(&SHA1context); - lutil_SHA1Update(&SHA1context, (unsigned char *)pw_in, strlen(pw_in)); - lutil_SHA1Final(SHA1digest, &SHA1context); - if (lutil_b64_ntop(SHA1digest, sizeof(SHA1digest), base64digest, sizeof(base64digest)) < 0) - return(0); + /* append salt to password */ + if (salted) + { + hashing_pw = (unsigned char *) malloc (tot_len + salt->len); + memcpy (hashing_pw, pw_in, tot_len); + memcpy (&hashing_pw[tot_len], salt->salt, salt->len); + tot_len += salt->len; + } + + lutil_SHA1Init (&SHA1context); + lutil_SHA1Update (&SHA1context, hashing_pw, tot_len); + lutil_SHA1Final (SHA1digest, &SHA1context); + + base64digest = pw_encode(SHA1digest, salt, sizeof(SHA1digest)); - strcpy(pw_out, base64digest); - return(1); + if (salted) + free (hashing_pw); + + return (base64digest); } -static struct hash_t hashes[] = { - {"none", 4, hash_none, HASHTYPE_NONE}, - {"crypt", 5, hash_crypt, HASHTYPE_CRYPT}, - {"md5", 3, hash_md5, HASHTYPE_MD5}, - {"sha", 3, hash_sha1, HASHTYPE_SHA1}, - {NULL, 0, NULL, HASHTYPE_NONE} +static Hash hashes[] = +{ + {"none", 4, hash_none, 0, HASHTYPE_NONE, HASHTYPE_NONE, 0}, + {"crypt", 5, hash_crypt, 1, HASHTYPE_CRYPT, HASHTYPE_CRYPT, 2}, + {"md5", 3, hash_md5, 0, HASHTYPE_MD5, HASHTYPE_SMD5, 0}, + {"smd5", 4, hash_md5, 1, HASHTYPE_SMD5, HASHTYPE_SMD5, 4}, + {"sha", 3, hash_sha1, 0, HASHTYPE_SHA1, HASHTYPE_SSHA1, 0}, + {"ssha", 4, hash_sha1, 1, HASHTYPE_SSHA1, HASHTYPE_SSHA1, 4}, + {NULL, 0, NULL, 0, HASHTYPE_NONE, HASHTYPE_NONE, 0} }; int -modify_dn(LDAP *ld, char *targetdn, char *newpw) +modify_dn (LDAP * ld, char *targetdn, char *pwattr, char *oldpw, + char *newpw, HashTypes htype, Salt * salt) { int ret = 0; - char hashed_pw[128] = {'\0'}; - char buf[128] = {'\0'}; - char *strvals[2] = {buf, NULL}; - LDAPMod mod, *mods[2] = {&mod, NULL}; + int salted = salt->salt ? 1 : 0; + int want_salt = salt->len && !salted; + char *buf = NULL; + char *hashed_pw = NULL; + char *strvals[2] = {NULL, NULL}; + LDAPMod mod, *mods[2] = {&mod, NULL}; if (!ld || !targetdn || !newpw) - return(1); + return (1); + + /* auto-generate password */ + if (auto_gen_pw) + newpw = gen_pass(auto_gen_pw); + + /* handle salt */ + if (want_salt) + { + make_salt (salt, salt->len); + htype = hashes[htype].type_salted; + } + else if (hashes[htype].default_salt_len) + { + /* user chose a salted hash and needs a salt */ + if (!salted) + { + want_salt++; + salt->len = hashes[htype].default_salt_len; + make_salt(salt, salt->len); + } + } /* hash password */ - hashes[hashtype].func(newpw, hashed_pw); - if (hashtype) - sprintf(buf, "{%s}%s", hashes[hashtype].name, hashed_pw); + hashed_pw = hashes[htype].func (newpw, salt->len ? salt : NULL); + + /* return salt back to it's original state */ + if (want_salt) + { + free (salt->salt); + salt->salt = NULL; + } + + buf = (char *) malloc (hashes[htype].namesz + 3 + strlen (hashed_pw)); + if (htype) + sprintf (buf, "{%s}%s", hashes[htype].name, hashed_pw); else - sprintf(buf, "%s", hashed_pw); + sprintf (buf, "%s", hashed_pw); if (verbose > 0) { - printf("%s", targetdn); + printf ("%s", targetdn); if (verbose > 1) { - printf(":%s", buf); + printf (":%s", buf); if (verbose > 2) - printf(":%s", newpw); + printf (":%s", newpw); } - printf("\n"); + printf ("\n"); } - mod.mod_vals.modv_strvals = strvals; + strvals[0] = buf; + mod.mod_vals.modv_strvals = strvals; mod.mod_type = pwattr; mod.mod_op = LDAP_MOD_REPLACE; - if (!noupdates && (ret = ldap_modify_s(ld, targetdn, mods)) != LDAP_SUCCESS) - ldap_perror(ld, "ldap_modify_s"); - return(ret); + if (!noupdates && (ret = ldap_modify_s (ld, targetdn, mods)) != LDAP_SUCCESS) + ldap_perror (ld, "ldap_modify_s"); + + free (hashed_pw); + free (buf); + return (ret); } void -usage(char *s) +usage (char *s) { - fprintf(stderr, "usage: %s [options] [filter]\n", s); - fprintf(stderr, "\t-a attrib password attribute (default: userPassword)\n"); - fprintf(stderr, "\t-b basedn basedn to perform searches\n"); - fprintf(stderr, "\t-c hash hash type: none, crypt, md5, sha (default: crypt)\n"); - fprintf(stderr, "\t-D binddn bind dn\n"); - fprintf(stderr, "\t-d level debugging level\n"); - fprintf(stderr, "\t-h host ldap server (default: localhost)\n"); - fprintf(stderr, "\t-l time time limit\n"); - fprintf(stderr, "\t-n make no modifications\n"); - fprintf(stderr, "\t-p port ldap port\n"); - fprintf(stderr, "\t-s scope search scope: base, one, sub (default: sub)\n"); - fprintf(stderr, "\t-t targetdn dn to change password\n"); - fprintf(stderr, "\t-W newpass new password\n"); - fprintf(stderr, "\t-w [passwd] bind password (for simple authentication)\n"); - fprintf(stderr, "\t-v verbose\n"); - fprintf(stderr, "\t-z size size limit\n"); - exit(1); + fprintf (stderr, "Usage: %s [options] [filter]\n", s); + fprintf (stderr, " -a attrib\tpassword attribute (default: %s)\n", LDAP_PASSWD_ATTRIB); + fprintf (stderr, " -b basedn\tbasedn to perform searches\n"); +/* fprintf (stderr, " -C\t\tuse entry's current hash mechanism\n"); */ + fprintf (stderr, " -D binddn\tbind dn\n"); + fprintf (stderr, " -d level\tdebugging level\n"); + fprintf (stderr, " -E\t\tprompt for new password\n"); + fprintf (stderr, " -e passwd\tnew password\n"); + fprintf (stderr, " -g passlen\tauto-generate passwords with length pwlen\n"); + fprintf (stderr, " -H hash\thash type (default: crypt)\n"); + fprintf (stderr, " -h host\tldap server (default: localhost)\n"); +#ifdef HAVE_KERBEROS + fprintf (stderr, " -K\t\tuse Kerberos step 1\n"); + fprintf (stderr, " -k\t\tuse Kerberos\n"); +#endif + fprintf (stderr, " -l time\ttime limit\n"); + fprintf (stderr, " -n\t\tmake no modifications\n"); + fprintf (stderr, " -p port\tldap port\n"); + fprintf (stderr, " -s scope\tsearch scope: base, one, sub (default: sub)\n"); + fprintf (stderr, " -t targetdn\tdn to change password\n"); + fprintf (stderr, " -v\t\tverbose (more v's, more verbose)\n"); + fprintf (stderr, " -W\t\tprompt for bind password\n"); + fprintf (stderr, " -w passwd\tbind password (for simple authentication)\n"); + fprintf (stderr, " -Y saltlen\tsalt length to use\n"); +/* fprintf (stderr, " -y salt\tsalt to use\n"); */ + fprintf (stderr, " -z size\tsize limit\n"); + exit (1); } int -main(int argc, char *argv[]) +main (int argc, char *argv[]) { + char *base = NULL; + char *binddn = NULL; + char *bindpw = NULL; + char *filtpattern = NULL; + char *ldaphost = "localhost"; + char *targetdn = NULL; + char *pwattr = LDAP_PASSWD_ATTRIB; char *newpw = NULL; + int authmethod = LDAP_AUTH_SIMPLE; + int hashtype = HASHTYPE_CRYPT; int i, j; + int ldapport = LDAP_PORT; + int scope = LDAP_SCOPE_SUBTREE; int sizelimit = LDAP_NO_LIMIT; int timelimit = LDAP_NO_LIMIT; int want_bindpw = 0; + int want_newpw = 0; LDAP *ld; + Salt salt; - while ((i = getopt(argc, argv, "D:W:a:b:c:d:h:l:np:s:t:vw::z:")) != EOF) + salt.salt = NULL; + salt.len = 0; + + if (argc == 1) + usage(argv[0]); + + while ((i = getopt (argc, argv, "a:b:C:D:d:Ee:g:H:h:Kkl:np:s:t:vWw:Y:y:z:")) != EOF) { - switch(i) - { - case 'D': /* bind distinguished name */ - binddn = strdup(optarg); + switch (i) + { + case 'a': /* password attribute */ + pwattr = strdup (optarg); break; - case 'W': /* new password */ - newpw = strdup(optarg); + case 'b': /* base search dn */ + base = strdup (optarg); break; - case 'a': /* password attribute */ - pwattr = strdup(optarg); + case 'C': + want_entryhash++; break; - case 'b': /* base search dn */ - base = strdup(optarg); + case 'D': /* bind distinguished name */ + binddn = strdup (optarg); break; - case 'c': /* hashes */ + case 'd': /* debugging option */ +#ifdef LDAP_DEBUG + ldap_debug = lber_debug = atoi (optarg); /* */ +#else + fprintf (stderr, "compile with -DLDAP_DEBUG for debugging\n"); +#endif + break; + + case 'E': /* prompt for new password */ + want_newpw++; + break; + + case 'e': /* new password */ + newpw = strdup (optarg); + break; + + case 'g': + auto_gen_pw = strtol(optarg, NULL, 10); + break; + + case 'H': /* hashes */ for (j = 0; hashes[j].name; j++) { - if (!strncasecmp(optarg, hashes[j].name, hashes[j].namesz)) + if (!strncasecmp (optarg, hashes[j].name, hashes[j].namesz)) { hashtype = hashes[j].type; break; @@ -257,75 +446,94 @@ main(int argc, char *argv[]) if (!hashes[j].name) { - fprintf(stderr, "hash type: %s is unknown\n", optarg); - usage(argv[0]); + fprintf (stderr, "hash type: %s is unknown\n", optarg); + usage (argv[0]); } break; - case 'd': /* debugging option */ -#ifdef LDAP_DEBUG - ldap_debug = lber_debug = atoi(optarg); /* */ + case 'h': /* ldap host */ + ldaphost = strdup (optarg); + break; + + case 'K': /* use kerberos bind, 1st part only */ +#ifdef HAVE_KERBEROS + authmethod = LDAP_AUTH_KRBV41; #else - fprintf(stderr, "compile with -DLDAP_DEBUG for debugging\n"); + fprintf(stderr, "%s was not compiled with Kerberos support\n", argv[0]); #endif - break; + break; - case 'h': /* ldap host */ - ldaphost = strdup(optarg); - break; + case 'k': /* use kerberos bind */ +#ifdef HAVE_KERBEROS + authmethod = LDAP_AUTH_KRBV4; +#else + fprintf(stderr, "%s was not compiled with Kerberos support\n", argv[0]); +#endif + break; - case 'l': /* time limit */ - timelimit = strtol(optarg, NULL, 10); + case 'l': /* time limit */ + timelimit = strtol (optarg, NULL, 10); break; - case 'n': /* don't update entry(s) */ + case 'n': /* don't update entry(s) */ noupdates++; break; - case 'p': /* ldap port */ - ldapport = strtol(optarg, NULL, 10); + case 'p': /* ldap port */ + ldapport = strtol (optarg, NULL, 10); break; - case 's': /* scope */ - if (strncasecmp(optarg, "base", 4) == 0) + case 's': /* scope */ + if (strncasecmp (optarg, "base", 4) == 0) scope = LDAP_SCOPE_BASE; - else if (strncasecmp(optarg, "one", 3) == 0) + else if (strncasecmp (optarg, "one", 3) == 0) scope = LDAP_SCOPE_ONELEVEL; - else if (strncasecmp(optarg, "sub", 3) == 0) + else if (strncasecmp (optarg, "sub", 3) == 0) scope = LDAP_SCOPE_SUBTREE; - else { - fprintf(stderr, "scope should be base, one, or sub\n" ); - usage(argv[0]); + else + { + fprintf (stderr, "scope should be base, one, or sub\n"); + usage (argv[0]); } break; - case 't': /* target dn */ - targetdn = strdup(optarg); + case 't': /* target dn */ + targetdn = strdup (optarg); break; - case 'v': /* verbose */ + case 'v': /* verbose */ verbose++; break; - case 'w': /* bind password */ - if (optarg) - bindpw = strdup(optarg); - else - want_bindpw++; - break; + case 'W': /* promt for bind password */ + want_bindpw++; + break; + + case 'w': /* bind password */ + bindpw = strdup (optarg); + break; + + case 'Y': /* salt length */ + salt.len = strtol (optarg, NULL, 10); + break; + + case 'y': /* user specified salt */ + salt.len = strlen (optarg); + salt.salt = (unsigned char *) strdup (optarg); + break; - case 'z': /* time limit */ - sizelimit = strtol(optarg, NULL, 10); + case 'z': /* time limit */ + sizelimit = strtol (optarg, NULL, 10); break; default: - usage(argv[0]); + usage (argv[0]); } } /* grab filter */ if (!(argc - optind < 1)) - filtpattern = strdup(argv[optind]); + filtpattern = strdup (argv[optind]); /* check for target(s) */ if (!filtpattern && !targetdn) @@ -333,70 +541,86 @@ main(int argc, char *argv[]) /* handle bind password */ if (want_bindpw) - bindpw = strdup(getpass("Enter LDAP password: ")); + bindpw = strdup (getpass ("Enter LDAP password: ")); /* handle new password */ if (!newpw) { char *cknewpw; - newpw = strdup(getpass("New password: ")); - cknewpw = getpass("Re-enter new password: "); + newpw = strdup (getpass ("New password: ")); + cknewpw = getpass ("Re-enter new password: "); - if (strncmp(newpw, cknewpw, strlen(newpw))) + if (strncmp (newpw, cknewpw, strlen (newpw))) { - fprintf(stderr, "passwords do not match\n"); - return(1); + fprintf (stderr, "passwords do not match\n"); + return (1); } } /* connect to server */ - if ((ld = ldap_open(ldaphost, ldapport)) == NULL) + if ((ld = ldap_open (ldaphost, ldapport)) == NULL) { - perror(ldaphost); - return(1); + perror (ldaphost); + return (1); } /* set options */ - ldap_set_option(ld, LDAP_OPT_TIMELIMIT, (void *)&timelimit); - ldap_set_option(ld, LDAP_OPT_SIZELIMIT, (void *)&sizelimit); + ldap_set_option (ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit); + ldap_set_option (ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit); - /* authenticate to server */ - if (ldap_bind_s(ld, binddn, bindpw, LDAP_AUTH_SIMPLE) != LDAP_SUCCESS) + /* authenticate to server */ + if (ldap_bind_s (ld, binddn, bindpw, authmethod) != LDAP_SUCCESS) { - ldap_perror(ld, "ldap_bind"); - return(1); + ldap_perror (ld, "ldap_bind"); + return (1); + } + + if (targetdn) + { + if (want_entryhash) + { + fprintf (stderr, "insert code here (this path not implemented yet)\n"); + return (1); + } + else + modify_dn (ld, targetdn, pwattr, NULL, newpw, hashtype, &salt); } if (filtpattern) { char filter[BUFSIZ]; LDAPMessage *result = NULL, *e = NULL; - char *attrs[] = {"dn", NULL}; + char *attrs[3] = {"dn", NULL, NULL}; + attrs[1] = pwattr; /* search */ - sprintf(filter, "%s", filtpattern); - i = ldap_search_s(ld, base, scope, filter, attrs, 1, &result); - if (i != LDAP_SUCCESS && i != LDAP_TIMELIMIT_EXCEEDED && i != LDAP_SIZELIMIT_EXCEEDED) + sprintf (filter, "%s", filtpattern); + i = ldap_search_s (ld, base, scope, filter, attrs, 0, &result); + if (i != LDAP_SUCCESS && + i != LDAP_TIMELIMIT_EXCEEDED && + i != LDAP_SIZELIMIT_EXCEEDED) { - ldap_perror(ld, "ldap_search_s"); - return(1); + ldap_perror (ld, "ldap_search_s"); + return (1); } - for (e = ldap_first_entry(ld, result); e; e = ldap_next_entry(ld, e)) + for (e = ldap_first_entry (ld, result); e; e = ldap_next_entry (ld, e)) { - char *dn = ldap_get_dn(ld, e); + char *dn = ldap_get_dn (ld, e); if (dn) { - modify_dn(ld, dn, newpw); - free(dn); + struct berval **pw_vals = ldap_get_values_len (ld, e, pwattr); + modify_dn (ld, dn, pwattr, + pw_vals ? pw_vals[0]->bv_val : NULL, + newpw, hashtype, &salt); + if (pw_vals) + ldap_value_free_len (pw_vals); + free (dn); } } } - if (targetdn) - modify_dn(ld, targetdn, newpw); - /* disconnect from server */ - ldap_unbind(ld); - return(0); + ldap_unbind (ld); + return (0); } -- 2.39.5