From 8c5868b5007d8ff735c31f6b798bd39f836aef97 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Wed, 2 Sep 1998 21:31:35 +0000 Subject: [PATCH] Add basic support for MD5 and SHA1 passwords. SHA1 support is contributed by Daniel J. Gregor MD5 support is contributed by me Uses public domain MD5 routines Uses ISC/IBM freely redistributable Base64 routines SHA1 support requires external SHA1 routines --- Make-common.dist | 5 +- include/lutil.h | 12 ++ include/lutil_md5.h | 30 +++ libraries/liblutil/Make-template | 62 ++++++ libraries/liblutil/Version.c | 9 + libraries/liblutil/base64.c | 314 +++++++++++++++++++++++++++++ libraries/liblutil/md5.c | 320 ++++++++++++++++++++++++++++++ servers/slapd/Make-template | 2 +- servers/slapd/back-ldbm/bind.c | 62 +++++- servers/slapd/tools/Make-template | 4 +- servers/slurpd/replica.c | 3 + tests/Make-template | 2 +- 12 files changed, 816 insertions(+), 9 deletions(-) create mode 100644 include/lutil.h create mode 100644 include/lutil_md5.h create mode 100644 libraries/liblutil/Make-template create mode 100644 libraries/liblutil/Version.c create mode 100644 libraries/liblutil/base64.c create mode 100644 libraries/liblutil/md5.c diff --git a/Make-common.dist b/Make-common.dist index 127ec9af81..dec90d498a 100644 --- a/Make-common.dist +++ b/Make-common.dist @@ -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 index 0000000000..654450c667 --- /dev/null +++ b/include/lutil.h @@ -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 index 0000000000..71aad8f35a --- /dev/null +++ b/include/lutil_md5.h @@ -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 index 0000000000..c1ee9a263e --- /dev/null +++ b/libraries/liblutil/Make-template @@ -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 index 0000000000..245730fe8d --- /dev/null +++ b/libraries/liblutil/Version.c @@ -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 index 0000000000..01ead24322 --- /dev/null +++ b/libraries/liblutil/base64.c @@ -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 +#include +#include +#include + +#include + +#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 index 0000000000..838ed54ff6 --- /dev/null +++ b/libraries/liblutil/md5.c @@ -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 + 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 + +#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<>(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 + +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 */ diff --git a/servers/slapd/Make-template b/servers/slapd/Make-template index 01ef5cc0e0..9fab1e99bd 100644 --- a/servers/slapd/Make-template +++ b/servers/slapd/Make-template @@ -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) diff --git a/servers/slapd/back-ldbm/bind.c b/servers/slapd/back-ldbm/bind.c index a4cbcd397f..3ab224136a 100644 --- a/servers/slapd/back-ldbm/bind.c +++ b/servers/slapd/back-ldbm/bind.c @@ -19,6 +19,15 @@ extern char *crypt (char *key, char *salt); #endif #endif /* LDAP_CRYPT */ +#ifdef LDAP_SHA1 +#include +#endif /* LDAP_SHA1 */ +#ifdef LDAP_MD5 +#include +#endif /* LDAP_MD5 */ + +#include + 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 ); diff --git a/servers/slapd/tools/Make-template b/servers/slapd/tools/Make-template index b5c3c17d3e..7464e9aa21 100644 --- a/servers/slapd/tools/Make-template +++ b/servers/slapd/tools/Make-template @@ -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 \ diff --git a/servers/slurpd/replica.c b/servers/slurpd/replica.c index 596d14d383..faeddeaa3f 100644 --- a/servers/slurpd/replica.c +++ b/servers/slurpd/replica.c @@ -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 diff --git a/tests/Make-template b/tests/Make-template index 7e6be68593..46675972d7 100644 --- a/tests/Make-template +++ b/tests/Make-template @@ -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 -- 2.39.5