]> git.sur5r.net Git - openldap/commitdiff
Reengineered ldappasswd(1). Uses extended operation to set
authorKurt Zeilenga <kurt@openldap.org>
Wed, 8 Dec 1999 04:37:59 +0000 (04:37 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Wed, 8 Dec 1999 04:37:59 +0000 (04:37 +0000)
user password.  Likely to be modified to use bind control
instead.  Use of modify deprecated in favor mechanisms that
support passwords stored externally to the directory (such
as in a SASL service).
Modified slapd extended operation infrastructure to support
backend provided extended operations.

39 files changed:
clients/tools/ldappasswd.c
doc/man/man1/ldappasswd.1
doc/man/man3/ldap_url.3
include/ldap.h
include/lutil.h
libraries/libldif/line64.c
libraries/liblutil/passwd.c
servers/slapd/add.c
servers/slapd/back-bdb2/init.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldbm/Makefile.in
servers/slapd/back-ldbm/extended.c [new file with mode: 0644]
servers/slapd/back-ldbm/external.h
servers/slapd/back-ldbm/init.c
servers/slapd/back-ldbm/modify.c
servers/slapd/back-ldbm/modrdn.c
servers/slapd/back-ldbm/passwd.c [new file with mode: 0644]
servers/slapd/back-ldbm/proto-back-ldbm.h
servers/slapd/back-passwd/init.c
servers/slapd/back-perl/init.c
servers/slapd/back-shell/init.c
servers/slapd/backend.c
servers/slapd/bind.c
servers/slapd/compare.c
servers/slapd/config.c
servers/slapd/controls.c
servers/slapd/delete.c
servers/slapd/extended.c
servers/slapd/init.c
servers/slapd/modify.c
servers/slapd/modrdn.c
servers/slapd/module.c
servers/slapd/passwd.c
servers/slapd/proto-slap.h
servers/slapd/result.c
servers/slapd/root_dse.c
servers/slapd/search.c
servers/slapd/slap.h
servers/slapd/tools/Makefile.in

index c6cc0bce18e92c342a7b163ce9e6f0cdcc878337..c8337121baf0117809c358cd5f60a7d1e5c76c09 100644 (file)
@@ -3,20 +3,6 @@
  * 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;
@@ -415,106 +79,27 @@ main (int argc, char *argv[])
                        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;
 
@@ -529,50 +114,35 @@ main (int argc, char *argv[])
                        }
                        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 );
@@ -585,105 +155,70 @@ main (int argc, char *argv[])
 #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);
 
index 24d5ca240df561c78af30f23419078fa57ba63f5..6772123db9bc34615c3c2248904cce9217f0dfe2 100644 (file)
 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.  
index a10079260985abea4a2d9eb3e9d3f19d4abb4fd6..9acdd89f37d254eb8a463961d95e14a80531d4cf 100644 (file)
@@ -74,10 +74,10 @@ LDAP URLs look like this:
 
 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
index 5af2eb99375f2e35581e43aa0dfa76b2d7d242f6..3ba432e10926abbc36bdd9199184e7e2da4168c8 100644 (file)
@@ -104,8 +104,6 @@ LDAP_BEGIN_DECL
 
 /* 0x34 - 0x0fff not defined by current draft */
 
-/* extended options - none */
-
 /* private and experimental options */
 #define LDAP_OPT_DNS                           0x4001  /* use DN & DNS */
 
