httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dirk-Willem van Gulik <di...@webweaving.org>
Subject Re: PATCH: ap_md5c.c understands SHA1 (Netscape web server) passwords
Date Fri, 06 Aug 1999 08:57:43 GMT

Good stuff ! Well done. I hope you do not mind me fowrarding 
it to the new-httpd list. If I do not hear any rumbles I'll
commit it sometime after the americans have woken up (to it).

Dw.

On Fri, 6 Aug 1999, Life is hard, and then you die. wrote:

> 
>   Hi Dirk-Willem,
> 
> > > > Good idea. If you're doing that, you might want to also consider adding
> > > > the base64encode() and base64decode() functions from the mod_digest I
> > > > posted - they're binary versions, i.e. they only do the ebcdic conversion
> > > > on the encoded side and they use explicit lengths instead of NUL
> > > > termination on the data side. But if you do that, you might want to
> > > > (mis-)name them uuencode_binary or something for consistency.
> > > > 
> > > Hmm, I am then going to be nasty. The next message contains the patch I
> > > had in mind; feel free to take it further :-) I'll postpone commiting
> > > that one a bit; to see if you come up with something way cooler.
> 
> Sorry for the delay - had some unexpected interrupts.
> 
> Ok, I had a look at ap_base64.c - nice work. I've made the following
> changes:
> 
> - added ap_uuencode_binary() and ap_uudecode_binary() functions. These
>   are the same as their normal counterparts on ASCII systems, but
>   don't do the conversion on the encoded stuff on EBCDIC.
> 
> - the normal ap_uuencode() and ap_uudecode() take char* for the encoded
>   buffer; the binary versions use unsigned char*. This seems more
>   consistent to me.
> 
> - For EBCDIC machines folded to_ascii[] into ps2six[]. This simplifies
>   the code (less #ifdef's) and makes things faster for those platforms.
> 
> - NUL terminate all output. I consider this the path of least surprise,
>   especially for ap_uuencode[_binary].
> 
> - Fixed a bug in ap_uuencode(): if (len % 3 == 1) and the buffer had
>   non-NUL characters after the end then the last character before the
>   terminating '==' was wrong (the code was accessing string[i+1] when
>   (i == len-1)).
> 
> - commented out the '#include ap_base64.h' - it was not in the stuff
>   you sent, and the functions seemed to be defined in ap.h. However,
>   I think it would be better to put the prototypes in an ap_base64.h
>   and #include that in ap.h (the discussions on new-httpd leads me to
>   believe that others consider this right way too).
> 
> 
> On the sha1 side of things, my changes are:
> 
> - move the SHA_INFO to ap_sha1.h and rename to AP_SHA1_CTX; similarly
>   moved the AP_BYTE and AP_LONG typedefs to ap_sha1.h.
> 
> - rename the functions to ap_SHA1Init(), ap_SHA1Update(), and
>   ap_SHA1_Final(), made them exported, and move prototypes to ap_sha1.h
> 
> - ap_SHA1Update() does ebcdic -> ascii conversion on input, just like
>   the corresponding function for md5.
> 
> - added ap_SHA1Update_binary() which does not do any ebcdic -> ascii
>   conversions.
> 
> - ap_SHA1Final() writes the digest to the given buffer.
> 
> - Most the other changes you sent were also incorporated.
> 
> I've appended the patches for ap_sha1.[ch] and ap.h, and the full
> ap_base64.c . Let me know if you disagree, or just go ahead and commit
> as you see fit.
> 
> 
>   Cheers,
> 
>   Ronald
> 
> 
> ------------------------------------------------------------------------
> Index: ap_sha1.c
> ===================================================================
> RCS file: /home/cvs/apache-1.3/src/ap/ap_sha1.c,v
> retrieving revision 1.3
> diff -u -r1.3 ap_sha1.c
> --- ap_sha1.c	1999/08/05 20:04:01	1.3
> +++ ap_sha1.c	1999/08/06 07:22:46
> @@ -6,7 +6,7 @@
>   * are met:
>   *
>   * 1. Redistributions of source code must retain the above copyright
> - *    notice, this list of conditions and the following disclaimer. 
> + *    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
> @@ -70,10 +70,10 @@
>   *     will always generate the same hash, making it easier
>   *     to break since the search space is smaller.
>   *
> - * See also the documentation in support/SHA1 as to hints on how to 
> + * See also the documentation in support/SHA1 as to hints on how to
>   * migrate an existing netscape installation and other supplied utitlites.
>   *
> - * This software also makes use of the following components: 
> + * This software also makes use of the following components:
>   *
>   * NIST Secure Hash Algorithm
>   *  	heavily modified by Uwe Hollerbach uh@alumni.caltech edu
> @@ -86,15 +86,15 @@
>   *
>   * Metamail's copyright is:
>   * 	Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
> - * 	Permission to use, copy, modify, and distribute this material 
> - *	for any purpose and without fee is hereby granted, provided 
> - *	that the above copyright notice and this permission notice 
> - *	appear in all copies, and that the name of Bellcore not be 
> - *	used in advertising or publicity pertaining to this 
> - *	material without the specific, prior written permission 
> - *	of an authorized representative of Bellcore.  BELLCORE 
> - *	MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY 
> - *	OF THIS MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS", 
> + * 	Permission to use, copy, modify, and distribute this material
> + *	for any purpose and without fee is hereby granted, provided
> + *	that the above copyright notice and this permission notice
> + *	appear in all copies, and that the name of Bellcore not be
> + *	used in advertising or publicity pertaining to this
> + *	material without the specific, prior written permission
> + *	of an authorized representative of Bellcore.  BELLCORE
> + *	MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
> + *	OF THIS MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS",
>   *	WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
>   */
>  
> @@ -133,30 +133,13 @@
>      temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n;	\
>      E = D; D = C; C = ROT32(B,30); B = A; A = temp
>  
> -typedef unsigned char AP_BYTE;     /* an 8-bit quantity */
> -typedef unsigned long AP_LONG;     /* a 32-bit quantity */
> - 
>  #define SHA_BLOCKSIZE           64
>  #define SHA_DIGESTSIZE          20
> - 
> -typedef struct {
> -    AP_LONG digest[5];             /* message digest */
> -    AP_LONG count_lo, count_hi;    /* 64-bit bit count */
> -    AP_LONG data[16];              /* SHA data buffer */
> -    int local;                  /* unprocessed amount in data */
> -} SHA_INFO;
> -
> -static void sha_init(SHA_INFO *);
> -static void sha_update(SHA_INFO *, const AP_BYTE *, int);
> -static void sha_final(SHA_INFO *);
> -static void sha_raw_swap(SHA_INFO *);
> -static void output64chunk(unsigned char, unsigned char, unsigned char,
> -			  int, unsigned char **);
> -static void encode_mime64(unsigned char *, unsigned char *, int);
> -void sha1_base64(char *, int, char *);
>  
> +typedef unsigned char AP_BYTE;
> +
>  /* do SHA transformation */
> -static void sha_transform(SHA_INFO *sha_info)
> +static void sha_transform(AP_SHA1_CTX *sha_info)
>  {
>      int i;
>      AP_LONG temp, A, B, C, D, E, W[80];
> @@ -236,7 +219,7 @@
>      int i;
>      AP_BYTE ct[4], *cp;
>  
> -    if (isLittleEndian()) {    /* do the swap only if it is little endian */
> +    if (isLittleEndian()) {	/* do the swap only if it is little endian */
>  	count /= sizeof(AP_LONG);
>  	cp = (AP_BYTE *) buffer;
>  	for (i = 0; i < count; ++i) {
> @@ -255,7 +238,7 @@
>  
>  /* initialize the SHA digest */
>  
> -static void sha_init(SHA_INFO *sha_info)
> +API_EXPORT(void) ap_SHA1Init(AP_SHA1_CTX *sha_info)
>  {
>      sha_info->digest[0] = 0x67452301L;
>      sha_info->digest[1] = 0xefcdab89L;
> @@ -269,7 +252,9 @@
>  
>  /* update the SHA digest */
>  
> -static void sha_update(SHA_INFO *sha_info, const AP_BYTE *buffer, int count)
> +API_EXPORT(void) ap_SHA1Update_binary(AP_SHA1_CTX *sha_info,
> +				      const unsigned char *buffer,
> +				      unsigned int count)
>  {
>      int i;
>  
> @@ -306,12 +291,55 @@
>      sha_info->local = count;
>  }
>  
> +API_EXPORT(void) ap_SHA1Update(AP_SHA1_CTX *sha_info, const char *buf,
> +			       unsigned int count)
> +{
> +#ifdef CHARSET_EBCDIC
> +    int i;
> +    const AP_BYTE *buffer = (const AP_BYTE *) buf;
> +
> +    if ((sha_info->count_lo + ((LONG) count << 3)) < sha_info->count_lo)
{
> +	++sha_info->count_hi;
> +    }
> +    sha_info->count_lo += (LONG) count << 3;
> +    sha_info->count_hi += (LONG) count >> 29;
> +    if (sha_info->local) {
> +	i = SHA_BLOCKSIZE - sha_info->local;
> +	if (i > count) {
> +	    i = count;
> +	}
> +	ebcdic2ascii_strictly(((AP_BYTE *) sha_info->data) + sha_info->local, ubuf, i);
> +	count -= i;
> +	buffer += i;
> +	sha_info->local += i;
> +	if (sha_info->local == SHA_BLOCKSIZE) {
> +	    maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
> +	    sha_transform(sha_info);
> +	}
> +	else {
> +	    return;
> +	}
> +    }
> +    while (count >= SHA_BLOCKSIZE) {
> +	ebcdic2ascii_strictly(sha_info->data, buffer, SHA_BLOCKSIZE);
> +	buffer += SHA_BLOCKSIZE;
> +	count -= SHA_BLOCKSIZE;
> +	maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
> +	sha_transform(sha_info);
> +    }
> +    ebcdic2ascii_strictly(sha_info->data, buffer, count);
> +    sha_info->local = count;
> +#else
> +    ap_SHA1Update_binary(sha_info, (const unsigned char *) buf, count);
> +#endif
> +}
> +
>  /* finish computing the SHA digest */
>  
> -static void sha_final(SHA_INFO *sha_info)
> +API_EXPORT(void) ap_SHA1Final(unsigned char digest[20], AP_SHA1_CTX *sha_info)
>  {
> -    int count;
> -    AP_LONG lo_bit_count, hi_bit_count;
> +    int count, i, j;
> +    AP_LONG lo_bit_count, hi_bit_count, k;
>  
>      lo_bit_count = sha_info->count_lo;
>      hi_bit_count = sha_info->count_hi;
> @@ -331,66 +359,17 @@
>      sha_info->data[14] = hi_bit_count;
>      sha_info->data[15] = lo_bit_count;
>      sha_transform(sha_info);
> -}
> -
> -/*
> -   internally implemented as an array of longs, need to swap if 
> -   you're going to access the memory in the raw, instead of looping
> -   through with arrays of longs.
> -*/
>  
> -static void sha_raw_swap(SHA_INFO *sha_info)
> -{
> -    int i;
> -
> -    for (i = 0; i < 5; ++i) {
> -	maybe_byte_reverse((AP_LONG *) &sha_info->digest[i], 4);
> +    for (i = 0, j = 0; j < SHA_DIGESTSIZE; i++) {
> +	k = sha_info->digest[i];
> +	digest[j++] = (unsigned char) ((k >> 24) & 0xff);
> +	digest[j++] = (unsigned char) ((k >> 16) & 0xff);
> +	digest[j++] = (unsigned char) ((k >> 8) & 0xff);
> +	digest[j++] = (unsigned char) (k & 0xff);
>      }
>  }
>  
> -static char basis_64[] =
> -  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
>  
> -static void output64chunk(unsigned char c1, unsigned char c2, unsigned char c3,
> -			  int pads, unsigned char **outfile)
> -{
> -    *(*outfile)++ = basis_64[c1>>2];
> -
> -    *(*outfile)++ = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >>
4)];
> -    if (pads == 2) {
> -	*(*outfile)++ = '=';
> -	*(*outfile)++ = '=';
> -    }
> -    else if (pads) {
> -	*(*outfile)++ =  basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
> -	*(*outfile)++ = '=';
> -    }
> -    else {
> -	*(*outfile)++ = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
> -	*(*outfile)++ = basis_64[c3 & 0x3F];
> -    }
> -}
> -
> -static void encode_mime64(unsigned char *in, unsigned char *out, int length)
> -{
> -    int diff, ct = 0;
> -
> -    while ((diff = length - ct)) {
> -	if ( diff >= 3 ) {
> -	    diff = 3;
> -	    output64chunk(in[ct], in[ct+1], in[ct+2], 0, &out);
> -	}
> -	else if (diff == 2) {
> -	    output64chunk(in[ct], in[ct+1], 0, 1, &out);
> -	}
> -	else if (diff == 1) {
> -	    output64chunk(in[ct], 0, 0, 2, &out);
> -	}
> -	ct += diff;
> -    }
> -    *out++ = 0;
> -}
> -
>  /* {SHA} is the prefix used for base64 encoded sha1 in
>   * ldap data interchange format.
>   */
> @@ -398,23 +377,27 @@
>  
>  API_EXPORT(void) ap_sha1_base64(const char *clear, int len, char *out)
>  {
> -    SHA_INFO context;
> +    int l;
> +    AP_SHA1_CTX context;
> +    AP_BYTE digest[SHA_DIGESTSIZE];
>  
>      if (!strncmp(clear, sha1_id, strlen(sha1_id))) {
>  	clear += strlen(sha1_id);
>      }
> -
> -    sha_init(&context);
> -    sha_update(&context, clear, len);
> -    sha_final(&context);
>  
> -    sha_raw_swap(&context);
> +    ap_SHA1Init(&context);
> +    ap_SHA1Update(&context, clear, len);
> +    ap_SHA1Final(digest, &context);
>  
>      /* private marker. */
>      strcpy(out, sha1_id);
>  
>      /* SHA1 hash is always 20 chars */
> -    encode_mime64((char *)context.digest, out+strlen(sha1_id), 20);
> -    /* output of MIME Base 64 encoded SHA1 is always
> -     * 28 characters + strlen(sha1_id) */
> +    l = ap_uuencode_binary(out + strlen(sha1_id), digest, sizeof(digest));
> +    out[l + strlen(sha1_id)] = '\0';
> +
> +    /*
> +     * output of MIME Base 64 encoded SHA1 is always 28 characters +
> +     * strlen(sha1_id)
> +     */
>  }
> Index: ap_sha1.h
> ===================================================================
> RCS file: /home/cvs/apache-1.3/src/include/ap_sha1.h,v
> retrieving revision 1.3
> diff -u -r1.3 ap_sha1.h
> --- ap_sha1.h	1999/08/05 20:04:03	1.3
> +++ ap_sha1.h	1999/08/06 07:24:06
> @@ -84,11 +84,27 @@
>  extern "C" {
>  #endif
>  
> +typedef unsigned long AP_LONG;     /* a 32-bit quantity */
> +
> +typedef struct {
> +    AP_LONG digest[5];             /* message digest */
> +    AP_LONG count_lo, count_hi;    /* 64-bit bit count */
> +    AP_LONG data[16];              /* SHA data buffer */
> +    int local;                     /* unprocessed amount in data */
> +} AP_SHA1_CTX;
> +
>  extern const char *sha1_id;	/* passwd prefix marker for SHA1 */
>  API_EXPORT(void) ap_sha1_base64(const char *clear, int len, char *out);
> +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_MD5_H */
> +#endif	/* !APACHE_SHA1_H */
> Index: ap.h
> ===================================================================
> RCS file: /home/cvs/apache-1.3/src/include/ap.h,v
> retrieving revision 1.22
> diff -u -r1.22 ap.h
> --- ap.h	1999/08/02 20:50:14	1.22
> +++ ap.h	1999/08/06 08:42:44
> @@ -159,6 +159,30 @@
>  			    __attribute__((format(printf,3,4)));
>  API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
>  			     va_list ap);
> +/* Simple BASE64 encode/decode functions.
> + * 
> + * As we might encode binary strings, hence we require the length of
> + * the incoming plain source. And return the length of what we decoded.
> + *
> + * The decoding function takes any non valid char (i.e. whitespace, \0
> + * or anything non A-Z,0-9 etc as terminal.
> + * 
> + * plain strings/binary sequences are not assumed '\0' terminated. Encoded
> + * strings are neither. But propably should.
> + *
> + */
> +API_EXPORT(int) ap_uuencode_len(int len);
> +API_EXPORT(int) ap_uuencode(char * coded_dst, const char *plain_src,int len_plain_src);
> +API_EXPORT(int) ap_uuencode_binary(char * coded_dst, const unsigned char *plain_src,int
len_plain_src);
> +
> +API_EXPORT(int) ap_uudecode_len(const char * coded_src);
> +API_EXPORT(int) ap_uudecode(char * plain_dst, const char *coded_src);
> +API_EXPORT(int) ap_uudecode_binary(unsigned char * plain_dst, const char *coded_src);
> +
> +/* Password validation, as used in AuthType Basic which is able to cope
> + * (based on the prexix) with the SHA1, Apache's internal MD5 and (depending
> + * on your platform either plain or crypt(3) passwords.
> + */
>  API_EXPORT(char *) ap_validate_password(const char *passwd, const char *hash);
>  
>  #ifdef __cplusplus
> ------------------------------------------------------------------------
> /* ====================================================================
>  * Copyright (c) 1995-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/>.
>  *
>  */
> 
> /* * base64 encoder/decoder. Origianly part of main/util.c
>  * but moved here so that support/ab and ap_sha1.c could
>  * use it. This mean (re)moving the ap_palloc()s. And adding
>  * ugly 'len' functions. Which is quite a nasty cost.
>  */
> 
> #include <string.h>
> 
> #include "ap_config.h"
> /* #include "ap_base64.h" ??? */
> #include "ap.h"
> 
> #ifdef CHARSET_EBCDIC
> #include "ebcdic.h"
> #endif				/* CHARSET_EBCDIC */
> 
> /* aaaack but it's fast and const should make it shared text page. */
> static const unsigned char pr2six[256] =
> {
> #ifndef CHARSET_EBCDIC
>     /* ASCII table */
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54,
>     55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3,
>     4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
>     22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32,
>     33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
>     50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
> #else /*CHARSET_EBCDIC*/
>     /* EBCDIC table */
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 64, 64, 64, 64, 64, 64,
>     64, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 64, 64, 64, 64, 64,
>     64, 64, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64,
>     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
>     64,  0,  1,  2,  3,  4,  5,  6,  7,  8, 64, 64, 64, 64, 64, 64,
>     64,  9, 10, 11, 12, 13, 14, 15, 16, 17, 64, 64, 64, 64, 64, 64,
>     64, 64, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64,
>     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
> #endif /*CHARSET_EBCDIC*/
> };
> 
> API_EXPORT(int) ap_uudecode_len(const char *bufcoded)
> {
>     int nbytesdecoded;
>     register const unsigned char *bufin;
>     register int nprbytes;
> 
>     bufin = (const unsigned char *) bufcoded;
>     while (pr2six[*(bufin++)] <= 63);
> 
>     nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
>     nbytesdecoded = ((nprbytes + 3) / 4) * 3;
> 
>     return nbytesdecoded + 1;
> }
> 
> API_EXPORT(int) ap_uudecode(char *bufplain, const char *bufcoded)
> {
> #ifdef CHARSET_EBCDIC
>     int i;
> #endif				/* CHARSET_EBCDIC */
>     int len;
>     
>     len = ap_uudecode_binary((unsigned char *) bufplain, bufcoded);
> #ifdef CHARSET_EBCDIC
>     for (i=0; i<len; i++)
> 	bufplain[i] = os_toebcdic[bufplain[i]];
> #endif				/* CHARSET_EBCDIC */
>     return len;
> }
> 
> /* This is the same as ap_uudecode() except on EBCDIC machines, where
>  * the conversion of the output to ebcdic is left out.
>  */
> API_EXPORT(int) ap_uudecode_binary(unsigned char *bufplain,
> 				   const char *bufcoded)
> {
>     int nbytesdecoded;
>     register const unsigned char *bufin;
>     register unsigned char *bufout;
>     register int nprbytes;
> 
>     bufin = (const unsigned char *) bufcoded;
>     while (pr2six[*(bufin++)] <= 63);
>     nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
>     nbytesdecoded = ((nprbytes + 3) / 4) * 3;
> 
>     bufout = (unsigned char *) bufplain;
>     bufin = (const unsigned char *) bufcoded;
> 
>     while (nprbytes > 4) {
> 	*(bufout++) =
> 	    (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
> 	*(bufout++) =
> 	    (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
> 	*(bufout++) =
> 	    (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
> 	bufin += 4;
> 	nprbytes -= 4;
>     }
> 
>     /* Note: (nprbytes == 1) would be an error, so just ingore that case */
>     if (nprbytes > 1) {
> 	*(bufout++) =
> 	    (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
>     }
>     if (nprbytes > 2) {
> 	*(bufout++) =
> 	    (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
>     }
>     if (nprbytes > 3) {
> 	*(bufout++) =
> 	    (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
>     }
> 
>     *(bufout++) = '\0';
>     nbytesdecoded -= (4 - nprbytes) & 3;
>     return nbytesdecoded;
> }
> 
> static const char basis_64[] =
> "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
> 
> API_EXPORT(int) ap_uuencode_len(int len)
> {
>     return ((len + 2) / 3 * 4) + 1;
> }
> 
> API_EXPORT(int) ap_uuencode(char *encoded, const char *string, int len)
> {
> #ifndef CHARSET_EBCDIC
>     return ap_uuencode_binary(encoded, (const unsigned char *) string, len);
> #else				/* CHARSET_EBCDIC */
>     int i;
>     char *p;
> 
>     p = encoded;
>     for (i = 0; i < len - 2; i += 3) {
> 	*p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
> 	*p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) | ((int) (os_toascii[string[i
+ 1]] & 0xF0) >> 4)];
> 	*p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) | ((int) (os_toascii[string[i
+ 2]] & 0xC0) >> 6)];
> 	*p++ = basis_64[os_toascii[string[i + 2]] & 0x3F];
>     }
>     if (i < len) {
> 	*p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
> 	if (i == (len - 1)) {
> 	    *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)];
> 	    *p++ = '=';
> 	}
> 	else {
> 	    *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) | ((int) (os_toascii[string[i
+ 1]] & 0xF0) >> 4)];
> 	    *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)];
> 	}
> 	*p++ = '=';
>     }
> 
>     *p++ = '\0';
>     return p - encoded;
> #endif				/* CHARSET_EBCDIC */
> }
> 
> /* This is the same as ap_uuencode() except on EBCDIC machines, where
>  * the conversion of the input to ascii is left out.
>  */
> API_EXPORT(int) ap_uuencode_binary(char *encoded, const unsigned char *string,
> 				   int len)
> {
>     int i;
>     char *p;
> 
>     p = encoded;
>     for (i = 0; i < len - 2; i += 3) {
> 	*p++ = basis_64[(string[i] >> 2) & 0x3F];
> 	*p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0)
>> 4)];
> 	*p++ = basis_64[((string[i + 1] & 0xF) << 2) | ((int) (string[i + 2] &
0xC0) >> 6)];
> 	*p++ = basis_64[string[i + 2] & 0x3F];
>     }
>     if (i < len) {
> 	*p++ = basis_64[(string[i] >> 2) & 0x3F];
> 	if (i == (len - 1)) {
> 	    *p++ = basis_64[((string[i] & 0x3) << 4)];
> 	    *p++ = '=';
> 	}
> 	else {
> 	    *p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] &
0xF0) >> 4)];
> 	    *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
> 	}
> 	*p++ = '=';
>     }
> 
>     *p++ = '\0';
>     return p - encoded;
> }
> ------------------------------------------------------------------------
> 
> 


Mime
View raw message