httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Life is hard, and then you die." <ron...@innovation.ch>
Subject Re: Updated mod_digest (fwd)
Date Thu, 08 Jul 1999 06:31:48 GMT

  Hi all,

sorry for the way slow reply on this - things are a little busy at
work (anybody looking for a job? It's all Java...)

> IE5 does support digest.  However, last I checked, the
> digest module wasnt compliant with the final digest spec.
> If memory serves, apache didnt support the client nonce, which
> IE insists upon since it increases security.
> 
> Does anyone know the status of the module ?

The new mod_digest works fine with IE5 (though IE5 has at least one
bug...). Anybody wishing to try it out can go to
http://www.innovation.ch:8000/digest_auth/ - the username is "digest"
and the password is "test" (w/o the quotes).

> Nothing has changed in the code since October 3rd (except the license
> date update), so his patch should still apply cleanly.  Can someone
> eyeball it and let me know if it's worth committing?
> 
> Also, Ronald, have you worked on it more recently than 20 Nov 1998?

As Ralf noticed, I had sent a version begining of January. Since
then I've fixed a small bug in the case where a "Satisfy any" is
configured.

> And what's the impact on src/support/htdigest?

Zero. The format and contents of the .htpasswd file have not changed.

It would be nice to get the new mod_digest in the next release, but Ken
will have to decide that or course. In order to make things a little
easier I'm posting two sets of patches/additions. The first one adds
src/ap/ap_sha1.c and src/include/ap_sha1.h to provide a SHA-1
implementation. The second one is the new mod_digest (posted in the next
mail). I'll commit the stuff if there are enough votes.

I'm going to try and integrate Ralf's MM library into mod_digest this
weekend (should be straightforward from what I've seen) so that
nonce-count checking, sessions management, and one-time nonces are
supported. However, since I guess folks are not ready to include the
MM package in Apache yet I'm not figuring on those changes going in.


  Cheers,

  Ronald

----- src/ap/ap_sha1.c -------------------------------------------------
/*
 * This is work is derived from the public domain SHA-1 by
 * Steve Reid <sreid@sea-to-sky.net>. The original code is available
 * from http://sea-to-sky.net/~sreid/sha1.c
 */
/* ====================================================================
 * Copyright (c) 1996-1999 The Apache Group.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * 4. The names "Apache Server" and "Apache Group" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Group and was originally based
 * on public domain software written at the National Center for
 * Supercomputing Applications, University of Illinois, Urbana-Champaign.
 * For more information on the Apache Group and the Apache HTTP server
 * project, please see <http://www.apache.org/>.
 *
 */


#include "ap_config.h"
#include "ap_sha1.h"
#ifdef CHARSET_EBCDIC
#include "ebcdic.h"
#endif /*CHARSET_EBCDIC*/


static void SHA1Transform(UINT4 state[5], const unsigned char buffer[64]);
static void Encode(unsigned char *output, const UINT4 *input,
		   unsigned int len);
static void Decode(UINT4 *output, const unsigned char *input,
		   unsigned int len);

static unsigned char PADDING[64] =
{
    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};


#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))

#define blk(i)	(block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
		^block[(i+2)&15]^block[i&15],1))

/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+block[i]+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);


/* Hash a single 512-bit block. This is the core of the algorithm. */

static void SHA1Transform(UINT4 state[5], const unsigned char buffer[64])
{
    UINT4 a, b, c, d, e;
    UINT4 block[16];

    Decode(block, buffer, 64);

    /* Copy context->state[] to working vars */
    a = state[0];
    b = state[1];
    c = state[2];
    d = state[3];
    e = state[4];

    /* 4 rounds of 20 operations each. Loop unrolled. */
    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);

    /* Add the working vars back into context.state[] */
    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;
    state[4] += e;

    /* Wipe variables */
    a = b = c = d = e = 0;
    memset(block, 0, sizeof(block));
}


/* SHA1Init - Initialize new context */

API_EXPORT(void) ap_SHA1Init(AP_SHA1_CTX *context)
{
    /* SHA1 initialization constants */
    context->state[0] = 0x67452301;
    context->state[1] = 0xEFCDAB89;
    context->state[2] = 0x98BADCFE;
    context->state[3] = 0x10325476;
    context->state[4] = 0xC3D2E1F0;
    context->count[0] = context->count[1] = 0;
}


/*
 * This does an update w/o any conversion of the input data.
 */
