httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jeff Trawick <trawi...@bellsouth.net>
Subject [PATCH] clean up translation support APR MD5 routines
Date Wed, 03 May 2000 02:42:10 GMT
Here are mods to apr_md5.h/apr_md5.c as well as a simple test driver
for APR's md5 support.  The test driver allows the digest to be
computed in conjunction with the translation support in ap_MD5xx().
The driver will complain if some code breaks and the proper digest is
not computed (the stored digest was calculated by apr_md5.c before I
modified it).

Old:

  ap_MD5Update() always called ebcdic2ascii() when CHARSET_EBCDIC was
  defined.

  This forced the caller to compensate when no translation was desired
  (e.g., MD5 of a .gif).

  The translation support was not customizable.

  The translation support was only available on an EBCDIC machine.

New:

  Translation is only done when desired; the client calls the new
  ap_MD5SetXlate() function to store an APR translation handle.  

  Any SBCS conversion supported by APR can be used.  The interface
  does not need to change in the future if somebody wants to do
  non-SBCS conversion.

  The translation support is available wherever APR implements
  translation.

Quick todos... Sanity check on ASCII with APR_HAS_XLATE (e.g., RedHat
6) and ASCII without APR_HAS_XLATE (e.g., FreeBSD 3.4, RedHat 5,
Win32).

Index: include/apr_md5.h
===================================================================
RCS file: /cvs/apache/apache-2.0/src/lib/apr/include/apr_md5.h,v
retrieving revision 1.9
diff -u -r1.9 apr_md5.h
--- apr_md5.h	2000/04/23 02:32:57	1.9
+++ apr_md5.h	2000/05/03 02:29:20
@@ -82,10 +82,11 @@
  * <http://www.apache.org/>.
  */
 
-#ifndef APACHE_MD5_H
-#define APACHE_MD5_H
+#ifndef APR_MD5_H
+#define APR_MD5_H
 
 #include "apr_lib.h"
+#include "apr_xlate.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -101,9 +102,15 @@
     UINT4 state[4];		/* state (ABCD) */
     UINT4 count[2];		/* number of bits, modulo 2^64 (lsb first) */
     unsigned char buffer[64];	/* input buffer */
+#if APR_HAS_XLATE
+    ap_xlate_t *xlate;          /* translation handle */
+#endif
 } ap_md5_ctx_t;
 
 API_EXPORT(ap_status_t) ap_MD5Init(ap_md5_ctx_t *context);
+#if APR_HAS_XLATE
+API_EXPORT(ap_status_t) ap_MD5SetXlate(ap_md5_ctx_t *context, ap_xlate_t *xlate);
+#endif
 API_EXPORT(ap_status_t) ap_MD5Update(ap_md5_ctx_t *context,
                                      const unsigned char *input,
                                      unsigned int inputLen);
@@ -116,4 +123,4 @@
 }
 #endif
 
-#endif	/* !APACHE_MD5_H */
+#endif	/* !APR_MD5_H */
Index: lib/apr_md5.c
===================================================================
RCS file: /cvs/apache/apache-2.0/src/lib/apr/lib/apr_md5.c,v
retrieving revision 1.12
diff -u -r1.12 apr_md5.c
--- apr_md5.c	2000/04/23 02:32:57	1.12
+++ apr_md5.c	2000/05/03 02:29:20
@@ -189,9 +189,25 @@
     context->state[1] = 0xefcdab89;
     context->state[2] = 0x98badcfe;
     context->state[3] = 0x10325476;
+#if APR_HAS_XLATE
+    context->xlate = NULL;
+#endif
     return APR_SUCCESS;
 }
 
+#if APR_HAS_XLATE
+/* MD5 translation setup.  Provides the APR translation handle
+ * to be used for translating the content before calculating the
+ * digest.
+ */
+
+API_EXPORT(ap_status_t) ap_MD5SetXlate(ap_md5_ctx_t *context, ap_xlate_t *xlate)
+{
+    context->xlate = xlate;
+    return APR_SUCCESS;
+}
+#endif /* APR_HAS_XLATE */
+
 /* MD5 block update operation. Continues an MD5 message-digest
    operation, processing another message block, and updating the
    context.
@@ -201,6 +217,9 @@
                                      unsigned int inputLen)
 {
     unsigned int i, idx, partLen;
+#if APR_HAS_XLATE
+    ap_size_t inbytes_left, outbytes_left;
+#endif
 
     /* Compute number of bytes mod 64 */
     idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