@@ -172,7 +170,7 @@ typedef struct ldapcontrol {
 #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 */
@@ -181,6 +179,7 @@ typedef struct ldapcontrol {
 
 
 /* LDAP Extended Operations */
+#define LDAP_EXOP_X_MODIFY_PASSWD "1.3.6.1.4.1.4203.666.6.1"
 
 
 /* 
index 2a207d43daeb188e0eb33106154305df2c90d339..e26374d6b3882b85413f399048cdb85a151ea20e 100644 (file)
@@ -58,10 +58,15 @@ lutil_entropy LDAP_P((
 /* 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 )
index b02cf8f4b2c01a989c5587a794de07310664f73c..edec31540d35a8953718292501c2d8a39e98e573 100644 (file)
@@ -405,8 +405,10 @@ ldif_sput(
        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;
 
index 4960add60d74dfb82b963cb1e7d9355256a0eca8..89ae997be99d84bfc4daedda137be8ee546a8027 100644 (file)
@@ -21,6 +21,8 @@
 #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, schemelen ) == 0 ) {
-               return &passwd[len];
+       if( strncasecmp( passwd, scheme->name, scheme->namelen ) == 0 ) {
+               return &passwd[scheme->namelen];
        }
 
        return NULL;
@@ -96,146 +186,376 @@ static const char *passwd_scheme(
  */
 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
index 093072677b17bc12930f847c597af3749465d154..9bc2133841a79b5b2a7e623f862457f1199106a3 100644 (file)
@@ -147,6 +147,14 @@ do_add( Connection *conn, Operation *op )
                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 );
index 8d8dcfd12746b0c511cc577ad0cdca2a7a7fed55..d3b243f2ca2eb90fd1f64706def4c093d3f1ccf7 100644 (file)
@@ -55,6 +55,14 @@ bdb2_back_initialize(
 {
        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;
@@ -76,6 +84,8 @@ bdb2_back_initialize(
        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;
 
index e1d80f76e68bd9277e8b13414705f9eb881ddca7..830c833e8db5b920121a0b6f4ba74f68f7eb7647 100644 (file)
@@ -72,6 +72,8 @@ ldap_back_initialize(
        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;
index 7fb735cf29d64fdb5bb1dbf69e588df243a60367..15211cb0f77d4f962f91a7febe90c7b717a00c2d 100644 (file)
@@ -3,11 +3,13 @@
 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
diff --git a/servers/slapd/back-ldbm/extended.c b/servers/slapd/back-ldbm/extended.c
new file mode 100644 (file)
index 0000000..eb55797
--- /dev/null
@@ -0,0 +1,51 @@
+/* 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;
+}
+
index c8a1b25d5f47939df6eb1df6688c9ac93de763b1..24ca3560a84ad6aa1a6fb63e3eafff14e2b82f7a 100644 (file)
@@ -22,6 +22,13 @@ extern int   ldbm_back_db_destroy LDAP_P(( BackendDB *bd ));
 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,
index e399f676ab1bcab0f5a3166f8d58156d92e9266d..7d59f5dde0d271860d865e0aca71b2ca3eb84b07 100644 (file)
@@ -35,6 +35,14 @@ ldbm_back_initialize(
     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;
@@ -56,6 +64,8 @@ ldbm_back_initialize(
        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;
 
index fa55df90bef373b261769fdb18fdaab54d00cc03..b3f104fcc9c7844ec8e352eaf8110aba02c825b8 100644 (file)
@@ -39,9 +39,7 @@ int ldbm_modify_internal(
        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;
@@ -82,9 +80,7 @@ int ldbm_modify_internal(
                        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; 
                }
        }
 
@@ -94,7 +90,7 @@ int ldbm_modify_internal(
                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 );
 
@@ -103,9 +99,7 @@ int ldbm_modify_internal(
                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 */
@@ -114,7 +108,7 @@ int ldbm_modify_internal(
                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 );
 
@@ -143,20 +137,10 @@ int ldbm_modify_internal(
        /* 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;
 }
 
 
@@ -170,6 +154,7 @@ ldbm_back_modify(
     LDAPModList        *modlist
 )
 {
+       int rc;
        struct ldbminfo *li = (struct ldbminfo *) be->be_private;
        Entry           *matched;
        Entry           *e;
@@ -221,7 +206,14 @@ ldbm_back_modify(
        }
        
        /* 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;
        }
 
@@ -234,6 +226,7 @@ ldbm_back_modify(
 
        send_ldap_result( conn, op, LDAP_SUCCESS,
                NULL, NULL, NULL, NULL );
+
        cache_return_entry_w( &li->li_cache, e );
        return( 0 );
 
index 6152c952a4a18daa00753bf4c116353dceaa9c51..ac9f17d69984acca1ae159e8f1e6441812afd48d 100644 (file)
@@ -453,8 +453,13 @@ ldbm_back_modrdn(
        }
 
        /* 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;
        }
diff --git a/servers/slapd/back-ldbm/passwd.c b/servers/slapd/back-ldbm/passwd.c
new file mode 100644 (file)
index 0000000..355405b
--- /dev/null
@@ -0,0 +1,109 @@
+/* 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;
+}
index 1b466f4eb69f87bbe73ed403a0030c23a61747ea..c6aeaa519f05cec0b87bb364b4d71a26c7182da2 100644 (file)
@@ -144,13 +144,16 @@ int index_change_values LDAP_P(( Backend *be,
                                 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
@@ -166,9 +169,11 @@ int index_change_values LDAP_P(( Backend *be,
 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
index 609231dba429661ea69646c9ea0d694108c0bb54..ac41c382f4d5480357d5d78cecde4949b80aa537 100644 (file)
@@ -51,6 +51,8 @@ passwd_back_initialize(
        bi->bi_op_delete = 0;
        bi->bi_op_abandon = 0;
 
+       bi->bi_extended = 0;
+
        bi->bi_acl_group = 0;
 
        bi->bi_connection_init = 0;
index c62391f468feb278934d7be2b957e9cf2d7001c9..1fdeb55ce399270896d85eb290861749b6d68c3e 100644 (file)
@@ -96,6 +96,8 @@ perl_back_initialize(
        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;
index 57c3742c4eae7c6c635b6272f88f7ac8074ca363..f86ccccb0d144d1d6a6c04a1ccbc77e2d3ec6ee2 100644 (file)
@@ -51,6 +51,8 @@ shell_back_initialize(
        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;
index a7a6b2c9f4e890e5c0f48998a723cc918e67aedf..d1a71cc491897d95866572383a44b9eb2e9b9a2c 100644 (file)
@@ -506,14 +506,14 @@ be_isroot_pw( Backend *be, const char *ndn, struct berval *cred )
        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 );
@@ -584,6 +584,29 @@ backend_connection_destroy(
        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,
index 449c820b8ff315fc9cbfc346086f5c73709dbf8a..9be3d11c8a2135472f92dc119a945642b0b1755e 100644 (file)
@@ -68,6 +68,8 @@ do_bind(
                conn->c_dn = NULL;
        }
 
+       conn->c_authz_backend = NULL;
+
        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
        if ( op->o_dn != NULL ) {
@@ -281,14 +283,28 @@ do_bind(
                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;
index 86bdaff74dbb2dced9e1b1ac5a735fbec6f34802..0454281b71a1728ff6b54175bc6e45535c0b118b 100644 (file)
@@ -99,6 +99,14 @@ do_compare(
                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 );
 
index cee2fe9e3d7a4f9796d1705a33ef272053a63c41..1c72b121af44857907abe981421616556e577b39 100644 (file)
@@ -34,6 +34,7 @@ int           global_lastmod = ON;
 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;
@@ -171,6 +172,24 @@ read_config( const char *fname )
 
                        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 ) {
index f906b4068dcf04742fe3483de71517a55d705969..c5cdb803d40a2400266afab80706450cac61f612 100644 (file)
@@ -21,7 +21,7 @@
 
 char *supportedControls[] = {
        LDAP_CONTROL_MANAGEDSAIT,
-       LDAP_CONTROL_X_CHANGE_PASSWD,
+/*     LDAP_CONTROL_X_CHANGE_PASSWD, */
        NULL
 };
 
index 87f4672919a0ac62fc6200571e4277161148777a..77b2f4098a1e76f37cdb4af0c7110a0126c8795b 100644 (file)
@@ -86,6 +86,14 @@ do_delete(
                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 );
index 0f0d3ed01bea0ef5f164756027625305ccf95b17..2abf5407f64378b2debcaee7e341ab56935bc6d8 100644 (file)
 
 #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.
@@ -73,9 +60,6 @@ get_supported_extension (int index)
        if (ext == NULL)
                return(NULL);
        return(ext->oid);
-#else
-       return(supportedExtensions[index]);
-#endif
 }
 
 int
@@ -85,21 +69,18 @@ do_extended(
 )
 {
        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",
@@ -110,7 +91,7 @@ do_extended(
                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" );
@@ -118,23 +99,18 @@ do_extended(
                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" );
@@ -148,99 +124,70 @@ do_extended(
                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)
@@ -250,38 +197,37 @@ find_extension (extensions_list_t *list, char *oid)
 }
 
 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;
@@ -291,6 +237,3 @@ extensions_callback (extensions_cookie_t *cookie, int msg, int arg, void *argp)
        }
        return(-1);
 }
-
-#endif
-
index 510816798af8ee3491da3c4eb3a6b582ae0a265d..f9020726bced8d235c9fe8c20b59a51371ceea5d 100644 (file)
@@ -137,6 +137,8 @@ int slap_startup( Backend *be )
                rc = sasl_init();
        }
 
+       slap_passwd_init();
+
        return rc;
 }
 
index 7d1fc71abdbb08ce95c07e28bea5f0d2fbf1b04f..2eea03e3ef3619dbe136fcac4d40dde85c350970 100644 (file)
@@ -178,6 +178,14 @@ do_modify(
                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 );
index 2292789beade64a18981fa747a49a95453e683c7..0467e54dc6f35cd26b0098fd018324a5340fd694 100644 (file)
@@ -172,6 +172,14 @@ do_modrdn(
                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 );
index 71d93a300fa65d8987286b60c8b713b3921a58b1..984f904948a73b5ae7d7abf2a45e0471834c40ad 100644 (file)
@@ -7,19 +7,25 @@
 
 #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;
@@ -28,7 +34,7 @@ typedef struct module_loaded_t {
 
 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)
 {
@@ -60,7 +66,7 @@ int module_load(const char* file_name, int argc, char *argv[])
        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) {
@@ -153,10 +159,10 @@ void *module_resolve (const void *module, const char *name)
        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 */
@@ -188,5 +194,25 @@ int load_null (const void *module, const char *file_name)
        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 */
 
index 05d341cb9f5a59d2da0682dfd70e595ca8690788..b06cd71e056fdad8cbe4c8a7dfcec2c68e5372f7 100644 (file)
 
 #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;
+}
index 9c337317733bf6fcd10766d49efff07f61ddf6f0..e2d2bd8c0c81f4d6ced6b9c92291ea5eea6ef33e 100644 (file)
@@ -100,9 +100,13 @@ LIBSLAPD_F (int) be_entry_release_rw LDAP_P(( Backend *be, Entry *e, int rw ));
 #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));
 
@@ -239,8 +243,32 @@ LIBSLAPD_F (int) entry_id_cmp LDAP_P(( Entry *a, Entry *b ));
  * 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
@@ -268,13 +296,23 @@ LIBSLAPD_F (int) lock_fclose LDAP_P(( FILE *fp, FILE *lfp ));
  */
 
 #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 */
 
 /*
@@ -445,6 +483,8 @@ LIBSLAPD_F (void) slap_init_user LDAP_P(( char *username, char *groupname ));
 LIBSLAPD_F (int) slap_passwd_check(
        Attribute                       *attr,
        struct berval           *cred );
+LIBSLAPD_F (struct berval *) slap_passwd_generate(
+       struct berval           *cred );
 
 /*
  * kerberos.c
@@ -470,6 +510,7 @@ LIBSLAPD_F (int)            global_lastmod;
 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;
 
index 37faa5181ec71d941b3c11f99f28d5476276b3f8..3c142748d48182421ee4c4fb5f07a05b2e3b4c04 100644 (file)
@@ -241,7 +241,7 @@ send_ldap_response(
     const char *text,
        struct berval   **ref,
        const char      *resoid,
-       struct berval   *resdata,
+       struct berval   *data,
        LDAPControl **ctrls
 )
 {
@@ -281,9 +281,8 @@ send_ldap_response(
                        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 ) {
index 8b296ecc7f79ac2d081d7301edd17e08dfd24a9e..5d688c936dbb0fb9ed022b8e2bc82d28521c7bc5 100644 (file)
@@ -74,7 +74,7 @@ root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
        }
 
        /* 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 );
        }
index 233da67a2d46193bcd2332fc0de9f980d23fc6f9..10e6d67b27601e43d908f32e34f1b7621eaf620d 100644 (file)
@@ -204,6 +204,14 @@ do_search(
                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 );
 
index 5435af855c90b3fdbc51861af07362749b6a3d3f..b9f7ea5de439fd6ab6a206b9029a3dbf08c682a8 100644 (file)
@@ -66,6 +66,9 @@ LDAP_BEGIN_DECL
 
 #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) == '+')
@@ -482,9 +485,13 @@ struct slap_backend_db {
 #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
 
@@ -524,6 +531,15 @@ struct slap_backend_db {
        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 */
 
@@ -615,6 +631,9 @@ struct slap_backend_info {
                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));
 
@@ -642,6 +661,8 @@ struct slap_backend_info {
 #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 */
 };
@@ -662,9 +683,19 @@ typedef struct slap_op {
        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       */
@@ -709,19 +740,35 @@ typedef struct slap_conn {
        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 */
index 00473ec40414afe843bcd08c84c9d22ffbc820e3..49baf569b98e2b79164c1b1f2c3c9619e75ec1bd 100644 (file)
@@ -53,7 +53,9 @@ SLAPD_OBJS = ../config.o ../ch_malloc.o ../backend.o ../charray.o \
                ../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