API_EXPORT(void) ap_SHA1Update_binary(AP_SHA1_CTX *context,
				      const unsigned char *input,
				      unsigned int len)
{
    unsigned int i, j;

    j = (context->count[0] >> 3) & 63;
    if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
    context->count[1] += (len >> 29);
    if ((j + len) > 63) {
        memcpy(&context->buffer[j], input, (i = 64-j));
        SHA1Transform(context->state, context->buffer);
        for ( ; i + 63 < len; i += 64) {
            SHA1Transform(context->state, &input[i]);
        }
        j = 0;
    }
    else i = 0;
    memcpy(&context->buffer[j], &input[i], len - i);
}

/*
 * On ascii systems this is identical to ap_SHA1Update_binary; on ebcdic
 * systems this first converts the input string to ascii before updating.
 */
API_EXPORT(void) ap_SHA1Update(AP_SHA1_CTX *context, const char *input,
			       unsigned int len)
{
#ifdef CHARSET_EBCDIC
    unsigned int i, j;
    const unsigned char *uinp = (const unsigned char *) input;

    j = (context->count[0] >> 3) & 63;
    if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
    context->count[1] += (len >> 29);
    if ((j + len) > 63) {
        ebcdic2ascii_strictly(&context->buffer[j], uinp, (i = 64-j));
        SHA1Transform(context->state, context->buffer);
        for ( ; i + 63 < len; i += 64) {
	    char inp_tmp[64];
	    ebcdic2ascii_strictly(inp_tmp, &uinp[i], 64);
            SHA1Transform(context->state, inp_tmp);
        }
        j = 0;
    }
    else i = 0;
    ebcdic2ascii_strictly(&context->buffer[j], &uinp[i], len - i);
#else
    ap_SHA1Update_binary(context, (const unsigned char *) input, len);
#endif
}


/* Add padding and return the message digest. */

API_EXPORT(void) ap_SHA1Final(unsigned char digest[20], AP_SHA1_CTX *context)
{
    unsigned int idx, padLen;
    unsigned char finalcount[8];

    Encode(finalcount, &context->count[1], 4);
    Encode(finalcount+4, &context->count[0], 4);

    idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
    padLen = (idx < 56) ? (56 - idx) : (120 - idx);
    ap_SHA1Update_binary(context, PADDING, padLen);

    ap_SHA1Update_binary(context, finalcount, 8);

    Encode(digest, context->state, 20);

    /* Wipe variables */
    memset(context, 0, sizeof(*context));
    memset(finalcount, 0, sizeof(finalcount));
}


/* Encodes input (UINT4) into output (unsigned char). Assumes len is
   a multiple of 4.
 */
static void Encode(unsigned char *output, const UINT4 *input, unsigned int len)
{
    unsigned int i, j;
    UINT4 k;

    for (i = 0, j = 0; j < len; i++, j += 4) {
	k = input[i];
	output[j]     = (unsigned char) ((k >> 24) & 0xff);
	output[j + 1] = (unsigned char) ((k >> 16) & 0xff);
	output[j + 2] = (unsigned char) ((k >> 8) & 0xff);
	output[j + 3] = (unsigned char) (k & 0xff);
    }
}

/* Decodes input (unsigned char) into output (UINT4). Assumes len is
   a multiple of 4.
 */
static void Decode(UINT4 *output, const unsigned char *input, unsigned int len)
{
    unsigned int i, j;

    for (i = 0, j = 0; j < len; i++, j += 4)
	output[i] = ((UINT4) input[j + 3]) | (((UINT4) input[j + 2]) << 8) |
	    (((UINT4) input[j + 1]) << 16) | (((UINT4) input[j]) << 24);
}


/*************************************************************/
#ifdef	SHA1_TEST_SUITE

int main(int argc, char **argv)
{
    int idx, idx2, sts = 0;
    AP_SHA1_CTX context;
    unsigned char digest[20];
    unsigned char tests[][2][101] = { /* Test Vectors (from FIPS PUB 180-1) */
	{ "abc",
	    { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
	      0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }
        },
	{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
	    { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
	      0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }
        },
	{ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
/* A million repetitions of "a" */
	    { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
	      0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F }
        }
    };

    for (idx=0; idx<3; idx++) {
	ap_SHA1Init(&context);
	if (idx < 2)
	    ap_SHA1Update(&context, tests[idx][0], strlen(tests[idx][0]));
	else {
	    for (idx2=0; idx2<10000; idx2++)
		ap_SHA1Update(&context, tests[idx][0], strlen(tests[idx][0]));
	}
	ap_SHA1Final(digest, &context);
	if (memcmp(digest, tests[idx][1], sizeof(digest))) {
	    fprintf(stderr, "test %d failed\n", idx);
	    fprintf(stderr, "Expected: ");
	    for (idx2=0; idx2<sizeof(digest); idx2++)
		fprintf(stderr, "%.2X ", tests[idx][1][idx2]);
	    fprintf(stderr, "\nbut got:  ");
	    for (idx2=0; idx2<sizeof(digest); idx2++)
		fprintf(stderr, "%.2X ", digest[idx2]);
	    fprintf(stderr, "\n");
	    sts = EXIT_FAILURE;
	}
    }

    if (sts == 0)
	fprintf(stderr, "All tests passed\n");

    return sts;
}
#endif	/* SHA1_TEST_SUITE */

