* Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
-/*
- * 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.
- *
- * ldappasswd.c - program to modify passwords in an LDAP tree
- *
- * Author: David E. Storey <dave@tamos.net>
- */
#include "portable.h"
#include <ac/string.h>
#include <ac/time.h>
#include <ac/unistd.h>
-#include <ac/crypt.h>
-#include <lber.h>
#include <ldap.h>
-#include <lutil.h>
-#include <lutil_md5.h>
-#include <lutil_sha1.h>
#include "ldap_defaults.h"
-/* local macros */
-#define LDAP_PASSWD_ATTRIB "userPassword"
-#define LDAP_PASSWD_CONF LDAP_SYSCONFDIR LDAP_DIRSEP "passwd.conf"
-
-#define HS_NONE 0
-#define HS_PLAIN 1
-#define HS_CONV 2
-
-typedef enum
-{
- HASHTYPE_NONE,
- HASHTYPE_CRYPT,
- HASHTYPE_MD5,
- HASHTYPE_SMD5,
- HASHTYPE_SHA1,
- HASHTYPE_SSHA1
-}
-HashTypes;
-
-typedef struct salt_t
-{
- unsigned char *salt;
- unsigned int len;
-}
-Salt;
-
-typedef struct hash_t
-{
- const 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 its salt
- */
-
-static 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 = LUTIL_BASE64_ENCODE_LEN(len) + 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.
- */
-
-static void
-make_salt (Salt * salt, unsigned int len)
-{
-
- if (!salt)
- return;
-
- salt->len = len;
- salt->salt = (unsigned char *)malloc (len);
-
- for (len = 0; len < salt->len; len++)
- salt->salt[len] = rand () & 0xff;
-}
-
-/*
- * password generator
- */
-
-static char *
-gen_pass (unsigned int len)
-{
- static const unsigned char autogen[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890.,";
- unsigned int i;
- Salt salt;
-
- salt.salt = NULL;
- salt.len = 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);
-}
-
-#ifdef SLAPD_CLEARTEXT
-static char *
-hash_none (const char *pw_in, Salt * salt)
-{
- return (strdup (pw_in));
-}
-#endif
-
-#ifdef SLAPD_CRYPT
-static char *
-hash_crypt (const char *pw_in, Salt * salt)
-{
- static 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));
-}
-#endif
-
-static char *
-hash_md5 (const char *pw_in, Salt * salt)
-{
- lutil_MD5_CTX MD5context;
- unsigned char MD5digest[16];
-
- lutil_MD5Init (&MD5context);
- lutil_MD5Update (&MD5context,
- (const unsigned char *)pw_in, strlen(pw_in));
- if (salt && salt->salt && salt->len)
- lutil_MD5Update (&MD5context, salt->salt, salt->len);
- lutil_MD5Final (MD5digest, &MD5context);
-
- return (pw_encode (MD5digest, salt, sizeof (MD5digest)));
-}
-
-static char *
-hash_sha1 (const char *pw_in, Salt * salt)
-{
- lutil_SHA1_CTX SHA1context;
- unsigned char SHA1digest[20];
-
- lutil_SHA1Init (&SHA1context);
- lutil_SHA1Update (&SHA1context,
- (const unsigned char *)pw_in, strlen(pw_in));
- if (salt && salt->salt && salt->len)
- lutil_SHA1Update (&SHA1context, salt->salt, salt->len);
- lutil_SHA1Final (SHA1digest, &SHA1context);
-
- return (pw_encode (SHA1digest, salt, sizeof (SHA1digest)));
-}
-
-static const Hash hashes[] =
-{
-#ifdef SLAPD_CLEARTEXT
- {"none", 4, hash_none, 0, HASHTYPE_NONE, HASHTYPE_NONE, 0},
-#endif
-#ifdef SLAPD_CRYPT
- {"crypt", 5, hash_crypt, 1, HASHTYPE_CRYPT, HASHTYPE_CRYPT, 2},
-#endif
- {"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}
-};
-
-static int
-modify_dn (LDAP * ld, char *targetdn, char *pwattr, char *oldpw,
- char *newpw, HashTypes htype, Salt * salt)
-{
- 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];
- LDAPMod mod, *mods[2];
-
- if (!ld || !targetdn || !newpw)
- 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 */
- hashed_pw = hashes[htype].func (newpw, salt->len ? salt : NULL);
-
- /* return salt back to its 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);
-
- if (verbose > 0)
- {
- printf ("%s", targetdn);
- if (verbose > 1)
- {
- printf (":%s", buf);
- if (verbose > 2)
- printf (":%s", newpw);
- }
- printf ("\n");
- }
-
- strvals[0] = buf;
- strvals[1] = NULL;
- mod.mod_values = strvals;
- mod.mod_type = pwattr;
- mod.mod_op = LDAP_MOD_REPLACE;
- mods[0] = &mod;
- mods[1] =NULL;
-
- if (!noupdates && (ret = ldap_modify_s (ld, targetdn, mods)) != LDAP_SUCCESS)
- ldap_perror (ld, "ldap_modify");
-
- free (hashed_pw);
- free (buf);
- return (ret);
-}
static void
usage(const char *s)
{
- fprintf (stderr, "Usage: %s [options] [filter]\n", s);
- fprintf (stderr, " -a attrib\tpassword attribute (default: " LDAP_PASSWD_ATTRIB ")\n");
- 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 version\tprotocol version (2 or 3)\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");
+ fprintf(stderr,
+ "Usage: %s [options]\n"
+ " -D binddn\tbind dn\tREQUIRED\n"
+ " -d level\tdebugging level\n"
+ " -h host\tldap server (default: localhost)\n"
+ " -n\t\tmake no modifications\n"
+ " -p port\tldap port\n"
+ " -s secret\tnew password\n"
+ " -v\t\tincrease verbosity\n"
+ " -W\t\tprompt for bind password\n"
+ " -w passwd\tbind password (for simple authentication)\n"
+ , s );
+
exit( EXIT_FAILURE );
}
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 = NULL;
- char *targetdn = NULL;
- char *pwattr = LDAP_PASSWD_ATTRIB;
- char *newpw = NULL;
- int authmethod = LDAP_AUTH_SIMPLE;
- int hashtype = HASHTYPE_CRYPT;
+ int rc;
+ char *binddn = NULL;
+ char *bindpw = NULL;
+ char *ldaphost = NULL;
+ char *newpw = NULL;
+ int noupdates = 0;
int i, j;
int ldapport = 0;
int debug = 0;
- int scope = LDAP_SCOPE_SUBTREE;
- int sizelimit = -1;
- int timelimit = -1;
int version = -1;
int want_bindpw = 0;
- int want_newpw = 0;
LDAP *ld;
- Salt salt;
+ struct berval cred;
+ struct berval *bv = NULL;
+ BerElement *ber;
- salt.salt = NULL;
- salt.len = 0;
+ char *retoid;
+ struct berval *retdata;
if (argc == 1)
usage (argv[0]);
- while ((i = getopt (argc, argv, "a:b:C:D:d:Ee:g:H:h:Kkl:nP:p:s:t:vWw:Y:y:z:")) != EOF)
+ while( (i = getopt( argc, argv,
+ "D:d:h:np:s:vWw:" )) != EOF )
{
- switch (i)
- {
- case 'a': /* password attribute */
- pwattr = strdup (optarg);
- break;
-
- case 'b': /* base search dn */
- base = strdup (optarg);
- break;
-
- case 'C':
- want_entryhash++;
- break;
-
+ switch (i) {
case 'D': /* bind distinguished name */
binddn = strdup (optarg);
break;
debug |= atoi (optarg);
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))
- {
- hashtype = hashes[j].type;
- break;
- }
- }
-
- if (!hashes[j].name)
- {
- fprintf (stderr, "hash type: %s is unknown\n", optarg);
- usage (argv[0]);
- }
- break;
-
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, "%s was not compiled with Kerberos support\n", argv[0]);
- usage (argv[0]);
-#endif
- 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]);
- usage (argv[0]);
-#endif
- break;
-
- case 'l': /* time limit */
- timelimit = strtol (optarg, NULL, 10);
- break;
-
case 'n': /* don't update entry(s) */
noupdates++;
break;
- case 'P':
- switch( atoi( optarg ) ) {
- case 2:
- version = LDAP_VERSION2;
- break;
- case 3:
- version = LDAP_VERSION3;
- break;
- default:
- fprintf( stderr, "protocol version should be 2 or 3\n" );
- usage( argv[0] );
- }
- break;
-
case 'p': /* ldap port */
- ldapport = strtol (optarg, NULL, 10);
+ ldapport = strtol( optarg, NULL, 10 );
break;
- case 's': /* scope */
- if (strcasecmp (optarg, "base") == 0)
- scope = LDAP_SCOPE_BASE;
- else if (strcasecmp (optarg, "one") == 0)
- scope = LDAP_SCOPE_ONELEVEL;
- else if (strcasecmp (optarg, "sub") == 0)
- scope = LDAP_SCOPE_SUBTREE;
- else
- {
- fprintf (stderr, "scope should be base, one, or sub\n");
- usage (argv[0]);
- }
- break;
-
- case 't': /* target dn */
- targetdn = strdup (optarg);
+ case 's': /* new password (secret) */
+ newpw = strdup (optarg);
break;
case 'v': /* verbose */
verbose++;
break;
- case 'W': /* promt for bind password */
+ case 'W': /* prompt for bind password */
want_bindpw++;
break;
}
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);
- break;
default:
usage (argv[0]);
}
}
- /* grab filter */
- if (!(argc - optind < 1))
- filtpattern = strdup (argv[optind]);
-
- /* check for target(s) */
- if (!filtpattern && !targetdn)
- targetdn = binddn;
-
- /* handle bind password */
- if (want_bindpw)
- bindpw = strdup (getpass ("Enter LDAP password: "));
-
- /* handle new password */
- if (!newpw)
- {
+ if( newpw == NULL ) {
+ /* prompt for new password */
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)))
- {
- fprintf (stderr, "passwords do not match\n");
- return ( EXIT_FAILURE );
+ if( strncmp( newpw, cknewpw, strlen(newpw) )) {
+ fprintf( stderr, "passwords do not match\n" );
+ return EXIT_FAILURE;
}
}
+ if( binddn == NULL ) {
+ fprintf( stderr, "no bind DN specified\n" );
+ return EXIT_FAILURE;
+ }
+
+ /* handle bind password */
+ if (want_bindpw) {
+ fprintf( stderr, "Bind DN: %s\n", binddn );
+ bindpw = strdup( getpass("Enter bind password: "));
+ }
+
if ( debug ) {
if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
#ifdef SIGPIPE
(void) SIGNAL( SIGPIPE, SIG_IGN );
#endif
- /* seed random number generator */
-
-#ifdef HAVE_GETTIMEOFDAY
- /* this is of questionable value
- * gettimeofday may not provide much usec
- */
- {
- struct timeval tv;
- gettimeofday (&tv, NULL);
- srand(tv.tv_sec * (tv.tv_usec + 1));
- }
-#else
- /* The traditional seed */
- srand((unsigned)time( NULL ));
-#endif
/* connect to server */
- if ((ld = ldap_init (ldaphost, ldapport)) == NULL)
- {
- perror ("ldap_init");
- return ( EXIT_FAILURE );
+ if ((ld = ldap_init( ldaphost, ldapport )) == NULL) {
+ perror("ldap_init");
+ return EXIT_FAILURE;
}
- /* set options */
- if (timelimit != -1 &&
- ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *) &timelimit ) != LDAP_OPT_SUCCESS )
- {
- fprintf( stderr, "Could not set LDAP_OPT_TIMELIMIT %d\n", timelimit );
- }
- if (sizelimit != -1 &&
- ldap_set_option( ld, LDAP_OPT_SIZELIMIT, (void *) &sizelimit ) != LDAP_OPT_SUCCESS )
- {
- fprintf( stderr, "Could not set LDAP_OPT_SIZELIMIT %d\n", sizelimit );
- }
-
- /* this seems prudent */
- {
- int deref = LDAP_DEREF_NEVER;
- ldap_set_option( ld, LDAP_OPT_DEREF, &deref);
- }
/* don't chase referrals */
ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF );
- if (version != -1 &&
- ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != LDAP_OPT_SUCCESS )
- {
+ version = 3;
+ rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
+
+ if(rc != LDAP_OPT_SUCCESS ) {
fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
}
- /* authenticate to server */
- if (ldap_bind_s (ld, binddn, bindpw, authmethod) != LDAP_SUCCESS)
- {
- ldap_perror (ld, "ldap_bind");
- return ( EXIT_FAILURE );
+ rc = ldap_bind_s( ld, binddn, bindpw, LDAP_AUTH_SIMPLE );
+
+ if ( rc != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_bind" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
}
- if (targetdn)
- {
- if (want_entryhash)
- {
- /* insert code here =) */
- }
- else
- modify_dn (ld, targetdn, pwattr, NULL, newpw, hashtype, &salt);
+ /* build change password control */
+ ber = ber_alloc_t( LBER_USE_DER );
+
+ if( ber == NULL ) {
+ perror( "ber_alloc_t" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
}
- if (filtpattern)
- {
- char filter[BUFSIZ];
- LDAPMessage *result = NULL, *e;
- char *attrs[2];
- attrs[0] = pwattr;
- attrs[1] = NULL;
-
- /* search */
- 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");
- return ( EXIT_FAILURE );
- }
+ ber_printf( ber, "{es}",
+ (ber_int_t) 0,
+ newpw );
- for (e = ldap_first_entry (ld, result); e; e = ldap_next_entry (ld, e))
- {
- char *dn = ldap_get_dn (ld, e);
- if (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);
- }
- }
+ rc = ber_flatten( ber, &bv );
+
+ if( rc < 0 ) {
+ perror( "ber_flatten" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
}
+ ber_free( ber, 1 );
+
+ rc = ldap_extended_operation_s( ld,
+ LDAP_EXOP_X_MODIFY_PASSWD, bv,
+ NULL, NULL,
+ &retoid, &retdata );
+
+ ber_bvfree( bv );
+
+ if ( rc != LDAP_SUCCESS ) {
+ ldap_perror( ld, "ldap_extended_operation" );
+ ldap_unbind( ld );
+ return EXIT_FAILURE;
+ }
+
+ ldap_memfree( retoid );
+ ber_bvfree( retdata );
+
/* disconnect from server */
ldap_unbind (ld);
ldappasswd \- change the password of an LDAP entry
.SH SYNOPSIS
.B ldappasswd
-[\c
-.BI \-a \ passwdattribute\fR]
-[\c
-.BI \-b \ searchbase\fR]
-[\c
-.BI \-D \ binddn\fR]
+.BI \-D \ binddn\fR
[\c
.BI \-d \ debuglevel\fR]
[\c
-.BR \-E ]
-[\c
-.BI \-e \ passwd\fR]
-[\c
-.BI \-g \ pwlen\fR]
-[\c
-.BI \-H \ none\fR\||\|\fIcrypt\fR\||\|\fImd5\fR\||\|\fIsmd5\fR\||\|\fIsha\fR\||\|\fIssha]
-[\c
.BI \-h \ ldaphost\fR]
[\c
-.BR \-K ]
-[\c
-.BR \-k ]
-[\c
-.BI \-l \ searchtime\fR]
-[\c
.BR \-n ]
[\c
-.BI \-P \ 2\fR\||\|\fI3\fR]
-[\c
.BI \-p \ ldapport\fR]
[\c
-.BI \-s \ base\fR\||\|\fIone\fR\||\|\fIsub\fR]
-[\c
-.BI \-t \ targetdn\fR]
+.BI \-s \ newPasswd\fR]
[\c
.BR \-v ]
[\c
.BR \-W ]
[\c
.BI \-w \ passwd\fR]
-[\c
-.BI \-z \ searchsize\fR]
-[\fIfilter\fR]
.SH DESCRIPTION
.B ldappasswd
-is a tool to modify the password of one or more LDAP entries.
-Multiple entries can be specified using a search filter.
+is a tool to set the password of an LDAP user.
It is neither designed nor intended to be a replacement for
.BR passwd (1)
and should not be installed as such.
.LP
.B ldappasswd
-works by specifying a single target dn or by using a search filter.
-Matching entries will be modified with the new password.
+sets the password of associated with the user associated with the
+bind DN.
If the new password is not specified on the command line, the user
will be prompted to enter it.
-The new password will be hashed using
-.I crypt
-or any other supported hashing algorithm.
-For hashing algorithms other than
-.I crypt
-or
-.IR none ,
-the stored password will be base64 encoded.
-Salts are only generated for crypt and are based on the least
-significant bits of the current time and other psuedo randomness.
.SH OPTIONS
.TP
-.BI \-a \ passwdattribute
-Specify the LDAP attribute to change. The default is "userPassword".
-.TP
-.BI \-b \ searchbase
-Use \fIsearchbase\fP as the starting point for the search instead of
-the default.
-.TP
.BI \-D \ binddn
-Use \fIbinddn\fP to bind to the X.500 directory. \fIbinddn\fP should be
-a string-represented DN as defined in RFC 1779.
+Use \fIbinddn\fP to bind to the LDAP directory. \fIbinddn\fP should
+be a string-represented DN as defined in RFC 2253.
+This flag is not optional.
.TP
.BI \-d \ debuglevel
Set the LDAP debugging level to \fIdebuglevel\fP.
.B ldappasswd
must be compiled with LDAP_DEBUG defined for this option to have any effect.
.TP
-.BI \-g \ pwlen
-Auto-generate passwords of length \fIpwlen\fR.
-Passwords will be displayed when using verbose,
-.BR -vvv .
-.TP
-.B \-H \fInone\fR\||\|\fIcrypt\fR\||\|\fImd5\fR\||\|\fIsmd5\fR\||\|\fIsha\fR\||\|\fIssha
-Specify the hashing algorithm used to store the password. The default is
-.IR crypt .
-.TP
.BI \-h \ ldaphost
Specify an alternate host on which the ldap server is running.
.TP
-.B \-K
-Same as -k, but only does step 1 of the kerberos bind.
-This is useful when connecting to a slapd and there is no x500dsa.hostname principal registered with your kerberos servers.
-.TP
-.B \-k
-Use Kerberos authentication instead of simple authentication.
-It is assumed that you already have a valid ticket granting ticket.
-.B ldappasswd
-must be compiled with KERBEROS defined for this option to have any effect.
-.TP
-.BI \-l \ searchtime
-Specify a maximum query time in seconds.
-.TP
.B \-n
-Make no modifications. (Can be useful when used in conjunction with
+Do not set password. (Can be useful when used in conjunction with
.BR \-v \ or
.BR \-d )
.TP
-.BI \-P \ 2\fR\||\|\fI3
-Specify the LDAP protocol version to use.
+.BI \-s \ newPasswd
+Set the user password to \fInewPasswd\fP.
.TP
.BI \-p \ ldapport
Specify an alternate port on which the ldap server is running.
.TP
-.BI \-s \ base\fR\||\|\fIone\fR\||\|\fIsub\fR
-Specify the scope of the search. The default is
-.IR base .
-.TP
-.B \-t \fR[\fItargetdn\fR]
-Specify the target dn to modify.
-If an argument is not given, the target dn will be the binddn.
-.TP
.B \-v
-The more v's the more verbose.
+Increase the verbosity of output. Can be specified multiple times.
.TP
.BI \-W
-Prompt for simple authentication.
+Prompt for bind password.
This is used instead of specifying the password on the command line.
.TP
.BI \-w \ passwd
-Use \fIpasswd\fP as the password for simple authentication.
-.TP
-.BI \-z \ searchsize
-Specify a maximum query size.
-.SH AUTHOR
-David E. Storey <dave@tamos.net>
-.SH "SEE ALSO"
-.BR ldapadd (1),
-.BR ldapdelete (1),
-.BR ldapmodrdn (1),
-.BR ldapsearch (1)
+Use \fIpasswd\fP as the password to bind with.
+.SH SEE ALSO
+.BR ldap_bind (3)
+.SH BUGS
+No transport security layer is provided.
+.SH ACKNOWLEDGEMENTS
+.B OpenLDAP
+is developed and maintained by The OpenLDAP Project (http://www.openldap.org/).
+.B OpenLDAP
+is derived from University of Michigan LDAP 3.3 Release.
where:
\fIhostport\fP is a host name with an optional ":portnumber"
- \fIdn\f is the base DN to be used for an LDAP search operation
+ \fIdn\fP is the base DN to be used for an LDAP search operation
\fIattributes\fP is a comma separated list of attributes to be retrieved
\fIscope\fP is one of these three strings: base one sub (default=base)
- \fIfilter\f is LDAP search filter as used in a call to ldap_search(3)
+ \fIfilter\fP is LDAP search filter as used in a call to ldap_search(3)
e.g., ldap://ldap.itd.umich.edu/c=US?o,description?one?o=umich
.fi
/* 0x34 - 0x0fff not defined by current draft */
-/* extended options - none */
-
/* private and experimental options */
#define LDAP_OPT_DNS 0x4001 /* use DN & DNS */
#define LDAP_CONTROL_MANAGEDSAIT "2.16.840.1.113730.3.4.2"
/* Experimental Controls */
-#define LDAP_CONTROL_X_CHANGE_PASSWD "1.3.6.1.4.1.4203.666.5.1"
+#define LDAP_CONTROL_X_MODIFY_PASSWD "1.3.6.1.4.1.4203.666.5.1"
/* LDAP Unsolicited Notifications */
/* LDAP Extended Operations */
+#define LDAP_EXOP_X_MODIFY_PASSWD "1.3.6.1.4.1.4203.666.6.1"
/*
/* passwd.c */
LIBLUTIL_F( int )
lutil_passwd LDAP_P((
- const char *cred,
- const char *passwd,
+ const char *passwd, /* stored password */
+ const char *cred, /* user supplied value */
const char **methods ));
+LIBLUTIL_F( char * )
+lutil_passwd_generate LDAP_P((
+ const char *passwd,
+ const char *method ));
+
LIBLUTIL_F (const char *) lutil_passwd_schemes[];
LIBLUTIL_F( int )
if ( type == LDIF_PUT_VALUE
&& isgraph( val[0] ) && val[0] != ':' && val[0] != '<'
&& isgraph( val[vlen-1] )
+#ifndef LDAP_PASSWD_DEBUG
&& strcasecmp( name, "userPassword" ) != 0 /* encode userPassword */
&& strcasecmp( name, "2.5.4.35" ) != 0 /* encode userPassword */
+#endif
) {
int b64 = 0;
#include <ac/unistd.h>
#include <ac/crypt.h>
+#include <lber.h>
+
#include "lutil_md5.h"
#include "lutil_sha1.h"
#include "lutil.h"
# include <pwd.h>
#endif
-static int is_allowed_scheme(
- const char* scheme,
- const char** schemes )
-{
- int i;
+struct pw_scheme;
- if(schemes == NULL) {
- return 1;
- }
+typedef int (*PASSWD_CHK_FUNC)(
+ const struct pw_scheme *scheme,
+ const char *passwd,
+ const char *cred );
- for(i=0; schemes[i] != NULL; i++) {
- if(strcasecmp(scheme, schemes[i]) == 0) {
- return 1;
- }
- }
+typedef char * (*PASSWD_GEN_FUNC) (
+ const struct pw_scheme *scheme,
+ const char *passwd );
- return 0;
-}
+struct pw_scheme {
+ char *name;
+ size_t namelen;
+ PASSWD_CHK_FUNC chk_fn;
+ PASSWD_GEN_FUNC gen_fn;
+};
+
+/* password check routines */
+static int chk_md5(
+ const struct pw_scheme *scheme,
+ const char *passwd,
+ const char *cred );
+
+static int chk_smd5(
+ const struct pw_scheme *scheme,
+ const char *passwd,
+ const char *cred );
+
+static int chk_ssha1(
+ const struct pw_scheme *scheme,
+ const char *passwd,
+ const char *cred );
+
+static int chk_sha1(
+ const struct pw_scheme *scheme,
+ const char *passwd,
+ const char *cred );
+
+static int chk_crypt(
+ const struct pw_scheme *scheme,
+ const char *passwd,
+ const char *cred );
+
+static int chk_unix(
+ const struct pw_scheme *scheme,
+ const char *passwd,
+ const char *cred );
+
+
+/* password generation routines */
+static char *gen_sha1(
+ const struct pw_scheme *scheme,
+ const char *passwd );
+
+static char *gen_ssha1(
+ const struct pw_scheme *scheme,
+ const char *passwd );
+
+static char *gen_smd5(
+ const struct pw_scheme *scheme,
+ const char *passwd );
+
+static char *gen_md5(
+ const struct pw_scheme *scheme,
+ const char *passwd );
+
+static char *gen_crypt(
+ const struct pw_scheme *scheme,
+ const char *passwd );
+
+
+static const struct pw_scheme pw_schemes[] =
+{
+ { "{SSHA}", sizeof("{SSHA}")-1, chk_ssha1, gen_ssha1 },
+ { "{SHA}", sizeof("{SHA}")-1, chk_sha1, gen_sha1 },
+
+ { "{SMD5}", sizeof("{SMD5}")-1, chk_smd5, gen_smd5 },
+ { "{MD5}", sizeof("{MD5}")-1, chk_md5, gen_md5 },
-const char *lutil_passwd_schemes[] = {
#ifdef SLAPD_CRYPT
- "{CRYPT}",
+ { "{CRYPT}", sizeof("{CRYPT}")-1, chk_crypt, gen_crypt },
#endif
- "{MD5}", "{SMD5}",
- "{SHA}", "{SSHA}",
# if defined( HAVE_GETSPNAM ) \
|| ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
- "{UNIX}",
+ { "{UNIX}", sizeof("{UNIX}")-1, chk_unix, NULL },
#endif
+
#ifdef SLAPD_CLEARTEXT
- "{CLEARTEXT}", /* psuedo scheme */
+ /* psuedo scheme */
+ { "{CLEARTEXT}", 0, NULL, NULL },
#endif
+
NULL,
};
-int lutil_passwd_scheme( char *scheme ) {
- return is_allowed_scheme( scheme, lutil_passwd_schemes );
+static const struct pw_scheme *get_scheme(
+ const char* scheme )
+{
+ int i;
+
+ for( i=0; pw_schemes[i].name != NULL; i++) {
+ if( pw_schemes[i].namelen == 0 ) continue;
+
+ if( strncasecmp(scheme, pw_schemes[i].name,
+ pw_schemes[i].namelen) == 0 )
+ {
+ return &pw_schemes[i];
+ }
+ }
+
+ return NULL;
}
-static const char *passwd_scheme(
- const char* passwd,
+
+static int is_allowed_scheme(
const char* scheme,
const char** schemes )
{
- int len;
+ int i;
- if( !is_allowed_scheme( scheme, schemes ) ) {
- return NULL;
+ if( schemes == NULL ) return 1;
+
+ for( i=0; schemes[i] != NULL; i++ ) {
+ if( strcasecmp( scheme, schemes[i] ) == 0 ) {
+ return 1;
+ }
}
+ return 0;
+}
- len = strlen(scheme);
+static const char *passwd_scheme(
+ const struct pw_scheme *scheme,
+ const char* passwd,
+ const char** allowed )
+{
+ if( !is_allowed_scheme( scheme->name, allowed ) ) {
+ return NULL;
+ }
- if( strncasecmp( passwd, scheme, len ) == 0 ) {
- return &passwd[len];
+ if( strncasecmp( passwd, scheme->name, scheme->namelen ) == 0 ) {
+ return &passwd[scheme->namelen];
}
return NULL;
*/
int
lutil_passwd(
- const char *cred,
- const char *passwd,
- const char **schemes)
+ const char *passwd, /* stored passwd */
+ const char *cred, /* user cred */
+ const char **schemes )
{
- const char *p;
+ int i;
if (cred == NULL || passwd == NULL) {
return -1;
}
- if ((p = passwd_scheme( passwd, "{MD5}", schemes )) != NULL ) {
- lutil_MD5_CTX MD5context;
- unsigned char MD5digest[16];
- char base64digest[LUTIL_BASE64_ENCODE_LEN(16)];
-
- lutil_MD5Init(&MD5context);
- lutil_MD5Update(&MD5context,
- (const unsigned char *)cred, strlen(cred));
- lutil_MD5Final(MD5digest, &MD5context);
+ for( i=0; pw_schemes[i].name != NULL; i++ ) {
+ if( pw_schemes[i].chk_fn ) {
+ const char *p = passwd_scheme( &pw_schemes[i],
+ passwd, schemes );
- if ( lutil_b64_ntop(MD5digest, sizeof(MD5digest),
- base64digest, sizeof(base64digest)) < 0)
- {
- return ( 1 );
+ if( p != NULL ) {
+ return (pw_schemes[i].chk_fn)( &pw_schemes[i], p, cred );
+ }
}
+ }
- return( strcmp(p, base64digest) );
+#ifdef SLAPD_CLEARTEXT
+ if( is_allowed_scheme("{CLEARTEXT}", schemes ) ) {
+ return strcmp( cred, passwd );
+ }
+#else
+ return 1;
+#endif
- } else if ((p = passwd_scheme( passwd, "{SHA}", schemes )) != NULL ) {
- lutil_SHA1_CTX SHA1context;
- unsigned char SHA1digest[20];
- char base64digest[LUTIL_BASE64_ENCODE_LEN(20)];
+}
- lutil_SHA1Init(&SHA1context);
- lutil_SHA1Update(&SHA1context,
- (const unsigned char *) cred, strlen(cred));
- lutil_SHA1Final(SHA1digest, &SHA1context);
+char * lutil_passwd_generate(
+ const char * passwd,
+ const char * method )
+{
+ const struct pw_scheme *sc = get_scheme( method );
- if (lutil_b64_ntop(SHA1digest, sizeof(SHA1digest),
- base64digest, sizeof(base64digest)) < 0)
- {
- return ( 1 );
+ if( sc == NULL ) return NULL;
+ if( ! sc->gen_fn ) return NULL;
+
+ return (sc->gen_fn)( sc, passwd );
+}
+
+static char * pw_string(
+ const struct pw_scheme *sc,
+ const char *passwd)
+{
+ size_t pwlen = strlen( passwd );
+ char *pw = ber_memalloc( sc->namelen + pwlen + 1 );
+
+ if( pw == NULL ) return NULL;
+
+ memcpy( pw, sc->name, sc->namelen );
+ memcpy( &pw[sc->namelen], passwd, pwlen );
+ pw[sc->namelen + pwlen] = '\0';
+
+ return pw;
+}
+
+static char * pw_string64(
+ const struct pw_scheme *sc,
+ const unsigned char *hash, size_t hashlen,
+ const unsigned char *salt, size_t saltlen )
+{
+ int rc;
+ char *string = NULL;
+ size_t b64len;
+ size_t len = hashlen + saltlen;
+ char *b64;
+
+ if( saltlen ) {
+ /* need to base64 combined string */
+ string = ber_memalloc( hashlen + saltlen );
+
+ if( string == NULL ) {
+ return NULL;
}
- return( strcmp(p, base64digest) );
+ memcpy( string, hash, len );
+ memcpy( &string[len], salt, saltlen );
+
+ } else {
+ string = (char *) hash;
+ }
+
+ b64len = LUTIL_BASE64_ENCODE_LEN( len ) + 1;
+ b64 = ber_memalloc( b64len + sc->namelen );
+
+ if( b64 == NULL ) {
+ if( saltlen ) ber_memfree( string );
+ return NULL;
+ }
- } else if ((p = passwd_scheme( passwd, "{SSHA}", schemes )) != NULL ) {
- lutil_SHA1_CTX SHA1context;
- unsigned char SHA1digest[20];
- int pw_len = strlen(p);
- int rc;
- unsigned char *orig_pass = NULL;
+ memcpy(b64, sc->name, sc->namelen);
+
+ rc = lutil_b64_ntop( string, len, &b64[sc->namelen], b64len );
+
+ if( saltlen ) ber_memfree( string );
+
+ if( rc < 0 ) {
+ free( b64 );
+ return NULL;
+ }
+
+ return b64;
+}
+
+/* PASSWORD CHECK ROUTINES */
+
+static int chk_ssha1(
+ const struct pw_scheme *sc,
+ const char* passwd,
+ const char* cred )
+{
+ lutil_SHA1_CTX SHA1context;
+ unsigned char SHA1digest[20];
+ int pw_len = strlen(passwd);
+ int rc;
+ unsigned char *orig_pass = NULL;
- /* base64 un-encode password */
- orig_pass = (unsigned char *) malloc( (size_t) (
- LUTIL_BASE64_DECODE_LEN(pw_len) + 1) );
- if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0)
- {
- free(orig_pass);
- return ( 1 );
- }
+ /* base64 un-encode password */
+ orig_pass = (unsigned char *) malloc( (size_t) (
+ LUTIL_BASE64_DECODE_LEN(pw_len) + 1) );
+
+ if ((rc = lutil_b64_pton(passwd, orig_pass, pw_len)) < 0) {
+ free(orig_pass);
+ return 1;
+ }
- /* hash credentials with salt */
- lutil_SHA1Init(&SHA1context);
- lutil_SHA1Update(&SHA1context,
- (const unsigned char *) cred, strlen(cred));
- lutil_SHA1Update(&SHA1context,
- (const unsigned char *) orig_pass + sizeof(SHA1digest),
- rc - sizeof(SHA1digest));
- lutil_SHA1Final(SHA1digest, &SHA1context);
+ /* hash credentials with salt */
+ lutil_SHA1Init(&SHA1context);
+ lutil_SHA1Update(&SHA1context,
+ (const unsigned char *) cred, strlen(cred));
+ lutil_SHA1Update(&SHA1context,
+ (const unsigned char *) &orig_pass[sizeof(SHA1digest)],
+ rc - sizeof(SHA1digest));
+ lutil_SHA1Final(SHA1digest, &SHA1context);
- /* compare */
- rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
- free(orig_pass);
- return(rc);
-
- } else if ((p = passwd_scheme( passwd, "{SMD5}", schemes )) != NULL ) {
- lutil_MD5_CTX MD5context;
- unsigned char MD5digest[16];
- int pw_len = strlen(p);
- int rc;
- unsigned char *orig_pass = NULL;
-
- /* base64 un-encode password */
- orig_pass = (unsigned char *) malloc( (size_t) (
- LUTIL_BASE64_DECODE_LEN(pw_len) + 1) );
- if ((rc = lutil_b64_pton(p, orig_pass, pw_len)) < 0)
- {
- free(orig_pass);
- return ( 1 );
- }
+ /* compare */
+ rc = memcmp((char *)orig_pass, (char *)SHA1digest, sizeof(SHA1digest));
+ free(orig_pass);
+ return rc;
+}
- /* hash credentials with salt */
- lutil_MD5Init(&MD5context);
- lutil_MD5Update(&MD5context,
- (const unsigned char *) cred, strlen(cred));
- lutil_MD5Update(&MD5context,
- (const unsigned char *) orig_pass + sizeof(MD5digest),
- rc - sizeof(MD5digest));
- lutil_MD5Final(MD5digest, &MD5context);
-
- /* compare */
- rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
+static int chk_sha1(
+ const struct pw_scheme *sc,
+ const char* passwd,
+ const char* cred )
+{
+ lutil_SHA1_CTX SHA1context;
+ unsigned char SHA1digest[20];
+ char base64digest[LUTIL_BASE64_ENCODE_LEN(sizeof(SHA1digest))+1];
+
+ lutil_SHA1Init(&SHA1context);
+ lutil_SHA1Update(&SHA1context,
+ (const unsigned char *) cred, strlen(cred));
+ lutil_SHA1Final(SHA1digest, &SHA1context);
+
+ if (lutil_b64_ntop(SHA1digest, sizeof(SHA1digest),
+ base64digest, sizeof(base64digest)) < 0)
+ {
+ return 1;
+ }
+
+ return strcmp(passwd, base64digest);
+}
+
+static int chk_smd5(
+ const struct pw_scheme *sc,
+ const char* passwd,
+ const char* cred )
+{
+ lutil_MD5_CTX MD5context;
+ unsigned char MD5digest[16];
+ int pw_len = strlen(passwd);
+ int rc;
+ unsigned char *orig_pass = NULL;
+
+ /* base64 un-encode password */
+ orig_pass = (unsigned char *) malloc( (size_t) (
+ LUTIL_BASE64_DECODE_LEN(pw_len) + 1) );
+
+ if ((rc = lutil_b64_pton(passwd, orig_pass, pw_len)) < 0) {
free(orig_pass);
- return ( rc );
+ return 1;
+ }
+
+ /* hash credentials with salt */
+ lutil_MD5Init(&MD5context);
+ lutil_MD5Update(&MD5context,
+ (const unsigned char *) cred, strlen(cred));
+ lutil_MD5Update(&MD5context,
+ (const unsigned char *) &orig_pass[sizeof(MD5digest)],
+ rc - sizeof(MD5digest));
+ lutil_MD5Final(MD5digest, &MD5context);
+
+ /* compare */
+ rc = memcmp((char *)orig_pass, (char *)MD5digest, sizeof(MD5digest));
+ free(orig_pass);
+ return rc;
+}
+
+static int chk_md5(
+ const struct pw_scheme *sc,
+ const char* passwd,
+ const char* cred )
+{
+ lutil_MD5_CTX MD5context;
+ unsigned char MD5digest[16];
+ char base64digest[LUTIL_BASE64_ENCODE_LEN(sizeof(MD5digest))+1];
+
+ lutil_MD5Init(&MD5context);
+ lutil_MD5Update(&MD5context,
+ (const unsigned char *)cred, strlen(cred));
+ lutil_MD5Final(MD5digest, &MD5context);
+
+ if ( lutil_b64_ntop(MD5digest, sizeof(MD5digest),
+ base64digest, sizeof(base64digest)) < 0 )
+ {
+ return 1;
+ }
+
+ return strcmp(passwd, base64digest);
+}
#ifdef SLAPD_CRYPT
- } else if ((p = passwd_scheme( passwd, "{CRYPT}", schemes )) != NULL ) {
- return( strcmp(p, crypt(cred, p)) );
+static int chk_crypt(
+ const struct pw_scheme *sc,
+ const char* passwd,
+ const char* cred )
+{
+ return strcmp(passwd, crypt(cred, passwd));
+}
# if defined( HAVE_GETSPNAM ) \
|| ( defined( HAVE_GETPWNAM ) && defined( HAVE_PW_PASSWD ) )
- } else if ((p = passwd_scheme( passwd, "{UNIX}", schemes )) != NULL ) {
-
+static int chk_unix(
+ const struct pw_scheme *sc,
+ const char* cred,
+ const char* p )
+{
# ifdef HAVE_GETSPNAM
- struct spwd *spwd = getspnam(p);
+ struct spwd *spwd = getspnam(p);
- if(spwd == NULL) {
- return 1; /* not found */
- }
+ if(spwd == NULL) {
+ return 1; /* not found */
+ }
- return strcmp(spwd->sp_pwdp, crypt(cred, spwd->sp_pwdp));
+ return strcmp(spwd->sp_pwdp, crypt(cred, spwd->sp_pwdp));
# else
- struct passwd *pwd = getpwnam(p);
+ struct passwd *pwd = getpwnam(p);
- if(pwd == NULL) {
- return 1; /* not found */
- }
+ if(pwd == NULL) {
+ return 1; /* not found */
+ }
- return strcmp(pwd->pw_passwd, crypt(cred, pwd->pw_passwd));
+ return strcmp(pwd->pw_passwd, crypt(cred, pwd->pw_passwd));
# endif
# endif
+}
#endif
+
+/* PASSWORD CHECK ROUTINES */
+static char *gen_ssha1(
+ const struct pw_scheme *scheme,
+ const char *passwd )
+{
+ lutil_SHA1_CTX SHA1context;
+ unsigned char SHA1digest[20];
+ unsigned char salt[4];
+
+ if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
+ return NULL;
}
-#ifdef SLAPD_CLEARTEXT
- return is_allowed_scheme("{CLEARTEXT}", schemes ) &&
- strcmp(passwd, cred) != 0;
-#else
- return( 1 );
-#endif
+ lutil_SHA1Init( &SHA1context );
+ lutil_SHA1Update( &SHA1context,
+ (const unsigned char *)passwd, strlen(passwd) );
+ lutil_SHA1Update( &SHA1context,
+ (const unsigned char *)salt, sizeof(salt) );
+ lutil_SHA1Final( SHA1digest, &SHA1context );
+
+ return pw_string64( scheme,
+ SHA1digest, sizeof(SHA1digest),
+ salt, sizeof(salt));
+}
+
+static char *gen_sha1(
+ const struct pw_scheme *scheme,
+ const char *passwd )
+{
+ lutil_SHA1_CTX SHA1context;
+ unsigned char SHA1digest[20];
+
+ lutil_SHA1Init( &SHA1context );
+ lutil_SHA1Update( &SHA1context,
+ (const unsigned char *)passwd, strlen(passwd) );
+ lutil_SHA1Final( SHA1digest, &SHA1context );
+
+ return pw_string64( scheme,
+ SHA1digest, sizeof(SHA1digest),
+ NULL, 0);
+}
+
+static char *gen_smd5(
+ const struct pw_scheme *scheme,
+ const char *passwd )
+{
+ lutil_MD5_CTX MD5context;
+ unsigned char MD5digest[16];
+ unsigned char salt[4];
+
+ if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
+ return NULL;
+ }
+
+ lutil_MD5Init( &MD5context );
+ lutil_MD5Update( &MD5context,
+ (const unsigned char *) passwd, strlen(passwd) );
+
+ lutil_MD5Update( &MD5context,
+ (const unsigned char *) salt, sizeof(salt) );
+
+ lutil_MD5Final( MD5digest, &MD5context );
+
+ return pw_string64( scheme,
+ MD5digest, sizeof(MD5digest),
+ salt, sizeof(salt) );
+}
+
+static char *gen_md5(
+ const struct pw_scheme *scheme,
+ const char *passwd )
+{
+ lutil_MD5_CTX MD5context;
+ unsigned char MD5digest[16];
+
+ lutil_MD5Init( &MD5context );
+ lutil_MD5Update( &MD5context,
+ (const unsigned char *) passwd, strlen(passwd) );
+
+ lutil_MD5Final( MD5digest, &MD5context );
+
+ return pw_string64( scheme,
+ MD5digest, sizeof(MD5digest),
+ NULL, 0 );
+}
+
+#ifdef SLAPD_CRYPT
+static char *gen_crypt(
+ const struct pw_scheme *scheme,
+ const char *passwd )
+{
+ static const unsigned char crypt64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./";
+
+ char *hash = NULL;
+ unsigned char salt[2];
+ if( lutil_entropy( salt, sizeof(salt)) < 0 ) {
+ return NULL;
+ }
+
+ salt[0] = crypt64[ salt[0] % (sizeof(crypt64)-1) ];
+ salt[1] = crypt64[ salt[1] % (sizeof(crypt64)-1) ];
+
+ hash = crypt( passwd, salt );
+
+ if( hash = NULL ) return NULL;
+
+ return pw_string( scheme, hash );
}
+#endif
return rc;
}
+ /* make sure this backend recongizes critical controls */
+ rc = backend_check_controls( be, conn, op ) ;
+
+ if( rc != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, rc,
+ NULL, NULL, NULL, NULL );
+ }
+
if ( global_readonly || be->be_readonly ) {
Debug( LDAP_DEBUG_ANY, "do_add: database is read-only\n",
0, 0, 0 );
{
int ret;
+ static char *controls[] = {
+ LDAP_CONTROL_MANAGEDSAIT,
+ /* LDAP_CONTROL_X_CHANGE_PASSWD, */
+ NULL
+ };
+
+ bi->bi_controls = controls;
+
bi->bi_open = bdb2_back_open;
bi->bi_config = bdb2_back_config;
bi->bi_close = bdb2_back_close;
bi->bi_op_delete = bdb2_back_delete;
bi->bi_op_abandon = bdb2_back_abandon;
+ bi->bi_extended = 0;
+
bi->bi_entry_release_rw = bdb2_back_entry_release_rw;
bi->bi_acl_group = bdb2_back_group;
bi->bi_op_delete = ldap_back_delete;
bi->bi_op_abandon = 0;
+ bi->bi_extended = 0;
+
bi->bi_acl_group = 0;
bi->bi_connection_init = 0;
SRCS = idl.c add.c search.c cache.c dbcache.c dn2id.c entry.c id2entry.c \
index.c id2children.c nextid.c abandon.c compare.c group.c \
modify.c modrdn.c delete.c init.c config.c bind.c attr.c \
- filterindex.c unbind.c close.c alias.c tools.c
+ filterindex.c unbind.c close.c alias.c tools.c \
+ extended.c passwd.c
OBJS = idl.lo add.lo search.lo cache.lo dbcache.lo dn2id.lo entry.lo id2entry.lo \
index.lo id2children.lo nextid.lo abandon.lo compare.lo group.lo \
modify.lo modrdn.lo delete.lo init.lo config.lo bind.lo attr.lo \
- filterindex.lo unbind.lo close.lo alias.lo tools.lo
+ filterindex.lo unbind.lo close.lo alias.lo tools.lo \
+ extended.lo passwd.lo
LDAP_INCDIR= ../../../include
LDAP_LIBDIR= ../../../libraries
--- /dev/null
+/* extended.c - ldbm backend extended routines */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-ldbm.h"
+#include "proto-back-ldbm.h"
+
+struct exop {
+ char *oid;
+ SLAP_EXTENDED_FN extended;
+} exop_table[] = {
+ { LDAP_EXOP_X_MODIFY_PASSWD, ldbm_back_exop_passwd },
+ { NULL, NULL }
+};
+
+int
+ldbm_back_extended(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *oid,
+ struct berval *reqdata,
+ struct berval **rspdata,
+ char** text
+)
+{
+ int i;
+
+ 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 );
+ }
+ }
+
+ *text = ch_strdup("not supported within naming context");
+ return LDAP_OPERATIONS_ERROR;
+}
+
extern int ldbm_back_db_config LDAP_P(( BackendDB *bd,
const char *fname, int lineno, int argc, char **argv ));
+extern int ldbm_back_extended LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *reqoid,
+ struct berval *reqdata,
+ struct berval **rspdata,
+ char **text ));
+
extern int ldbm_back_bind LDAP_P(( BackendDB *bd,
Connection *conn, Operation *op,
char *dn, char *ndn, int method, char* mech,
BackendInfo *bi
)
{
+ static char *controls[] = {
+ LDAP_CONTROL_MANAGEDSAIT,
+ /* LDAP_CONTROL_X_CHANGE_PASSWD, */
+ NULL
+ };
+
+ bi->bi_controls = controls;
+
bi->bi_open = ldbm_back_open;
bi->bi_config = 0;
bi->bi_close = ldbm_back_close;
bi->bi_op_delete = ldbm_back_delete;
bi->bi_op_abandon = ldbm_back_abandon;
+ bi->bi_extended = ldbm_back_extended;
+
bi->bi_entry_release_rw = ldbm_back_entry_release_rw;
bi->bi_acl_group = ldbm_back_group;
Attribute *save_attrs;
if ( !acl_check_modlist( be, conn, op, e, modlist )) {
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- NULL, NULL, NULL, NULL );
- return -1;
+ return LDAP_INSUFFICIENT_ACCESS;
}
save_attrs = e->e_attrs;
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
/* unlock entry, delete from cache */
- send_ldap_result( conn, op, err,
- NULL, NULL, NULL, NULL );
- return -1;
+ return err;
}
}
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
- return -1;
+ return SLAPD_ABANDON;
}
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
- NULL, NULL, NULL, NULL );
- return -1;
+ return LDAP_OBJECT_CLASS_VIOLATION;
}
/* check for abandon */
attrs_free( e->e_attrs );
e->e_attrs = save_attrs;
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
- return -1;
+ return SLAPD_ABANDON;
}
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* modify indexes */
if ( index_add_mods( be, modlist, e->e_id ) != 0 ) {
/* our indices are likely hosed */
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, NULL, NULL, NULL );
- return -1;
+ return LDAP_OPERATIONS_ERROR;
}
- /* check for abandon */
- ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
- if ( op->o_abandon ) {
- ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
- return -1;
- }
- ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
-
- return 0;
+ return LDAP_SUCCESS;
}
LDAPModList *modlist
)
{
+ int rc;
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
Entry *matched;
Entry *e;
}
/* Modify the entry */
- if ( ldbm_modify_internal( be, conn, op, ndn, modlist, e ) != 0 ) {
+ rc = ldbm_modify_internal( be, conn, op, ndn, modlist, e );
+
+ if( rc != LDAP_SUCCESS ) {
+ if( rc != SLAPD_ABANDON ) {
+ send_ldap_result( conn, op, rc,
+ NULL, NULL, NULL, NULL );
+ }
+
goto error_return;
}
send_ldap_result( conn, op, LDAP_SUCCESS,
NULL, NULL, NULL, NULL );
+
cache_return_entry_w( &li->li_cache, e );
return( 0 );
}
/* modify memory copy of entry */
- if ( ldbm_modify_internal( be, conn, op, dn, &mod[0], e )
- != 0 ) {
+ rc = ldbm_modify_internal( be, conn, op, dn, &mod[0], e );
+
+ if( rc != LDAP_SUCCESS ) {
+ if( rc != SLAPD_ABANDON ) {
+ send_ldap_result( conn, op, rc,
+ NULL, NULL, NULL, NULL );
+ }
goto return_results;
}
--- /dev/null
+/* extended.c - ldbm backend extended routines */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-ldbm.h"
+#include "proto-back-ldbm.h"
+
+int
+ldbm_back_exop_passwd(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ char *oid,
+ struct berval *reqdata,
+ struct berval **rspdata,
+ char** text
+)
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ int rc = LDAP_OPERATIONS_ERROR;
+ Entry *e;
+ struct berval *cred = NULL;
+
+ assert( oid != NULL );
+ assert( strcmp( LDAP_EXOP_X_MODIFY_PASSWD, oid ) == 0 );
+
+ Debug( LDAP_DEBUG_ARGS, "==> ldbm_back_exop_passwd: dn: %s\n",
+ op->o_dn, 0, 0 );
+
+
+ cred = slap_passwd_generate( reqdata );
+ if( cred == NULL || cred->bv_len == 0 ) {
+ *text = ch_strdup("password generation failed");
+ return LDAP_OPERATIONS_ERROR;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "passwd: %s\n", cred->bv_val, 0, 0 );
+
+ e = dn2entry_w( be, op->o_ndn, NULL );
+
+ if( e == NULL ) {
+ *text = ch_strdup("could not locate authorization entry");
+ return LDAP_OPERATIONS_ERROR;
+ }
+
+ if( ! access_allowed( be, conn, op, e, "entry", NULL, ACL_WRITE ) ) {
+ *text = ch_strdup("access to authorization entry denied");
+ rc = LDAP_INSUFFICIENT_ACCESS;
+ goto done;
+ }
+
+ if( is_entry_alias( e ) ) {
+ /* entry is an alias, don't allow operation */
+ *text = ch_strdup("authorization entry is alias");
+ rc = LDAP_ALIAS_PROBLEM;
+ goto done;
+ }
+
+ if( is_entry_referral( e ) ) {
+ /* entry is an referral, don't allow operation */
+ *text = ch_strdup("authorization entry is referral");
+ goto done;
+ }
+
+ {
+ LDAPModList ml;
+ struct berval *vals[2];
+
+ vals[0] = cred;
+ vals[1] = NULL;
+
+ ml.ml_type = ch_strdup("userPassword");
+ ml.ml_bvalues = vals;
+ ml.ml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
+ ml.ml_next = NULL;
+
+ rc = ldbm_modify_internal( be,
+ conn, op, op->o_ndn, &ml, e );
+
+ ch_free(ml.ml_type);
+ }
+
+ if( rc == LDAP_SUCCESS ) {
+ /* change the entry itself */
+ if( id2entry_add( be, e ) != 0 ) {
+ rc = LDAP_OPERATIONS_ERROR;
+ }
+ }
+
+done:
+ cache_return_entry_w( &li->li_cache, e );
+
+ if( cred != NULL ) {
+ ber_bvfree( cred );
+ }
+
+ return rc;
+}
unsigned int op ));
/*
- * kerberos.c
+ * passwd.c
*/
-
-#ifdef HAVE_KERBEROS
-/* krbv4_ldap_auth LDAP_P(( Backend *be, struct berval *cred, AUTH_DAT *ad )); */
-#endif
+extern int ldbm_back_exop_passwd LDAP_P(( BackendDB *bd,
+ Connection *conn, Operation *op,
+ char *oid,
+ struct berval *reqdata,
+ struct berval **rspdata,
+ char **text ));
+
/*
* modify.c
* These prototypes are placed here because they are used by modify and
int add_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
int delete_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
int replace_values LDAP_P(( Entry *e, LDAPMod *mod, char *dn ));
+
+/* returns LDAP error code indicating error OR SLAPD_ABANDON */
int ldbm_modify_internal LDAP_P((Backend *be,
Connection *conn, Operation *op,
- char *dn, LDAPModList *mods, Entry *e));
+ char *dn, LDAPModList *mods, Entry *e ));
/*
* nextid.c
bi->bi_op_delete = 0;
bi->bi_op_abandon = 0;
+ bi->bi_extended = 0;
+
bi->bi_acl_group = 0;
bi->bi_connection_init = 0;
bi->bi_op_delete = perl_back_delete;
bi->bi_op_abandon = 0;
+ bi->bi_extended = 0;
+
bi->bi_acl_group = 0;
bi->bi_connection_init = 0;
bi->bi_op_delete = shell_back_delete;
bi->bi_op_abandon = shell_back_abandon;
+ bi->bi_extended = 0;
+
bi->bi_acl_group = 0;
bi->bi_connection_init = 0;
int result;
if ( ! be_isroot( be, ndn ) ) {
- return( 0 );
+ return 0;
}
#ifdef SLAPD_CRYPT
ldap_pvt_thread_mutex_lock( &crypt_mutex );
#endif
- result = lutil_passwd( cred->bv_val, be->be_root_pw, NULL );
+ result = lutil_passwd( be->be_root_pw, cred->bv_val, NULL );
#ifdef SLAPD_CRYPT
ldap_pvt_thread_mutex_unlock( &crypt_mutex );
return 0;
}
+int
+backend_check_controls(
+ Backend *be,
+ Connection *conn,
+ Operation *op )
+{
+ LDAPControl **ctrls;
+ ctrls = op->o_ctrls;
+ if( ctrls == NULL ) {
+ return LDAP_SUCCESS;
+ }
+
+ for( ; *ctrls != NULL ; ctrls++ ) {
+ if( (*ctrls)->ldctl_iscritical &&
+ !charray_inlist( be->be_controls, (*ctrls)->ldctl_oid ) )
+ {
+ return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
int
backend_group(
Backend *be,
conn->c_dn = NULL;
}
+ conn->c_authz_backend = NULL;
+
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
if ( op->o_dn != NULL ) {
goto cleanup;
}
+ conn->c_authz_backend = be;
+
+ /* make sure this backend recongizes critical controls */
+ rc = backend_check_controls( be, conn, op ) ;
+
+ if( rc != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, rc,
+ NULL, NULL, NULL, NULL );
+ }
+
if ( be->be_bind ) {
+ int ret;
/* alias suffix */
char *edn = NULL;
/* deref suffix alias if appropriate */
ndn = suffix_alias( be, ndn );
- if ( (*be->be_bind)( be, conn, op, dn, ndn, method, mech, &cred, &edn ) == 0 ) {
+ ret = (*be->be_bind)( be, conn, op, dn, ndn,
+ method, mech, &cred, &edn );
+
+ if ( ret == 0 ) {
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
conn->c_cdn = dn;
goto cleanup;
}
+ /* make sure this backend recongizes critical controls */
+ rc = backend_check_controls( be, conn, op ) ;
+
+ if( rc != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, rc,
+ NULL, NULL, NULL, NULL );
+ }
+
/* deref suffix alias if appropriate */
ndn = suffix_alias( be, ndn );
int global_idletimeout = 0;
char *global_realm = NULL;
char *ldap_srvtab = "";
+char *default_passwd_hash;
char *slapd_pid_file = NULL;
char *slapd_args_file = NULL;
slapd_args_file = ch_strdup( cargv[1] );
+ /* default password hash */
+ } else if ( strcasecmp( cargv[0], "password-hash" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing realm in \"password-hash <hash>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+ if ( default_passwd_hash != NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: already set default password_hash!\n",
+ fname, lineno, 0 );
+ return 1;
+
+ } else {
+ default_passwd_hash = ch_strdup( cargv[1] );
+ }
+
/* set DIGEST realm */
} else if ( strcasecmp( cargv[0], "digest-realm" ) == 0 ) {
if ( cargc < 2 ) {
char *supportedControls[] = {
LDAP_CONTROL_MANAGEDSAIT,
- LDAP_CONTROL_X_CHANGE_PASSWD,
+/* LDAP_CONTROL_X_CHANGE_PASSWD, */
NULL
};
goto cleanup;
}
+ /* make sure this backend recongizes critical controls */
+ rc = backend_check_controls( be, conn, op ) ;
+
+ if( rc != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, rc,
+ NULL, NULL, NULL, NULL );
+ }
+
if ( global_readonly || be->be_readonly ) {
Debug( LDAP_DEBUG_ANY, "do_delete: database is read-only\n",
0, 0, 0 );
#include "slap.h"
-#ifdef SLAPD_EXTERNAL_EXTENSIONS
-
-typedef struct extensions_cookie_t {
- Connection *conn;
- Operation *op;
-} extensions_cookie_t;
-
#define MAX_OID_LENGTH 128
-typedef struct extensions_list_t {
- struct extensions_list_t *next;
+typedef struct extop_list_t {
+ struct extop_list_t *next;
char *oid;
- int (*ext_main)(int (*)(), void *, char *reqoid, struct berval *reqdata, char **rspoid, struct berval *rspdata, char **text);
-} extensions_list_t;
-
-extensions_list_t *supp_ext_list = NULL;
-
-extensions_list_t *find_extension (extensions_list_t *list, char *oid);
-int extensions_callback (extensions_cookie_t *cookie, int msg, int arg, void *argp);
+ SLAP_EXTOP_MAIN_FN ext_main;
+} extop_list_t;
-#else
+extop_list_t *supp_ext_list = NULL;
-char *supportedExtensions[] = {
- NULL
-};
-#endif
+static extop_list_t *find_extop( extop_list_t *list, char *oid );
+static int extop_callback(
+ Connection *conn, Operation *op,
+ int msg, int arg, void *argp);
char *
-get_supported_extension (int index)
+get_supported_extop (int index)
{
-#ifdef SLAPD_EXTERNAL_EXTENSIONS
- extensions_list_t *ext;
+ extop_list_t *ext;
/* linear scan is slow, but this way doesn't force a
* big change on root_dse.c, where this routine is used.
if (ext == NULL)
return(NULL);
return(ext->oid);
-#else
- return(supportedExtensions[index]);
-#endif
}
int
)
{
int rc = LDAP_SUCCESS;
- char* reqoid ;
- struct berval reqdata;
+ char* oid;
+ struct berval *reqdata;
ber_tag_t tag;
ber_len_t len;
-#ifdef SLAPD_EXTERNAL_EXTENSIONS
- extensions_list_t *ext;
- char *rspoid, *text;
- struct berval rspdata;
- extensions_cookie_t cookie;
-#endif
+ extop_list_t *ext;
+ char *text;
+ struct berval *rspdata;
Debug( LDAP_DEBUG_TRACE, "do_extended\n", 0, 0, 0 );
- reqoid = NULL;
- reqdata.bv_val = NULL;
+ oid = NULL;
+ reqdata = NULL;
if( op->o_protocol < LDAP_VERSION3 ) {
Debug( LDAP_DEBUG_ANY, "do_extended: protocol version (%d) too low\n",
goto done;
}
- if ( ber_scanf( op->o_ber, "{a" /*}*/, &reqoid ) == LBER_ERROR ) {
+ if ( ber_scanf( op->o_ber, "{a" /*}*/, &oid ) == LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 );
send_ldap_disconnect( conn, op,
LDAP_PROTOCOL_ERROR, "decoding error" );
goto done;
}
-#ifdef SLAPD_EXTERNAL_EXTENSIONS
- if( !(ext = find_extension(supp_ext_list, reqoid)) )
-#else
- if( !charray_inlist( supportedExtensions, reqoid ) )
-#endif
- {
+ if( !(ext = find_extop(supp_ext_list, oid)) ) {
Debug( LDAP_DEBUG_ANY, "do_extended: unsupported operation \"%s\"\n",
- reqoid, 0 ,0 );
+ oid, 0 ,0 );
send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
- NULL, "unsuppored extended operation", NULL, NULL );
+ NULL, "unsupported extended operation", NULL, NULL );
goto done;
}
tag = ber_peek_tag( op->o_ber, &len );
if( ber_peek_tag( op->o_ber, &len ) == LDAP_TAG_EXOP_REQ_VALUE ) {
- if( ber_scanf( op->o_ber, "o", &reqdata ) == LBER_ERROR ) {
+ if( ber_scanf( op->o_ber, "O", &reqdata ) == LBER_ERROR ) {
Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 );
send_ldap_disconnect( conn, op,
LDAP_PROTOCOL_ERROR, "decoding error" );
return rc;
}
- Debug( LDAP_DEBUG_ARGS, "do_extended: oid \"%s\"\n", reqoid, 0 ,0 );
+ Debug( LDAP_DEBUG_ARGS, "do_extended: oid=%s\n", oid, 0 ,0 );
-#ifdef SLAPD_EXTERNAL_EXTENSIONS
- cookie.conn = conn;
- cookie.op = op;
- rspoid = NULL;
- rspdata.bv_len = 0;
- rspdata.bv_val = NULL;
+ rspdata = NULL;
text = NULL;
- rc = (ext->ext_main)(extensions_callback, &cookie, reqoid, &reqdata, &rspoid, &rspdata, &text);
- send_ldap_extended(conn, op, rc, NULL, text, rspoid, rspdata.bv_val ? &rspdata : NULL);
+ rc = (ext->ext_main)( extop_callback, conn, op,
+ oid, reqdata, &rspdata, &text );
- if (rspoid != NULL)
- free(rspoid);
- if ( rspdata.bv_val != NULL )
- free(rspdata.bv_val);
- if ( text != NULL )
- free(text);
+ if( rc != SLAPD_ABANDON ) {
+ send_ldap_extended( conn, op, rc, NULL, text,
+ oid, rspdata );
+ }
-#else
- send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
- NULL, "unsupported extended operation", NULL, NULL );
+ if ( rspdata != NULL )
+ ber_bvfree( rspdata );
-#endif
+ if ( text != NULL )
+ free(text);
done:
- if ( reqoid != NULL ) {
- free( reqoid );
+ if ( reqdata != NULL ) {
+ ber_bvfree( reqdata );
}
- if ( reqdata.bv_val != NULL ) {
- free( reqdata.bv_val );
+ if ( oid != NULL ) {
+ free( oid );
}
return rc;
}
-#ifdef SLAPD_EXTERNAL_EXTENSIONS
-
int
-load_extension (
- const void *module,
- const char *file_name
-)
+load_extop(
+ const char *ext_oid,
+ SLAP_EXTOP_MAIN_FN ext_main )
{
- extensions_list_t *ext;
- int (*ext_getoid)(int index, char *oid, int blen);
+ extop_list_t *ext;
int rc;
- ext = ch_calloc(1, sizeof(extensions_list_t));
+ if( ext_oid == NULL || *ext_oid == '\0' ) return -1;
+ if(!ext_main) return -1;
+
+ ext = ch_calloc(1, sizeof(extop_list_t));
if (ext == NULL)
return(-1);
- ext->oid = ch_malloc(MAX_OID_LENGTH);
+ ext->oid = ch_strdup( ext_oid );
if (ext->oid == NULL) {
free(ext);
return(-1);
}
- ext->ext_main = module_resolve(module, "ext_main");
- if (ext->ext_main == NULL) {
- free(ext->oid);
- free(ext);
- return(-1);
- }
-
- ext_getoid = module_resolve(module, "ext_getoid");
- if (ext_getoid == NULL) {
- free(ext->oid);
- free(ext);
- return(-1);
- }
- rc = (ext_getoid)(0, ext->oid, MAX_OID_LENGTH);
- if (rc != 0) {
- free(ext->oid);
- free(ext);
- return(rc);
- }
- if (*ext->oid == 0) {
- free(ext->oid);
- free(ext);
- return(-1);
- }
-
+ ext->ext_main = ext_main;
ext->next = supp_ext_list;
+
supp_ext_list = ext;
+
return(0);
}
-extensions_list_t *
-find_extension (extensions_list_t *list, char *oid)
+
+static extop_list_t *
+find_extop( extop_list_t *list, char *oid )
{
- extensions_list_t *ext;
+ extop_list_t *ext;
for (ext = list; ext; ext = ext->next) {
if (strcmp(ext->oid, oid) == 0)
}
int
-extensions_callback (extensions_cookie_t *cookie, int msg, int arg, void *argp)
+extop_callback(
+ Connection *conn, Operation *op,
+ int msg, int arg, void *argp)
{
- if (cookie == NULL)
- return(-1);
-
if (argp == NULL)
return(-1);
switch (msg) {
- case 0: /* SLAPD_EXT_GETVERSION */
+ case SLAPD_EXTOP_GETVERSION:
*(int *)argp = 1;
return(0);
- case 1: /* SLAPD_EXT_GETPROTO */
- *(int *)argp = cookie->op->o_protocol;
+ case SLAPD_EXTOP_GETPROTO:
+ *(int *)argp = op->o_protocol;
return(0);
- case 2: /* SLAPD_EXT_GETAUTH */
- *(int *)argp = cookie->op->o_authtype;
+ case SLAPD_EXTOP_GETAUTH:
+ *(int *)argp = op->o_authtype;
return(0);
- case 3: /* SLAPD_EXT_GETDN */
- *(char **)argp = cookie->op->o_dn;
+ case SLAPD_EXTOP_GETDN:
+ *(char **)argp = op->o_dn;
return(0);
- case 4: /* SLAPD_EXT_GETCLIENT */
- if (cookie->conn->c_peer_domain != NULL && *cookie->conn->c_peer_domain != 0) {
- *(char **)argp = cookie->conn->c_peer_domain;
+ case SLAPD_EXTOP_GETCLIENT:
+ if (conn->c_peer_domain != NULL && *conn->c_peer_domain != 0) {
+ *(char **)argp = conn->c_peer_domain;
return(0);
}
- if (cookie->conn->c_peer_name != NULL && *cookie->conn->c_peer_name != 0) {
- *(char **)argp = cookie->conn->c_peer_name;
+ if (conn->c_peer_name != NULL && *conn->c_peer_name != 0) {
+ *(char **)argp = conn->c_peer_name;
return(0);
}
break;
}
return(-1);
}
-
-#endif
-
rc = sasl_init();
}
+ slap_passwd_init();
+
return rc;
}
goto cleanup;
}
+ /* make sure this backend recongizes critical controls */
+ rc = backend_check_controls( be, conn, op ) ;
+
+ if( rc != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, rc,
+ NULL, NULL, NULL, NULL );
+ }
+
if ( global_readonly || be->be_readonly ) {
Debug( LDAP_DEBUG_ANY, "do_modify: database is read-only\n",
0, 0, 0 );
goto cleanup;
}
+ /* make sure this backend recongizes critical controls */
+ rc = backend_check_controls( be, conn, op ) ;
+
+ if( rc != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, rc,
+ NULL, NULL, NULL, NULL );
+ }
+
if ( global_readonly || be->be_readonly ) {
Debug( LDAP_DEBUG_ANY, "do_modrdn: database is read-only\n",
0, 0, 0 );
#include <ltdl.h>
-int load_null (const void *module, const char *file_name);
-int load_extension (const void *module, const char *file_name);
+typedef int (*MODULE_INIT_FN)(
+ int argc,
+ char *argv[]);
+typedef int (*MODULE_LOAD_FN)(
+ const void *module,
+ const char *filename);
+typedef int (*MODULE_TERM_FN)(void);
+
struct module_regtable_t {
char *type;
- int (*proc)(const void *module, const char *file_name);
+ MODULE_LOAD_FN proc;
} module_regtable[] = {
- { "null", load_null },
+ { "null", load_null_module },
#ifdef SLAPD_EXTERNAL_EXTENSIONS
- { "extension", load_extension },
+ { "extension", load_extop_module },
#endif
- { NULL, NULL }
- };
+ { NULL, NULL }
+};
typedef struct module_loaded_t {
struct module_loaded_t *next;
module_loaded_t *module_list = NULL;
-int module_unload (module_loaded_t *module);
+static int module_unload (module_loaded_t *module);
int module_init (void)
{
module_loaded_t *module = NULL;
const char *error;
int rc;
- int (*initialize) LDAP_P((int argc, char *argv[]));
+ MODULE_INIT_FN initialize;
module = (module_loaded_t *)ch_calloc(1, sizeof(module_loaded_t));
if (module == NULL) {
return(lt_dlsym(((module_loaded_t *)module)->lib, name));
}
-int module_unload (module_loaded_t *module)
+static int module_unload (module_loaded_t *module)
{
module_loaded_t *mod;
- int (*terminate) LDAP_P((void));
+ MODULE_TERM_FN terminate;
if (module != NULL) {
/* remove module from tracking list */
return 0;
}
+#ifdef SLAPD_EXTERNAL_EXTENSIONS
+int
+load_extop_module (
+ const void *module,
+ const char *file_name
+)
+{
+ ext_main = module_resolve(module, "ext_main");
+ if (ext_main == NULL) {
+ return(-1);
+ }
+
+ ext_getoid = module_resolve(module, "ext_getoid");
+ if (ext_getoid == NULL) {
+ return(-1);
+ }
+
+ return load_extop( ext_main, ext_getoid );
+}
+#endif /* SLAPD_EXTERNAL_EXTENSIONS */
#endif /* SLAPD_MODULES */
#include <lutil.h>
+static int passwd_main(
+ SLAP_EXTOP_CALLBACK_FN ext_callback,
+ Connection *conn, Operation *op, char *oid,
+ struct berval *reqdata, struct berval **rspdata, char **text )
+{
+ int rc;
+ BerElement *ber;
+ struct berval *cred = NULL;
+ ber_int_t type;
+
+ assert( oid != NULL );
+ assert( strcmp( LDAP_EXOP_X_MODIFY_PASSWD, oid ) == 0 );
+
+ if( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
+ *text = ch_strdup("only authenicated users may change passwords");
+ return LDAP_STRONG_AUTH_REQUIRED;
+ }
+
+ if( reqdata == NULL || reqdata->bv_len == 0 ) {
+ *text = ch_strdup("data missing");
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ ber = ber_init( reqdata );
+
+ if( ber == NULL ) {
+ *text = ch_strdup("password decoding error");
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ rc = ber_scanf(ber, "{iO}", &type, &cred );
+ ber_free( ber, 1 );
+
+ if( rc == LBER_ERROR ) {
+ *text = ch_strdup("data decoding error");
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if( cred == NULL || cred->bv_len == 0 ) {
+ *text = ch_strdup("password missing");
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if( type != 0 ) {
+ ber_bvfree( cred );
+ *text = ch_strdup("password type unknown");
+ 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, cred, rspdata, text );
+
+ } else {
+ *text = ch_strdup("operation not supported for current user");
+ rc = LDAP_UNWILLING_TO_PERFORM;
+ }
+
+ ber_bvfree( cred );
+ return rc;
+}
+
+int
+slap_passwd_init( void )
+{
+ return load_extop( LDAP_EXOP_X_MODIFY_PASSWD, passwd_main );
+}
int
slap_passwd_check(
Attribute *a,
- struct berval *cred
-)
+ struct berval *cred )
{
int i;
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
- if ( a->a_syntax == SYNTAX_BIN ) {
- int result;
+ int result;
#ifdef SLAPD_CRYPT
- ldap_pvt_thread_mutex_lock( &crypt_mutex );
+ ldap_pvt_thread_mutex_lock( &crypt_mutex );
#endif
- result = lutil_passwd(
- (char*) cred->bv_val,
- (char*) a->a_vals[i]->bv_val,
- NULL );
+ result = lutil_passwd(
+ a->a_vals[i]->bv_val,
+ cred->bv_val,
+ NULL );
#ifdef SLAPD_CRYPT
- ldap_pvt_thread_mutex_unlock( &crypt_mutex );
+ ldap_pvt_thread_mutex_unlock( &crypt_mutex );
#endif
- return result;
-
- } else {
- if ( value_cmp( a->a_vals[i], cred, a->a_syntax, 1 ) == 0 ) {
- return( 0 );
- }
- }
+ return result;
}
return( 1 );
}
+
+struct berval * slap_passwd_generate(
+ struct berval * cred )
+{
+ char* hash = default_passwd_hash ? default_passwd_hash : "{SSHA}";
+
+ struct berval *new = ber_memalloc( sizeof(struct berval) );
+
+ if( new == NULL ) return NULL;
+
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_lock( &crypt_mutex );
+#endif
+
+ new->bv_val = lutil_passwd_generate( cred->bv_val , hash );
+
+#ifdef SLAPD_CRYPT
+ ldap_pvt_thread_mutex_unlock( &crypt_mutex );
+#endif
+
+ if( new->bv_val == NULL ) {
+ ber_bvfree( new );
+ return NULL;
+ }
+
+ new->bv_len = strlen( new->bv_val );
+
+ return new;
+}
#define be_entry_release_r( be, e ) be_entry_release_rw( be, e, 0 )
#define be_entry_release_w( be, e ) be_entry_release_rw( be, e, 1 )
-
LIBSLAPD_F (int) backend_unbind LDAP_P((Connection *conn, Operation *op));
+LIBSLAPD_F( int ) backend_check_controls LDAP_P((
+ Backend *be,
+ Connection *conn,
+ Operation *op ));
+
LIBSLAPD_F (int) backend_connection_init LDAP_P((Connection *conn));
LIBSLAPD_F (int) backend_connection_destroy LDAP_P((Connection *conn));
* extended.c
*/
-LIBSLAPD_F (int) load_extension LDAP_P((const void *module, const char *file_name));
-LIBSLAPD_F (char *) get_supported_extension LDAP_P((int index));
+#define SLAPD_EXTOP_GETVERSION 0
+#define SLAPD_EXTOP_GETPROTO 1
+#define SLAPD_EXTOP_GETAUTH 2
+#define SLAPD_EXTOP_GETDN 3
+#define SLAPD_EXTOP_GETCLIENT 4
+
+typedef int (*SLAP_EXTOP_CALLBACK_FN) LDAP_P((
+ Connection *conn, Operation *op,
+ int msg, int arg, void *argp ));
+
+typedef int (*SLAP_EXTOP_MAIN_FN) LDAP_P((
+ SLAP_EXTOP_CALLBACK_FN,
+ Connection *conn, Operation *op,
+ char * oid,
+ struct berval * reqdata,
+ struct berval ** rspdata,
+ char ** text ));
+
+typedef int (*SLAP_EXTOP_GETOID_FN) LDAP_P((
+ int index, char *oid, int blen ));
+
+LIBSLAPD_F (int) load_extop LDAP_P((
+ const char *ext_oid,
+ SLAP_EXTOP_MAIN_FN ext_main ));
+
+LIBSLAPD_F (char *) get_supported_extop LDAP_P((int index));
/*
* filter.c
*/
#ifdef SLAPD_MODULES
+
LIBSLAPD_F (int) module_init LDAP_P(( void ));
LIBSLAPD_F (int) module_kill LDAP_P(( void ));
-LIBSLAPD_F (int) module_load LDAP_P(( const char* file_name, int argc, char *argv[] ));
+LIBSLAPD_F (int) load_null_module(
+ const void *module, const char *file_name);
+LIBSLAPD_F (int) load_extop_module(
+ const void *module, const char *file_name);
+
+LIBSLAPD_F (int) module_load LDAP_P((
+ const char* file_name,
+ int argc, char *argv[] ));
LIBSLAPD_F (int) module_path LDAP_P(( const char* path ));
-LIBSLAPD_F (void) *module_resolve LDAP_P((const void *module, const char *name));
+LIBSLAPD_F (void) *module_resolve LDAP_P((
+ const void *module, const char *name));
+
#endif /* SLAPD_MODULES */
/*
LIBSLAPD_F (int) slap_passwd_check(
Attribute *attr,
struct berval *cred );
+LIBSLAPD_F (struct berval *) slap_passwd_generate(
+ struct berval *cred );
/*
* kerberos.c
LIBSLAPD_F (int) global_idletimeout;
LIBSLAPD_F (int) global_schemacheck;
LIBSLAPD_F (char) *global_realm;
+LIBSLAPD_F (char) *default_passwd_hash;
LIBSLAPD_F (int) lber_debug;
LIBSLAPD_F (int) ldap_syslog;
const char *text,
struct berval **ref,
const char *resoid,
- struct berval *resdata,
+ struct berval *data,
LDAPControl **ctrls
)
{
rc = ber_printf( ber, "s", resoid );
}
- if( rc != -1 && resdata != NULL ) {
- rc = ber_printf( ber, "O", resdata );
-
+ if( rc != -1 && data != NULL ) {
+ rc = ber_printf( ber, "O", data );
}
if( rc != -1 ) {
}
/* supportedExtension */
- for ( i=0; (val.bv_val = get_supported_extension(i)) != NULL; i++ ) {
+ for ( i=0; (val.bv_val = get_supported_extop(i)) != NULL; i++ ) {
val.bv_len = strlen( val.bv_val );
attr_merge( e, "supportedExtension", vals );
}
goto return_results;
}
+ /* make sure this backend recongizes critical controls */
+ rc = backend_check_controls( be, conn, op ) ;
+
+ if( rc != LDAP_SUCCESS ) {
+ send_ldap_result( conn, op, rc,
+ NULL, NULL, NULL, NULL );
+ }
+
/* deref the base if needed */
nbase = suffix_alias( be, nbase );
#define MAXREMATCHES 10
+/* psuedo error code to indicating abandoned operation */
+#define SLAPD_ABANDON -1
+
/* XXYYZ: these macros assume 'x' is an ASCII x */
#define DNSEPARATOR(c) ((c) == ',' || (c) == ';')
#define SEPARATOR(c) ((c) == ',' || (c) == ';' || (c) == '+')
#define be_modrdn bd_info->bi_op_modrdn
#define be_search bd_info->bi_op_search
+#define be_extended bd_info->bi_extended
+
#define be_release bd_info->bi_entry_release_rw
#define be_group bd_info->bi_acl_group
+#define be_controls bd_info->bi_controls
+
#define be_connection_init bd_info->bi_connection_init
#define be_connection_destroy bd_info->bi_connection_destroy
void *be_private; /* anything the backend database needs */
};
+typedef int (*SLAP_EXTENDED_FN) LDAP_P((
+ Backend *be,
+ struct slap_conn *conn,
+ struct slap_op *op,
+ char *oid,
+ struct berval * reqdata,
+ struct berval ** rspdata,
+ char** text ));
+
struct slap_backend_info {
char *bi_type; /* type of backend */
struct slap_conn *c, struct slap_op *o,
ber_int_t msgid));
+ /* Extended Operations Helper */
+ SLAP_EXTENDED_FN bi_extended;
+
/* Auxilary Functions */
int (*bi_entry_release_rw) LDAP_P((BackendDB *bd, Entry *e, int rw));
#define SLAP_INDEX_ADD_OP 0x0001
#define SLAP_INDEX_DELETE_OP 0x0002
+ char **bi_controls; /* supported controls */
+
unsigned int bi_nDB; /* number of databases of this type */
void *bi_private; /* anything the backend type needs */
};
time_t o_time; /* time op was initiated */
int o_bind_in_progress; /* multi-step bind in progress */
+#ifdef SLAP_AUTHZID
+ /* should only be used for reporting purposes */
+ char *o_authc_dn; /* authentication DN */
+ /* should be used as the DN of the User */
+ char *o_authz_dn; /* authorization DN */
+ char *o_authz_ndn; /* authorizaiton NDN */
+
+#else
char *o_dn; /* dn bound when op was initiated */
char *o_ndn; /* normalized dn bound when op was initiated */
+#endif
+
ber_int_t o_protocol; /* version of the LDAP protocol used by client */
ber_tag_t o_authtype; /* auth method used to bind dn */
/* values taken from ldap.h */
char *c_peer_name; /* peer name (trans=addr:port) */
char *c_sock_name; /* sock name (trans=addr:port) */
+ /* only can be changed by binding thread */
+ int c_bind_in_progress; /* multi-op bind in progress */
#ifdef HAVE_CYRUS_SASL
sasl_conn_t *c_sasl_context;
#endif
+ void *c_authstate; /* SASL state data */
- /* only can be changed by binding thread */
- int c_bind_in_progress; /* multi-op bind in progress */
+ Backend *c_authc_backend;
+
+ /* authorization backend */
+ Backend *c_authz_backend;
+
+#ifdef SLAP_AUTHZID
+ /* authentication backend */
+ /* should only be used for reporting purposes */
+ char *c_authc_dn; /* authentication DN */
+ /* should be used as the DN of the User */
+ char *c_authz_dn; /* authorization DN */
+ char *c_authz_ndn; /* authorization NDN */
+
+#else
char *c_cdn; /* DN provided by the client */
char *c_dn; /* DN bound to this conn */
+#endif
+
ber_int_t c_protocol; /* version of the LDAP protocol used by client */
ber_tag_t c_authtype;/* auth method used to bind c_dn */
char *c_authmech; /* SASL mechanism used to bind c_dn */
- void *c_authstate; /* SASL state data */
Operation *c_ops; /* list of operations being processed */
Operation *c_pending_ops; /* list of pending operations */
../module.o ../aclparse.o ../schema.o ../filterentry.o \
../acl.o ../phonetic.o ../attr.o ../value.o ../entry.o \
../dn.o ../filter.o ../str2filter.o ../ava.o ../init.o \
- ../controls.o ../schemaparse.o ../kerberos.o ../passwd.o
+ ../controls.o ../schemaparse.o ../kerberos.o ../passwd.o \
+ ../extended.o
+
SLAPOBJS = $(SLAPD_OBJS) slapcommon.o mimic.o
EDB2LDIFSRCS = edb2ldif.c ldapsyntax.c