]> git.sur5r.net Git - openldap/commitdiff
Add basic support for MD5 and SHA1 passwords.
authorKurt Zeilenga <kurt@openldap.org>
Wed, 2 Sep 1998 21:31:35 +0000 (21:31 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Wed, 2 Sep 1998 21:31:35 +0000 (21:31 +0000)
SHA1 support is contributed by Daniel J. Gregor <dj@gregor.com>
MD5 support is contributed by me <kurt@OpenLDAP.org>
Uses public domain MD5 routines
Uses ISC/IBM freely redistributable Base64 routines
SHA1 support requires external SHA1 routines

12 files changed:
Make-common.dist
include/lutil.h [new file with mode: 0644]
include/lutil_md5.h [new file with mode: 0644]
libraries/liblutil/Make-template [new file with mode: 0644]
libraries/liblutil/Version.c [new file with mode: 0644]
libraries/liblutil/base64.c [new file with mode: 0644]
libraries/liblutil/md5.c [new file with mode: 0644]
servers/slapd/Make-template
servers/slapd/back-ldbm/bind.c
servers/slapd/tools/Make-template
servers/slurpd/replica.c
tests/Make-template

index 127ec9af8194aaefc3db09039ecdba27a1065668..dec90d498af9cb6a7cf8357cd05c29ab7c07b2a1 100644 (file)
@@ -253,8 +253,9 @@ LDAP_REFERRALS=-DLDAP_REFERRALS
 # uncomment this line to enable ACL by groups
 # LDAP_ACLGROUP=-DACLGROUP
 
-# uncomment these lines to enable support for CRYPT passwords in LDBM.
-# LDAP_CRYPT=-DLDAP_CRYPT
+# uncomment these lines to enable support for CRYPT, SHA1, and/or MD5 passwords
+# in LDBM.  Crypt uses platform provided crypt(3).
+# LDAP_CRYPT=-DLDAP_CRYPT -DLDAP_SHA1 -DLDAP_MD5
 # LDAP_CRYPT_LIB?=
 # and comment this line out
 LDAP_CRYPT_LIB=
diff --git a/include/lutil.h b/include/lutil.h
new file mode 100644 (file)
index 0000000..654450c
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _LUTIL_H
+#define _LUTIL_H 1
+
+/*
+ * Include file for LDAP utility routine
+ */
+
+/* ISC Base64 Routines */
+extern int b64_ntop(u_char const *, size_t, char *, size_t);
+extern int b64_pton(char const *, u_char *, size_t);
+
+#endif /* _LUTIL_H */
diff --git a/include/lutil_md5.h b/include/lutil_md5.h
new file mode 100644 (file)
index 0000000..71aad8f
--- /dev/null
@@ -0,0 +1,30 @@
+/* See md5.c for explanation and copyright information.  */
+
+#ifndef LDAP_MD5_H
+#define LDAP_MD5_H
+
+/* Unlike previous versions of this code, uint32 need not be exactly
+   32 bits, merely 32 bits or more.  Choosing a data type which is 32
+   bits instead of 64 is not important; speed is considerably more
+   important.  ANSI guarantees that "unsigned long" will be big enough,
+   and always using it seems to have few disadvantages.  */
+
+typedef unsigned long uint32;
+
+struct MD5Context {
+       uint32 buf[4];
+       uint32 bits[2];
+       unsigned char in[64];
+};
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+void MD5Transform(uint32 buf[4], const unsigned char in[64]);
+
+/*
+ * This is needed to make RSAREF happy on some MS-DOS compilers.
+ */
+typedef struct MD5Context MD5_CTX;
+
+#endif /* !LDAP_MD5_H */
diff --git a/libraries/liblutil/Make-template b/libraries/liblutil/Make-template
new file mode 100644 (file)
index 0000000..c1ee9a2
--- /dev/null
@@ -0,0 +1,62 @@
+#-----------------------------------------------------------------------------
+# Copyright (c) 1995 Regents of the University of Michigan.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted
+# provided that this notice is preserved and that due credit is given
+# to the University of Michigan at Ann Arbor. The name of the University
+# may not be used to endorse or promote products derived from this
+# software without specific prior written permission. This software
+# is provided ``as is'' without express or implied warranty.
+#
+#       lutil library makefile
+#
+#-----------------------------------------------------------------------------
+
+LDAPSRC        = ../..
+
+SRCS   = base64.c md5.c
+OBJS   = base64.o md5.o
+
+HDIR   = ../../include
+
+INCLUDES= -I$(HDIR)
+DEFINES        = $(DEFS)
+
+CFLAGS = $(INCLUDES) $(DEFINES) $(ACFLAGS)
+
+all:   liblutil.a
+
+liblutil.a:    version.o
+       $(AR) ruv $@ $(OBJS) version.o
+       @if [ ! -z "$(RANLIB)" ]; then \
+               $(RANLIB) $@; \
+       fi; \
+       $(RM) ../$@; \
+       $(LN) liblutil/$@ ../$@
+
+version.c:     $(OBJS)
+       $(RM) $@
+       (u=$${USER-root} v=`$(CAT) ../../build/version` d=`$(PWD)` \
+       h=`$(HOSTNAME)` t=`$(DATE)`; $(SED) -e "s|%WHEN%|$${t}|" \
+       -e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \
+       -e "s|%VERSION%|$${v}|" \
+       < Version.c > $@)
+
+install:       all
+
+lint:  FORCE
+       $(LINT) $(INCLUDES) $(DEFINES) $(SRCS)
+
+5lint: FORCE
+       $(5LINT) $(INCLUDES) $(DEFINES) $(SRCS)
+
+clean: FORCE
+       $(RM) liblutil.a ../liblutil.a *.o core a.out version.c
+
+depend:        FORCE
+       $(MKDEP) $(INCLUDES) $(DEFINES) $(SRCS)
+
+links:
+       @$(LN) .src/*.[ch] .
+
diff --git a/libraries/liblutil/Version.c b/libraries/liblutil/Version.c
new file mode 100644 (file)
index 0000000..245730f
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * Copyright 1998 The LDAP Foundation
+ * All rights reserved.
+ *
+ * This software may be used and distributed as provided under the
+ * terms of the OpenLDAP Public License.
+ */
+
+static char Version[] = "  liblutil.a v%VERSION% (%WHEN%)\n\t%WHOANDWHERE%\n";
diff --git a/libraries/liblutil/base64.c b/libraries/liblutil/base64.c
new file mode 100644 (file)
index 0000000..01ead24
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Modified by Kurt D. Zeilenga for inclusion into OpenLDAP
+ */
+
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <lutil.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+   The following encoding technique is taken from RFC 1521 by Borenstein
+   and Freed.  It is reproduced here in a slightly edited form for
+   convenience.
+
+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
+   represented per printable character. (The extra 65th character, "=",
+   is used to signify a special processing function.)
+
+   The encoding process represents 24-bit groups of input bits as output
+   strings of 4 encoded characters. Proceeding from left to right, a
+   24-bit input group is formed by concatenating 3 8-bit input groups.
+   These 24 bits are then treated as 4 concatenated 6-bit groups, each
+   of which is translated into a single digit in the base64 alphabet.
+
+   Each 6-bit group is used as an index into an array of 64 printable
+   characters. The character referenced by the index is placed in the
+   output string.
+
+                         Table 1: The Base64 Alphabet
+
+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
+          0 A            17 R            34 i            51 z
+          1 B            18 S            35 j            52 0
+          2 C            19 T            36 k            53 1
+          3 D            20 U            37 l            54 2
+          4 E            21 V            38 m            55 3
+          5 F            22 W            39 n            56 4
+          6 G            23 X            40 o            57 5
+          7 H            24 Y            41 p            58 6
+          8 I            25 Z            42 q            59 7
+          9 J            26 a            43 r            60 8
+         10 K            27 b            44 s            61 9
+         11 L            28 c            45 t            62 +
+         12 M            29 d            46 u            63 /
+         13 N            30 e            47 v
+         14 O            31 f            48 w         (pad) =
+         15 P            32 g            49 x
+         16 Q            33 h            50 y
+
+   Special processing is performed if fewer than 24 bits are available
+   at the end of the data being encoded.  A full encoding quantum is
+   always completed at the end of a quantity.  When fewer than 24 input
+   bits are available in an input group, zero bits are added (on the
+   right) to form an integral number of 6-bit groups.  Padding at the
+   end of the data is performed using the '=' character.
+
+   Since all base64 input is an integral number of octets, only the
+         -------------------------------------------------                       
+   following cases can arise:
+   
+       (1) the final quantum of encoding input is an integral
+           multiple of 24 bits; here, the final unit of encoded
+          output will be an integral multiple of 4 characters
+          with no "=" padding,
+       (2) the final quantum of encoding input is exactly 8 bits;
+           here, the final unit of encoded output will be two
+          characters followed by two "=" padding characters, or
+       (3) the final quantum of encoding input is exactly 16 bits;
+           here, the final unit of encoded output will be three
+          characters followed by one "=" padding character.
+   */
+
+int
+b64_ntop(
+       u_char const *src,
+       size_t srclength,
+       char *target,
+       size_t targsize)
+{
+       size_t datalength = 0;
+       u_char input[3];
+       u_char output[4];
+       size_t i;
+
+       while (2 < srclength) {
+               input[0] = *src++;
+               input[1] = *src++;
+               input[2] = *src++;
+               srclength -= 3;
+
+               output[0] = input[0] >> 2;
+               output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+               output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+               output[3] = input[2] & 0x3f;
+               Assert(output[0] < 64);
+               Assert(output[1] < 64);
+               Assert(output[2] < 64);
+               Assert(output[3] < 64);
+
+               if (datalength + 4 > targsize)
+                       return (-1);
+               target[datalength++] = Base64[output[0]];
+               target[datalength++] = Base64[output[1]];
+               target[datalength++] = Base64[output[2]];
+               target[datalength++] = Base64[output[3]];
+       }
+    
+       /* Now we worry about padding. */
+       if (0 != srclength) {
+               /* Get what's left. */
+               input[0] = input[1] = input[2] = '\0';
+               for (i = 0; i < srclength; i++)
+                       input[i] = *src++;
+       
+               output[0] = input[0] >> 2;
+               output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+               output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+               Assert(output[0] < 64);
+               Assert(output[1] < 64);
+               Assert(output[2] < 64);
+
+               if (datalength + 4 > targsize)
+                       return (-1);
+               target[datalength++] = Base64[output[0]];
+               target[datalength++] = Base64[output[1]];
+               if (srclength == 1)
+                       target[datalength++] = Pad64;
+               else
+                       target[datalength++] = Base64[output[2]];
+               target[datalength++] = Pad64;
+       }
+       if (datalength >= targsize)
+               return (-1);
+       target[datalength] = '\0';      /* Returned value doesn't count \0. */
+       return (datalength);
+}
+
+/* skips all whitespace anywhere.
+   converts characters, four at a time, starting at (or after)
+   src from base - 64 numbers into three 8 bit bytes in the target area.
+   it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(
+       char const *src,
+       u_char *target, 
+       size_t targsize)
+{
+       int tarindex, state, ch;
+       char *pos;
+
+       state = 0;
+       tarindex = 0;
+
+       while ((ch = *src++) != '\0') {
+               if (isspace(ch))        /* Skip whitespace anywhere. */
+                       continue;
+
+               if (ch == Pad64)
+                       break;
+
+               pos = strchr(Base64, ch);
+               if (pos == 0)           /* A non-base64 character. */
+                       return (-1);
+
+               switch (state) {
+               case 0:
+                       if (target) {
+                               if ((size_t)tarindex >= targsize)
+                                       return (-1);
+                               target[tarindex] = (pos - Base64) << 2;
+                       }
+                       state = 1;
+                       break;
+               case 1:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize)
+                                       return (-1);
+                               target[tarindex]   |=  (pos - Base64) >> 4;
+                               target[tarindex+1]  = ((pos - Base64) & 0x0f)
+                                                       << 4 ;
+                       }
+                       tarindex++;
+                       state = 2;
+                       break;
+               case 2:
+                       if (target) {
+                               if ((size_t)tarindex + 1 >= targsize)
+                                       return (-1);
+                               target[tarindex]   |=  (pos - Base64) >> 2;
+                               target[tarindex+1]  = ((pos - Base64) & 0x03)
+                                                       << 6;
+                       }
+                       tarindex++;
+                       state = 3;
+                       break;
+               case 3:
+                       if (target) {
+                               if ((size_t)tarindex >= targsize)
+                                       return (-1);
+                               target[tarindex] |= (pos - Base64);
+                       }
+                       tarindex++;
+                       state = 0;
+                       break;
+               default:
+                       abort();
+               }
+       }
+
+       /*
+        * We are done decoding Base-64 chars.  Let's see if we ended
+        * on a byte boundary, and/or with erroneous trailing characters.
+        */
+
+       if (ch == Pad64) {              /* We got a pad char. */
+               ch = *src++;            /* Skip it, get next. */
+               switch (state) {
+               case 0:         /* Invalid = in first position */
+               case 1:         /* Invalid = in second position */
+                       return (-1);
+
+               case 2:         /* Valid, means one byte of info */
+                       /* Skip any number of spaces. */
+                       for ((void)NULL; ch != '\0'; ch = *src++)
+                               if (!isspace(ch))
+                                       break;
+                       /* Make sure there is another trailing = sign. */
+                       if (ch != Pad64)
+                               return (-1);
+                       ch = *src++;            /* Skip the = */
+                       /* Fall through to "single trailing =" case. */
+                       /* FALLTHROUGH */
+
+               case 3:         /* Valid, means two bytes of info */
+                       /*
+                        * We know this char is an =.  Is there anything but
+                        * whitespace after it?
+                        */
+                       for ((void)NULL; ch != '\0'; ch = *src++)
+                               if (!isspace(ch))
+                                       return (-1);
+
+                       /*
+                        * Now make sure for cases 2 and 3 that the "extra"
+                        * bits that slopped past the last full byte were
+                        * zeros.  If we don't check them, they become a
+                        * subliminal channel.
+                        */
+                       if (target && target[tarindex] != 0)
+                               return (-1);
+               }
+       } else {
+               /*
+                * We ended by seeing the end of the string.  Make sure we
+                * have no partial bytes lying around.
+                */
+               if (state != 0)
+                       return (-1);
+       }
+
+       return (tarindex);
+}
diff --git a/libraries/liblutil/md5.c b/libraries/liblutil/md5.c
new file mode 100644 (file)
index 0000000..838ed54
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Modified by Kurt D. Zeilenga for inclusion into OpenLDAP
+ * I hereby disclaim copyright in any changes I have made; this
+ * code remains in the public domain.
+ */
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
+   not require an integer type which is exactly 32 bits.  This work
+   draws on the changes for the same purpose by Tatu Ylonen
+   <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
+   that code, there is no copyright issue.  I hereby disclaim
+   copyright in any changes I have made; this code remains in the
+   public domain.  */
+
+#include <string.h>
+
+#include "lutil_md5.h"
+
+/* Little-endian byte-swapping routines.  Note that these do not
+   depend on the size of datatypes such as uint32, nor do they require
+   us to detect the endianness of the machine we are running on.  It
+   is possible they should be macros for speed, but I would be
+   surprised if they were a performance bottleneck for MD5.  */
+
+static uint32
+getu32 (addr)
+     const unsigned char *addr;
+{
+       return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
+               | addr[1]) << 8 | addr[0];
+}
+
+static void
+putu32 (data, addr)
+     uint32 data;
+     unsigned char *addr;
+{
+       addr[0] = (unsigned char)data;
+       addr[1] = (unsigned char)(data >> 8);
+       addr[2] = (unsigned char)(data >> 16);
+       addr[3] = (unsigned char)(data >> 24);
+}
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init(ctx)
+     struct MD5Context *ctx;
+{
+       ctx->buf[0] = 0x67452301;
+       ctx->buf[1] = 0xefcdab89;
+       ctx->buf[2] = 0x98badcfe;
+       ctx->buf[3] = 0x10325476;
+
+       ctx->bits[0] = 0;
+       ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update(ctx, buf, len)
+     struct MD5Context *ctx;
+     unsigned char const *buf;
+     unsigned len;
+{
+       uint32 t;
+
+       /* Update bitcount */
+
+       t = ctx->bits[0];
+       if ((ctx->bits[0] = (t + ((uint32)len << 3)) & 0xffffffff) < t)
+               ctx->bits[1]++; /* Carry from low to high */
+       ctx->bits[1] += len >> 29;
+
+       t = (t >> 3) & 0x3f;    /* Bytes already in shsInfo->data */
+
+       /* Handle any leading odd-sized chunks */
+
+       if ( t ) {
+               unsigned char *p = ctx->in + t;
+
+               t = 64-t;
+               if (len < t) {
+                       memcpy(p, buf, len);
+                       return;
+               }
+               memcpy(p, buf, t);
+               MD5Transform(ctx->buf, ctx->in);
+               buf += t;
+               len -= t;
+       }
+
+       /* Process data in 64-byte chunks */
+
+       while (len >= 64) {
+               memcpy(ctx->in, buf, 64);
+               MD5Transform(ctx->buf, ctx->in);
+               buf += 64;
+               len -= 64;
+       }
+
+       /* Handle any remaining bytes of data. */
+
+       memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final(digest, ctx)
+     unsigned char digest[16];
+     struct MD5Context *ctx;
+{
+       unsigned count;
+       unsigned char *p;
+
+       /* Compute number of bytes mod 64 */
+       count = (ctx->bits[0] >> 3) & 0x3F;
+
+       /* Set the first char of padding to 0x80.  This is safe since there is
+          always at least one byte free */
+       p = ctx->in + count;
+       *p++ = 0x80;
+
+       /* Bytes of padding needed to make 64 bytes */
+       count = 64 - 1 - count;
+
+       /* Pad out to 56 mod 64 */
+       if (count < 8) {
+               /* Two lots of padding:  Pad the first block to 64 bytes */
+               memset(p, 0, count);
+               MD5Transform(ctx->buf, ctx->in);
+
+               /* Now fill the next block with 56 bytes */
+               memset(ctx->in, 0, 56);
+       } else {
+               /* Pad block to 56 bytes */
+               memset(p, 0, count-8);
+       }
+
+       /* Append length in bits and transform */
+       putu32(ctx->bits[0], ctx->in + 56);
+       putu32(ctx->bits[1], ctx->in + 60);
+
+       MD5Transform(ctx->buf, ctx->in);
+       putu32(ctx->buf[0], digest);
+       putu32(ctx->buf[1], digest + 4);
+       putu32(ctx->buf[2], digest + 8);
+       putu32(ctx->buf[3], digest + 12);
+       memset(ctx, 0, sizeof(ctx));    /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+       ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+MD5Transform(buf, inraw)
+     uint32 buf[4];
+     const unsigned char inraw[64];
+{
+       register uint32 a, b, c, d;
+       uint32 in[16];
+       int i;
+
+       for (i = 0; i < 16; ++i)
+               in[i] = getu32 (inraw + 4 * i);
+
+       a = buf[0];
+       b = buf[1];
+       c = buf[2];
+       d = buf[3];
+
+       MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
+       MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
+       MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
+       MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
+       MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
+       MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
+       MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
+       MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
+       MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
+       MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
+       MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
+       MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
+       MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
+       MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
+       MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
+       MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+
+       MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
+       MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
+       MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
+       MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
+       MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
+       MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
+       MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
+       MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
+       MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
+       MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
+       MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
+       MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
+       MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
+       MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
+       MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
+       MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+
+       MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
+       MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
+       MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
+       MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
+       MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
+       MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
+       MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
+       MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
+       MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
+       MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
+       MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
+       MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
+       MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
+       MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
+       MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
+       MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+
+       MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
+       MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
+       MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
+       MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
+       MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
+       MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
+       MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
+       MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
+       MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
+       MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
+       MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
+       MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
+       MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
+       MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
+       MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
+       MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+
+       buf[0] += a;
+       buf[1] += b;
+       buf[2] += c;
+       buf[3] += d;
+}
+#endif
+
+#ifdef TEST
+/* Simple test program.  Can use it to manually run the tests from
+   RFC1321 for example.  */
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+       struct MD5Context context;
+       unsigned char checksum[16];
+       int i;
+       int j;
+
+       if (argc < 2)
+       {
+               fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
+               exit (1);
+       }
+       for (j = 1; j < argc; ++j)
+       {
+               printf ("MD5 (\"%s\") = ", argv[j]);
+               MD5Init (&context);
+               MD5Update (&context, argv[j], strlen (argv[j]));
+               MD5Final (checksum, &context);
+               for (i = 0; i < 16; i++)
+               {
+                       printf ("%02x", (unsigned int) checksum[i]);
+               }
+               printf ("\n");
+       }
+       return 0;
+}
+#endif /* TEST */
index 01ef5cc0e079b0b2ccad4c58690556a466b37bc1..9fab1e99bdcedf335bbcca670b8e167bf9d51538 100644 (file)
@@ -36,7 +36,7 @@ INCLUDES= -I. -I$(HDIR) $(KRBINCLUDEFLAG)
 DEFINES = $(DEFS) $(SERVERDEFS)
 CFLAGS = $(INCLUDES) $(THREADSINCLUDE) $(DEFINES) $(ACFLAGS) $(THREADS)
 LDFLAGS        = -L$(LDIR) $(KRBLIBFLAG)
-LIBS   = $(KRBLIBS) -llber -lldbm -lavl -llthread -lldif \
+LIBS   = $(KRBLIBS) -llber -lldbm -lavl -llthread -lldif -llutil \
                $(REGEXLIB) $(THREADSLIB) \
                $(LDBMLIB) $(LDAP_CRYPT_LIB) $(LDAP_TCP_WRAPPERS_LIB) $(ALIBS)
 
index a4cbcd397fc2d33c44fb155705ed8badd7ee3d15..3ab224136a72688bbdf65504295b32de640cadda 100644 (file)
@@ -19,6 +19,15 @@ extern char *crypt (char *key, char *salt);
 #endif
 #endif /* LDAP_CRYPT */
 
+#ifdef LDAP_SHA1
+#include <sha1.h>
+#endif /* LDAP_SHA1 */
+#ifdef LDAP_MD5
+#include <lutil_md5.h>
+#endif /* LDAP_MD5 */
+
+#include <lutil.h>
+
 extern Entry           *dn2entry();
 extern Attribute       *attr_find();
 
@@ -40,15 +49,62 @@ crypted_value_find(
 {
        int     i;
        for ( i = 0; vals[i] != NULL; i++ ) {
-               if ( syntax != SYNTAX_BIN && 
-                       strncasecmp( "{CRYPT}", vals[i]->bv_val, (sizeof("{CRYPT}") - 1 ) ) == 0 ) {
+               if ( syntax != SYNTAX_BIN && strncasecmp( "{CRYPT}",
+                       vals[i]->bv_val, (sizeof("{CRYPT}") - 1 ) ) == 0 ) {
                                char *userpassword = vals[i]->bv_val + sizeof("{CRYPT}") - 1;
                                pthread_mutex_lock( &crypt_mutex );
-                               if ( ( !strcmp( userpassword, crypt( cred->bv_val, userpassword ) ) != 0 ) ) {
+                               if (strcmp(userpassword, crypt(cred->bv_val,
+                                               userpassword)) == 0) {
                                        pthread_mutex_unlock( &crypt_mutex );
                                        return ( 0 );
                                }
                                pthread_mutex_unlock( &crypt_mutex );
+#ifdef LDAP_MD5
+               } else if ( syntax != SYNTAX_BIN && strncasecmp( "{MD5}",
+                       vals[i]->bv_val, (sizeof("{MD5}") - 1 ) ) == 0 ) {
+                               MD5_CTX MD5context;
+                               unsigned char MD5digest[20];
+                               char base64digest[29];  /* ceiling(sizeof(input)/3) * 4 + 1 */
+
+                               char *userpassword = vals[i]->bv_val + sizeof("{MD5}") - 1;
+
+                               MD5Init(&MD5context);
+                               MD5Update(&MD5context, cred->bv_val, strlen(cred->bv_val));
+                               MD5Final(MD5digest, &MD5context);
+
+                               if (b64_ntop(MD5digest, sizeof(MD5digest),
+                                       base64digest, sizeof(base64digest)) < 0)
+                               {
+                                       return ( 1 );
+                               }
+
+                               if (strcmp(userpassword, base64digest) == 0) {
+                                       return ( 0 );
+                               }
+#endif /* LDAP_MD5 */
+#ifdef LDAP_SHA1
+               } else if ( syntax != SYNTAX_BIN && strncasecmp( "{SHA}",
+                       vals[i]->bv_val, (sizeof("{SHA}") - 1 ) ) == 0 ) {
+                               SHA1_CTX SHA1context;
+                               unsigned char SHA1digest[20];
+                               char base64digest[29];  /* ceiling(sizeof(input)/3) * 4 + 1 */
+
+                               char *userpassword = vals[i]->bv_val + sizeof("{SHA}") - 1;
+
+                               SHA1Init(&SHA1context);
+                               SHA1Update(&SHA1context, cred->bv_val, strlen(cred->bv_val));
+                               SHA1Final(SHA1digest, &SHA1context);
+
+                               if (b64_ntop(SHA1digest, sizeof(SHA1digest),
+                                       base64digest, sizeof(base64digest)) < 0)
+                               {
+                                       return ( 1 );
+                               }
+
+                               if (strcmp(userpassword, base64digest) == 0) {
+                                       return ( 0 );
+                               }
+#endif /* LDAP_SHA1 */
                } else {
                 if ( value_cmp( vals[i], v, syntax, normalize ) == 0 ) {
                         return( 0 );
index b5c3c17d3ebb46cda5a59a1694c97b111c158716..7464e9aa21e2ffb4942188049853be0bb9166f88 100644 (file)
@@ -30,8 +30,8 @@ INCLUDES= -I. -I$(HDIR) $(EXINCLUDES)
 DEFINES = $(DEFS) $(LDAP_CRYPT) $(SERVERDEFS) $(THREADS)
 CFLAGS = $(INCLUDES) $(DEFINES) $(ACFLAGS)
 LDFLAGS        = -L$(LDIR) $(EXLDFLAGS)
-LIBS   = -lldif -lldap -llber -lldbm -lavl $(LDBMLIB) $(EXLIBS) $(ALIBS)
-LIBS2  = -lldif -lldbm -lavl $(LDBMLIB) -llber $(KRBLIBFLAG) $(KRBLIBS) \
+LIBS   = -lldif -lldap -llber -lldbm -llutil -lavl $(LDBMLIB) $(EXLIBS) $(ALIBS)
+LIBS2  = -lldif -lldbm -llutil -lavl $(LDBMLIB) -llber $(KRBLIBFLAG) $(KRBLIBS) \
                -llthread $(THREADSLIB) $(ALIBS) $(LDAP_CRYPT_LIB)
 
 all:   build-edb2ldif ldif2index ldif2ldbm ldbmcat ldif2id2entry \
index 596d14d383e18af4e87f561a58c3a7416c3ea214..faeddeaa3feccfc9204f5fcff6b0de9da5c89da4 100644 (file)
@@ -57,7 +57,10 @@ start_replica_thread(
     pthread_attr_t     attr;
 
     pthread_attr_init( &attr );
+#ifdef NOTDEF
+       /* if main wants to join with us, we shouldn't detach */
     pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
+#endif
 
 #ifndef THREAD_MIT_PTHREADS
     /* POSIX_THREADS or compatible
index 7e6be68593cd990dda13c2e554edc5dcb286322f..46675972d73d11978d378b1972fa053dffad4284 100644 (file)
@@ -26,7 +26,7 @@ install:      FORCE
 depend:        FORCE
 
 clean: FORCE
-       $(RM) test-db/[!C]* test-repl/[!C]*
+       $(RM) test-db/[!C]* test-repl/[!C]* *core
 
 veryclean:     clean