From 10cbeba93609c07f69b357738288436848ea34bf Mon Sep 17 00:00:00 2001 From: Dave Storey Date: Mon, 14 Dec 1998 18:36:51 +0000 Subject: [PATCH] Added Kerberos support. Added Password auto-generation. Added salts for md5 and sha. Rewrote make_salt(). Made ldap-devel conformity changes. --- clients/tools/ldappasswd.c | 656 +++++++++++++++++++++++++------------ 1 file changed, 444 insertions(+), 212 deletions(-) diff --git a/clients/tools/ldappasswd.c b/clients/tools/ldappasswd.c index d5d18e36bd..ea440a43c8 100644 --- a/clients/tools/ldappasswd.c +++ b/clients/tools/ldappasswd.c @@ -11,18 +11,11 @@ * ldappasswd.c - program to modify passwords in an LDAP tree * * 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! */ #include "portable.h" +#include #include #include #include @@ -38,217 +31,421 @@ #include "ldapconfig.h" +/* local macros */ +#define CEILING(x) ((double)x > (int)x ? (int)x + 1 : (int)x) +#define STRDUP(x) (x ? strcpy(malloc(strlen(x) + 1), x) : NULL) + #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; - -struct hash_t { - char *name; - int namesz; - int (*func)(const char *, char *); - HashTypes type; -}; + HASHTYPE_SMD5, + HASHTYPE_SHA1, + HASHTYPE_SSHA1 +} +HashTypes; -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; +typedef struct salt_t +{ + unsigned char *salt; + unsigned int len; +} +Salt; + +typedef struct hash_t +{ + char *name; + unsigned int namesz; + char *(*func) (const char *, Salt *); + unsigned char takes_salt; + HashTypes type; + HashTypes type_salted; + unsigned int default_salt_len; +} +Hash; + +static int noupdates = 0; +static int verbose = 0; +static int want_entryhash = 0; +static int auto_gen_pw = 0; /*** functions ***/ +/* + * pw_encode() essentially base64 encodes a password and it's salt + */ + +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); +} + /* * 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; + + if (!salt) + return; + + /* seed random number generator */ + gettimeofday (&tv, NULL); + srand (tv.tv_usec); + + salt->len = len; + salt->salt = (unsigned char *)malloc (len); + + for (len = 0; len < salt->len; len++) + salt->salt[len] = (tv.tv_usec ^ rand ()) & 0xff; +} + +/* + * password generator + */ + +char * +gen_pass (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)); - - for (i = 0; i < sizeof(i); i++) - salt[i] = crypt64[t_salt[i] % (sizeof(crypt64) - 1)]; - salt[i] = '\0'; + const unsigned char autogen[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890.,"; + int i; + Salt salt = {NULL, 0}; + + make_salt (&salt, len); + for (i = 0; i < len; i++) + salt.salt[i] = autogen[salt.salt[i] % (sizeof (autogen) - 1)]; + + return ((char *)salt.salt); } -int -hash_none(const char *pw_in, char *pw_out) +char * +hash_none (const char *pw_in, Salt * salt) { - strcpy(pw_out, pw_in); - return(1); + return (STRDUP (pw_in)); } -int -hash_crypt(const char *pw_in, char *pw_out) +char * +hash_crypt (const char *pw_in, Salt * salt) { - char salt[5]; - crypt_make_salt(salt); - strcpy(pw_out, crypt(pw_in, salt)); - return(1); + const unsigned char crypt64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./"; + char *crypted_pw = NULL; + Salt lsalt; + + if (salt && salt->salt && strlen ((char *)salt->salt) >= 2) + { + /* sanity check */ + if (!(isalnum(salt->salt[0]) || salt->salt[0] == '.' || salt->salt[0] == '/')) + salt->salt[0] = crypt64[salt->salt[0] % (sizeof (crypt64) - 1)]; + if (!(isalnum(salt->salt[1]) || salt->salt[1] == '.' || salt->salt[1] == '/')) + salt->salt[1] = crypt64[salt->salt[1] % (sizeof (crypt64) - 1)]; + + crypted_pw = crypt (pw_in, (char *)salt->salt); + } + else + { + 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)); } -int -hash_md5(const char *pw_in, char *pw_out) +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 */ - - 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); - - strcpy(pw_out, base64digest); - return(1); + lutil_MD5_CTX MD5context; + unsigned char MD5digest[16]; + unsigned char *hashing_pw = (unsigned char *)pw_in; + char *base64digest = NULL; + int tot_len = strlen (pw_in); + int salted = (salt && salt->salt && salt->len); + + /* 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)); + + 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 */ - - 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); - - strcpy(pw_out, base64digest); - return(1); + lutil_SHA1_CTX SHA1context; + unsigned char SHA1digest[20]; + unsigned char *hashing_pw = (unsigned char *)pw_in; + char *base64digest = NULL; + int tot_len = strlen (pw_in); + int salted = (salt && salt->salt); + + /* 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)); + + 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 ret = 0; + 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; + LDAPMod *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"); } + 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 *newpw = NULL; - int i, j; - int sizelimit = LDAP_NO_LIMIT; - int timelimit = LDAP_NO_LIMIT; - int want_bindpw = 0; - LDAP *ld; - - while ((i = getopt(argc, argv, "D:W:a:b:c:d:h:l:np:s:t:vw::z:")) != EOF) + char *base = NULL; + char *binddn = NULL; + char *bindpw = NULL; + char *filtpattern = NULL; + char *ldaphost = NULL; + 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 = 0; + 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; + + 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) + switch (i) { - case 'D': /* bind distinguished name */ - binddn = strdup(optarg); + case 'a': /* password attribute */ + pwattr = STRDUP (optarg); + break; + + case 'b': /* base search dn */ + base = STRDUP (optarg); + break; + + case 'C': + want_entryhash++; + break; + + case 'D': /* bind distinguished name */ + binddn = STRDUP (optarg); + break; + + 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 'W': /* new password */ - newpw = strdup(optarg); + case 'E': /* prompt for new password */ + want_newpw++; break; - case 'a': /* password attribute */ - pwattr = strdup(optarg); + case 'e': /* new password */ + newpw = STRDUP (optarg); break; - case 'b': /* base search dn */ - base = strdup(optarg); + case 'g': + auto_gen_pw = strtol (optarg, NULL, 10); break; - case 'c': /* hashes */ + 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 +454,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; - case 'h': /* ldap host */ - ldaphost = strdup(optarg); + 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 'z': /* time limit */ - sizelimit = strtol(optarg, NULL, 10); + 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); 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 +549,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"); + exit (1); } } /* connect to server */ - if ((ld = ldap_open(ldaphost, ldapport)) == NULL) + if ((ld = ldap_open (ldaphost, ldapport)) == NULL) { - perror(ldaphost); - return(1); + perror (ldaphost); + exit (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) + if (ldap_bind_s (ld, binddn, bindpw, authmethod) != LDAP_SUCCESS) + { + ldap_perror (ld, "ldap_bind"); + exit (1); + } + + if (targetdn) { - ldap_perror(ld, "ldap_bind"); - return(1); + if (want_entryhash) + { + /* insert code here =) */ + } + 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 filter[BUFSIZ]; + LDAPMessage *result = NULL, *e = 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"); + exit (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); + exit(0); + + /* unreached */ + return (0); } -- 2.39.5