----- src/include/ap_sha1.h --------------------------------------------
/*
 * This is work is derived from the public domain SHA-1 by
 * Steve Reid <sreid@sea-to-sky.net>. The original code is available
 * from http://sea-to-sky.net/~sreid/sha1.c
 */
/* ====================================================================
 * Copyright (c) 1996-1999 The Apache Group.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * 4. The names "Apache Server" and "Apache Group" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the Apache Group
 *    for use in the Apache HTTP server project (http://www.apache.org/)."
 *
 * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Group and was originally based
 * on public domain software written at the National Center for
 * Supercomputing Applications, University of Illinois, Urbana-Champaign.
 * For more information on the Apache Group and the Apache HTTP server
 * project, please see <http://www.apache.org/>.
 *
 */

#ifndef APACHE_SHA1_H
#define APACHE_SHA1_H

#ifdef __cplusplus
extern "C" {
#endif

/* SHA1.H - header file for SHA1.C */

/* UINT4: a four-byte unsigned word */
#ifndef	HAVE_UINT4_TYPEDEF
typedef unsigned int UINT4;
#define	HAVE_UINT4_TYPEDEF
#endif

typedef struct {
    UINT4 state[5];
    UINT4 count[2];
    unsigned char buffer[64];
} AP_SHA1_CTX;

API_EXPORT(void) ap_SHA1Init(AP_SHA1_CTX *context);
API_EXPORT(void) ap_SHA1Update(AP_SHA1_CTX *context, const char *input,
			       unsigned int inputLen);
API_EXPORT(void) ap_SHA1Update_binary(AP_SHA1_CTX *context,
				      const unsigned char *input,
				      unsigned int inputLen);
API_EXPORT(void) ap_SHA1Final(unsigned char digest[20], AP_SHA1_CTX *context);

#ifdef __cplusplus
}
#endif

#endif  /* !APACHE_SHA1_H */
----- diffs ------------------------------------------------------------
===================================================================
RCS file: /home/cvs/apache-1.3/src/ap/Makefile.tmpl,v
retrieving revision 1.32
diff -u -r1.32 Makefile.tmpl
--- Makefile.tmpl	1999/05/31 17:09:30	1.32
+++ Makefile.tmpl	1999/07/08 06:24:47
@@ -5,8 +5,8 @@
 
 LIB=libap.a
 
-OBJS=ap_cpystrn.o ap_execve.o ap_fnmatch.o ap_getpass.o ap_md5c.o ap_signal.o \
-     ap_slack.o ap_snprintf.o
+OBJS=ap_cpystrn.o ap_execve.o ap_fnmatch.o ap_getpass.o ap_md5c.o ap_sha1.o \
+     ap_signal.o ap_slack.o ap_snprintf.o
 
 .c.o:
 	$(CC) -c $(INCLUDES) $(CFLAGS) $<
@@ -59,6 +59,8 @@
  $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(OSDIR)/os-inline.c \
  $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h $(INCDIR)/ap_md5.h \
  $(INCDIR)/ap.h
+ap_sha1.o: ap_sha1.c $(INCDIR)/ap_config.h $(INCDIR)/ap_sha1.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h $(OSDIR)/os-inline.c
 ap_signal.o: ap_signal.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
  $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
  $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
? ap_sha1.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/ap_md5.h,v
retrieving revision 1.5
diff -u -r1.5 ap_md5.h
--- ap_md5.h	1999/04/08 20:56:39	1.5
+++ ap_md5.h	1999/07/08 06:25:08
@@ -95,7 +95,10 @@
 /* MD5.H - header file for MD5C.C */
 
 /* UINT4 defines a four byte word */
+#ifndef HAVE_UINT4_TYPEDEF
 typedef unsigned int UINT4;
+#define HAVE_UINT4_TYPEDEF
+#endif
 
 /* MD5 context. */
 typedef struct {
------------------------------------------------------------------------


Mime
View raw message