@@ -213,7 +232,7 @@
     partLen = 64 - idx;
 
     /* Transform as many times as possible. */
-#ifndef CHARSET_EBCDIC
+#if !APR_HAS_XLATE
     if (inputLen >= partLen) {
 	memcpy(&context->buffer[idx], input, partLen);
 	MD5Transform(context->state, context->buffer);
@@ -228,15 +247,29 @@
 
     /* Buffer remaining input */
     memcpy(&context->buffer[idx], &input[i], inputLen - i);
-#else /*CHARSET_EBCDIC*/
+#else /*APR_HAS_XLATE*/
     if (inputLen >= partLen) {
-	ebcdic2ascii_strictly(&context->buffer[idx], input, partLen);
+        if (context->xlate) {
+            inbytes_left = outbytes_left = partLen;
+            ap_xlate_conv_buffer(context->xlate, input, &inbytes_left,
+                                 &context->buffer[idx],&outbytes_left);
+        }
+        else {
+            memcpy(&context->buffer[idx], input, partLen);
+        }
 	MD5Transform(context->state, context->buffer);
 
 	for (i = partLen; i + 63 < inputLen; i += 64) {
-	    unsigned char inp_tmp[64];
-	    ebcdic2ascii_strictly(inp_tmp, &input[i], 64);
-	    MD5Transform(context->state, inp_tmp);
+            if (context->xlate) {
+                unsigned char inp_tmp[64];
+                inbytes_left = outbytes_left = 64;
+                ap_xlate_conv_buffer(context->xlate, &input[i], &inbytes_left,
+                                     inp_tmp, &outbytes_left);
+                MD5Transform(context->state, inp_tmp);
+            }
+            else {
+                MD5Transform(context->state, &input[i]);
+            }
 	}
 
 	idx = 0;
@@ -245,8 +278,15 @@
 	i = 0;
 
     /* Buffer remaining input */
-    ebcdic2ascii_strictly(&context->buffer[idx], &input[i], inputLen - i);
-#endif /*CHARSET_EBCDIC*/
+    if (context->xlate) {
+        inbytes_left = outbytes_left = inputLen - i;
+        ap_xlate_conv_buffer(context->xlate, &input[i], &inbytes_left,
+                             &context->buffer[idx], &outbytes_left);
+    }
+    else {
+        memcpy(&context->buffer[idx], &input[i], inputLen - i);
+    }
+#endif /*APR_HAS_XLATE*/
     return APR_SUCCESS;
 }
 
@@ -259,24 +299,13 @@
     unsigned char bits[8];
     unsigned int idx, padLen;
 
-
     /* Save number of bits */
     Encode(bits, context->count, 8);
 
-#ifdef CHARSET_EBCDIC
-    /* XXX: @@@: In order to make this no more complex than necessary,
-     * this kludge converts the bits[] array using the ascii-to-ebcdic
-     * table, because the following ap_MD5Update() re-translates
-     * its input (ebcdic-to-ascii).
-     * Otherwise, we would have to pass a "conversion" flag to ap_MD5Update()
-     */
-    ascii2ebcdic(bits,bits,8);
-
-    /* Since everything is converted to ascii within ap_MD5Update(), 
-     * the initial 0x80 (PADDING[0]) must be stored as 0x20 
-     */
-    PADDING[0] = os_toebcdic[0x80];
-#endif /*CHARSET_EBCDIC*/
+#if APR_HAS_XLATE
+    /* ap_MD5Update() should not translate for this final round. */
+    context->xlate = NULL;
+#endif /*APR_HAS_XLATE*/
 
     /* Pad out to 56 mod 64. */
     idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);

test/testmd5.c:

/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2000 The Apache Software Foundation.  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. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" 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 name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``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 SOFTWARE FOUNDATION 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 Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include <assert.h>
#include <stdlib.h>

#include "apr_md5.h"
#include "apr_xlate.h"

struct testcase {
    const char *s;
    const char *digest;
};

struct testcase testcases[] =
{
    {"Jeff was here!",
     "\xa5\x25\x8a\x89\x11\xb2\x9d\x1f\x81\x75\x96\x3b\x60\x94\x49\xc0"},
    {"01234567890aBcDeFASDFGHJKLPOIUYTR"
     "POIUYTREWQZXCVBN  LLLLLLLLLLLLLLL",
     "\xd4\x1a\x06\x2c\xc5\xfd\x6f\x24\x67\x68\x56\x7c\x40\x8a\xd5\x69"},
    {"111111118888888888888888*******%%%%%%%%%%#####"
     "142134u8097289720432098409289nkjlfkjlmn,m..   ",
     "\xb6\xea\x5b\xe8\xca\x45\x8a\x33\xf0\xf1\x84\x6f\xf9\x65\xa8\xe1"},
    {"01234567890aBcDeFASDFGHJKLPOIUYTR"
     "POIUYTREWQZXCVBN  LLLLLLLLLLLLLLL"
     "01234567890aBcDeFASDFGHJKLPOIUYTR"
     "POIUYTREWQZXCVBN  LLLLLLLLLLLLLLL"
     "1",
     "\xd1\xa1\xc0\x97\x8a\x60\xbb\xfb\x2a\x25\x46\x9d\xa5\xae\xd0\xb0"}
};

static void try(const void *buf, size_t bufLen, ap_xlate_t *xlate,
                const void *digest)
{
    int i;
    ap_status_t rv;
    ap_md5_ctx_t context;
    unsigned char hash[MD5_DIGESTSIZE];

    rv = ap_MD5Init(&context);
    assert(!rv);

    if (xlate) {
#if APR_HAS_XLATE
        ap_MD5SetXlate(&context, xlate);
#else
        fprintf(stderr,
                "A translation handle was unexpected.\n");
#endif
    }
    
    rv = ap_MD5Update(&context, buf, bufLen);
    assert(!rv);

    rv = ap_MD5Final(hash, &context);
    assert(!rv);

    for (i = 0; i < MD5_DIGESTSIZE; i++) {
        printf("%02x",hash[i]);
    }

    printf("\n");

    if (memcmp(hash, digest, MD5_DIGESTSIZE)) {
        fprintf(stderr,
                "The digest is not as expected!\n");
#if 'A' != 0x41
        fprintf(stderr,
                "Maybe you didn't tell me what character sets "
                "to translate between?\n"
                "The expected digest is based on the string "
                "being in ASCII.\n");
#endif
    }
}

int main(int argc, char **argv)
{
    ap_status_t rv;
    ap_xlate_t *xlate = NULL;
    ap_pool_t *pool;
    const char *src = NULL, *dst = NULL;
    int cur;

    switch(argc) {
    case 1:
        break;
    case 3:
        src = argv[1];
        dst = argv[2];
        break;
    default:
        fprintf(stderr,
                "Usage: %s [src-charset dst-charset]\n",
                argv[0]);
        exit(1);
    }

    rv = ap_initialize();
    assert(!rv);
    atexit(ap_terminate);

    rv = ap_create_pool(&pool, NULL);

    if (src) {
#if APR_HAS_XLATE
        rv = ap_xlate_open(&xlate, dst, src, pool);
        assert(!rv);
#else
        fprintf(stderr,
                "APR doesn't implement translation for this "
                "configuration.\n");
#endif
    }

    for (cur = 0; cur < sizeof(testcases) / sizeof(testcases[0]); cur++) {
        try(testcases[cur].s, strlen(testcases[cur].s), xlate,
            testcases[cur].digest);
    }
    
    return 0;
}


-- 
Jeff Trawick | trawick@ibm.net | PGP public key at web site:
     http://www.geocities.com/SiliconValley/Park/9289/
          Born in Roswell... married an alien...

Mime
View raw message