Bugtraq mailing list archives

local mail delivery


From: mouse () Collatz McRCIM McGill EDU (der Mouse)
Date: Thu, 3 Aug 1995 07:28:46 -0400


I was called for help on a breakin attempt that appeared to be using
the local mail delivery agent race on SunOS.  In response, I wrote the
following.  It appears to me to be fairly tight, but I'd appreciate any
flaws anyone can pick with it.  (It does have some problems, notably
lack of checking for malloc() failure and disk full errors.  I'm
talking about specifically security holes.)

In return, I offer this to anyone who may care to use it.  (Of course,
it comes with no warranty; it's free, and you get what you pay for.)
Unpack into a directory somewhere and compile with
"cc -I. -o localmail *.c" or something equivalent.  (You will need to
use a prototype-capable compiler.  NeXTstep 2.1 /bin/cc works, as does
gcc 2.6.3 under SunOS 4.1.3, provided you link with something that
provides strerror().)

                                        der Mouse

                            mouse () collatz mcrcim mcgill edu

#! /bin/sh
#
# Shar: Shell Archiver
#
# This archive created Thu Aug  3 07:18:27 1995
# Run this through sh to create:
#       localmail.c
#       md5.c
#       md5.h
#       signaltype.h
#       syscalls.h
echo x - localmail.c \(9292 characters\)
sed 's/^X//' > localmail.c << \EOF
X#include <md5.h>
X#include <pwd.h>
X#include <stdio.h>
X#include <errno.h>
X#include <netdb.h>
X#include <stdlib.h>
X#include <signal.h>
X#include <syslog.h>
X#include <strings.h>
X#include <sysexits.h>
X#include <sys/time.h>
X#include <sys/file.h>
X#include <sys/stat.h>
X#include <syscalls.h>
X#include <arpa/inet.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <signaltype.h>
X
Xchar **argvec;
X
Xstatic const char maildir[256] = "/usr/spool/mail";
X
Xstatic FILE *tmpf;
Xstatic const char *fromperson;
X
Xstatic void setsig(int sig, signaltype (*f)(int))
X{
X if (signal(sig,SIG_IGN) != SIG_IGN) signal(sig,f);
X}
X
Xstatic SIGNALHANDLERDEF(die,sig)
X{
X exit(1);
X}
X
Xstatic void opentemp(void)
X{
X struct timeval tv;
X void *m;
X int n;
X int i;
X int j;
X unsigned int a;
X struct stat dstb;
X struct stat fstb;
X char hostname[256];
X unsigned char hash[16];
X char path[64];
X char *pp;
X static const char chars[] = " !\"#$%&'()*+,-.0123456789:;<=>?"
X                            "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
X                            "`abcdefghijklmnopqrstuvwxyz{|}~";
X
X m = md5_init();
X gettimeofday(&tv,0);
X md5_process_bytes(m,&tv,sizeof(tv));
X i = gethostid();
X md5_process_bytes(m,&i,sizeof(i));
X i = getpid();
X md5_process_bytes(m,&i,sizeof(i));
X i = getppid();
X md5_process_bytes(m,&i,sizeof(i));
X gethostname(&hostname[0],sizeof(hostname));
X md5_process_bytes(m,&hostname[0],sizeof(hostname));
X md5_result(m,&hash[0]);
X pp = &path[0];
X strcpy(pp,"/tmp/m:");
X pp += strlen(pp);
X for (i=0;i<20;i++)
X  { a = 0;
X    for (j=0;j<16;j++)
X     { a = (a * 256) + hash[j];
X       hash[j] = a / 94;
X       a %= 94;
X     }
X    *pp++ = chars[a];
X  }
X n = 0;
X while (1)
X  { n ++;
X    if (n > 100)
X     { pp[0] = '\0';
X       fprintf(stderr,"too many failures looking for temp file; prefix: %s\n",&path[0]);
X       syslog(LOG_ERR,"too many failures looking for temp file; prefix: %s",&path[0]);
X       exit(EX_OSERR);
X     }
X    for (j=0,i=n;i>0;j++,i/=94) pp[j] = chars[i%94];
X    pp[j] = '\0';
X    if ((lstat(&path[0],&dstb) < 0) && (errno == ENOENT))
X     { i = open(&path[0],O_RDWR|O_CREAT|O_TRUNC|O_EXCL,0600);
X       if (i < 0) continue;
X       fstat(i,&fstb);
X       if (lstat(&path[0],&dstb) < 0)
X       { fprintf(stderr,"open succeeded but path doesn't exist: %s\n",&path[0]);
X         syslog(LOG_CRIT,"UNDER ATTACK: temp open succeeded but path doesn't exist: %s",&path[0]);
X         exit(EX_TEMPFAIL);
X       }
X       if ((fstb.st_dev != dstb.st_dev) || (fstb.st_ino != dstb.st_ino))
X       { fprintf(stderr,"opened something else: %s\n",&path[0]);
X         fprintf(stderr,"fd: ino %lu on %lu; file: ino %lu on %lu\n",
X                       (unsigned long int)fstb.st_ino,
X                       (unsigned long int)fstb.st_dev,
X                       (unsigned long int)dstb.st_ino,
X                       (unsigned long int)dstb.st_dev);
X         syslog(LOG_CRIT,"UNDER ATTACK: temp open opened something else: %s",&path[0]);
X         syslog(LOG_CRIT,"fd: ino %lu on %lu; file: ino %lu on %lu",
X                       (unsigned long int)fstb.st_ino,
X                       (unsigned long int)fstb.st_dev,
X                       (unsigned long int)dstb.st_ino,
X                       (unsigned long int)dstb.st_dev);
X         exit(EX_TEMPFAIL);
X       }
X       tmpf = fdopen(i,"r+");
X       rewind(tmpf);
X       unlink(&path[0]);
X       return;
X     }
X  }
X}
X
Xstatic void collectletter(void)
X{
X time_t now;
X char fromcmp[5];
X int c;
X int i;
X
X time(&now);
X fprintf(tmpf,"From %s %s",fromperson,ctime(&now));
X while (1)
X  { for (i=0;i<5;i++)
X     { c = getchar();
X       if (c == EOF) break;
X       fromcmp[i] = c;
X       if (c == '\n') break;
X     }
X    if (i < 5)
X     { if (i > 0) fwrite(&fromcmp[0],1,i,tmpf);
X       if (c == EOF) break;
X       putc('\n',tmpf);
X       continue;
X     }
X    if (!bcmp(&fromcmp[0],"From ",5)) putc('>',tmpf);
X    fwrite(&fromcmp[0],1,5,tmpf);
X    while (1)
X     { c = getchar();
X       if (c == EOF) break;
X       putc(c,tmpf);
X       if (c == '\n') break;
X     }
X  }
X if (c != '\n') putc('\n',tmpf);
X putc('\n',tmpf);
X}
X
Xstatic int open_mailfile(const char *path, struct passwd *who)
X{
X struct stat pstb;
X struct stat fstb;
X int mfd;
X int e;
X
X if (lstat(path,&pstb) < 0)
X  { if (errno != ENOENT)
X     { e = errno;
X       fprintf(stderr,"peculiar mail spool stat error for %s: %s\n",path,strerror(e));
X       syslog(LOG_ERR,"peculiar mail spool stat error for %s: %s",path,strerror(e));
X       return(-1);
X     }
X    mfd = open(path,O_WRONLY|O_CREAT|O_EXCL,0600);
X    if (mfd < 0)
X     { e = errno;
X       fprintf(stderr,"mail spool create error for %s: %s\n",path,strerror(e));
X       syslog(LOG_ERR,"mail spool create error for %s: %s",path,strerror(e));
X       return(-1);
X     }
X    if (lstat(path,&pstb) < 0)
X     { e = errno;
X       fprintf(stderr,"open mail spool vanished for %s: %s\n",path,strerror(e));
X       syslog(LOG_CRIT,"UNDER ATTACK: open mail spool vanished for %s: %s",path,strerror(e));
X       return(-1);
X     }
X  }
X else
X  { mfd = open(path,O_WRONLY,0);
X    if (mfd < 0)
X     { e = errno;
X       fprintf(stderr,"mail spool open error for %s: %s\n",path,strerror(e));
X       syslog(LOG_ERR,"mail spool open error for %s: %s",path,strerror(e));
X       return(-1);
X     }
X  }
X fstat(mfd,&fstb);
X if ((fstb.st_dev != pstb.st_dev) || (fstb.st_ino != pstb.st_ino))
X  { fprintf(stderr,"mail spool moved: %s\n",path);
X    syslog(LOG_CRIT,"UNDER ATTACK: mail spool %s %lu on %lu [%lu], fd %lu on %lu\n",
X       path,
X       (unsigned long int)pstb.st_dev,
X       (unsigned long int)pstb.st_ino,
X       (unsigned long int)pstb.st_uid,
X       (unsigned long int)fstb.st_dev,
X       (unsigned long int)fstb.st_ino);
X    close(mfd);
X    return(-1);
X  }
X if (fstb.st_uid != who->pw_uid)
X  { if (fstb.st_uid == 0)
X     { if (fchown(mfd,who->pw_uid,who->pw_gid) < 0)
X       { e = errno;
X         fprintf(stderr,"can't chown mail spool: %s\n",strerror(e));
X         syslog(LOG_ERR,"can't chown mail spool %s: %s",path,strerror(e));
X         close(mfd);
X         return(-1);
X       }
X     }
X    else
X     { fprintf(stderr,"wrong mail spool owner\n");
X       syslog(LOG_ERR,"mail spool %s owned by %d not %d\n",path,fstb.st_uid,who->pw_uid);
X       close(mfd);
X       return(-1);
X     }
X  }
X return(mfd);
X}
X
Xstatic void notifybiff(const char *msg)
X{
X static struct sockaddr_in addr;
X static int f = -1;
X
X if (f < 0)
X  { struct servent *sp;
X    sp = getservbyname("biff","udp");
X    addr.sin_family = AF_INET;
X    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
X    addr.sin_port = sp ? sp->s_port : htons(512);
X    f = socket(AF_INET,SOCK_DGRAM,0);
X  }
X sendto(f,msg,strlen(msg)+1,0,(struct sockaddr *)&addr,sizeof(addr));
X}
X
X#define DELIVER_ERR_NOUSER  0x00000001
X#define DELIVER_ERR_TROUBLE 0x00000002
X
Xstatic int deliverit(const char *to)
X{
X struct passwd *pw;
X char *mailfile;
X int mfd;
X FILE *mf;
X int c;
X char comsatmsg[256];
X
X pw = getpwnam(to);
X if (! pw)
X  { fprintf(stderr,"can't send to %s (no such user)\n",to);
X    return(DELIVER_ERR_NOUSER);
X  }
X mailfile = malloc(strlen(&maildir[0])+1+strlen(to)+1);
X sprintf(mailfile,"%s/%s",&maildir[0],to);
X mfd = open_mailfile(mailfile,pw);
X free(mailfile);
X if (mfd < 0)
X  { return(DELIVER_ERR_TROUBLE);
X  }
X flock(mfd,LOCK_EX);
X lseek(mfd,0,L_XTND);
X comsatmsg[0] = '\0';
X if (strlen(to) < 200)
X  { sprintf(&comsatmsg[0],"%s@%lu\n",to,(unsigned long int)lseek(mfd,0,L_XTND));
X  }
X mf = fdopen(mfd,"a");
X rewind(tmpf);
X while (1)
X  { c = getc(tmpf);
X    if (c == EOF) break;
X    putc(c,mf);
X  }
X fclose(mf);
X if (comsatmsg[0]) notifybiff(&comsatmsg[0]);
X return(0);
X}
X
Xstatic void deliverall(int nnames, char **names)
X{
X int i;
X int nerr;
X
X nerr = 0;
X for (i=0;i<nnames;i++) nerr |= deliverit(names[i]);
X if (nerr & DELIVER_ERR_TROUBLE) exit(EX_OSERR);
X if (nerr & DELIVER_ERR_NOUSER) exit(EX_NOUSER);
X}
X
Xstatic void set_fromperson(void)
X{
X struct passwd *pw;
X char *t;
X
X fromperson = getenv("USER");
X if (fromperson)
X  { pw = getpwnam(fromperson);
X    if (pw->pw_uid != getuid()) fromperson = 0;
X  }
X if (! fromperson)
X  { pw = getpwuid(getuid());
X    if (pw) fromperson = pw->pw_name;
X  }
X if (fromperson)
X  { t = malloc(strlen(fromperson)+1);
X    strcpy(t,fromperson);
X    fromperson = t;
X  }
X}
X
Xvoid main(int, char **);
Xvoid main(int ac, char **av)
X{
X argvec = av;
X chdir("/tmp");
X openlog("localmail",LOG_PID|LOG_CONS,LOG_MAIL);
X  { FILE *f;
X    int i;
X    i = open("/tmp/localmail.log",O_WRONLY|O_APPEND);
X    if (i >= 0)
X     { f = fdopen(i,"a");
X       fprintf(f,"[%d] uid=%d euid=%d ac=%d\n",getpid(),getuid(),geteuid(),ac);
X       for (i=0;av[i];i++)
X       { fprintf(f,"\t%s\n",av[i]);
X       }
X       fclose(f);
X     }
X  }
X setsig(SIGHUP,die);
X setsig(SIGINT,die);
X setsig(SIGQUIT,die);
X setsig(SIGILL,die);
X setsig(SIGTRAP,die);
X setsig(SIGIOT,die);
X setsig(SIGABRT,die);
X setsig(SIGEMT,die);
X setsig(SIGFPE,die);
X setsig(SIGKILL,die);
X setsig(SIGBUS,die);
X setsig(SIGSEGV,die);
X setsig(SIGSYS,die);
X setsig(SIGPIPE,die);
X setsig(SIGALRM,die);
X setsig(SIGTERM,die);
X opentemp();
X set_fromperson();
X if ((ac > 2) && !strcmp(av[1],"-r"))
X  { fromperson = av[2];
X    ac -= 2;
X    av += 2;
X  }
X if (! fromperson)
X  { fprintf(stderr,"Who are you?\n");
X    syslog(LOG_ERR,"no -r and no passwd entry, uid %d\n",getuid());
X    exit(EX_OSERR);
X  }
X if (index(fromperson,'\n'))
X  { fprintf(stderr,"Invalid user\n");
X    syslog(LOG_CRIT,"UNDER ATTACK: newline in from person");
X    exit(EX_USAGE);
X  }
X if ((ac > 1) && !strcmp(av[1],"-d")) /* compatability */
X  { ac --;
X    av ++;
X  }
X if (ac < 2)
X  { fprintf(stderr,"Usage: %s [-d] username [username ...]\n",argvec[0]);
X    exit(EX_USAGE);
X  }
X collectletter();
X deliverall(ac-1,av+1);
X exit(EX_OK);
X}
EOF
if test 9292 -ne "`wc -c localmail.c`"
then
echo shar: error transmitting localmail.c \(should have been 9292 characters\)
fi
echo x - md5.c \(5767 characters\)
sed 's/^X//' > md5.c << \EOF
X#include <stdlib.h>
X
X#include <md5.h>
X
Xtypedef unsigned long int U32; /* unsigned, 32 bits */
X
X#define LIMIT32(x) (((U32)(x))&(U32)0xffffffff)
X
X/* T[i] = floor((1<<32)*abs(sin(i+1))), where sin arg is in radians */
Xstatic U32 T[64] = {
X       0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
X       0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
X       0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
X       0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
X       0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
X       0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
X       0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
X       0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
X       0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
X       0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
X       0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
X       0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
X       0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
X       0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
X       0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
X       0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };
X
Xtypedef struct state STATE;
X
Xstruct state {
X  U32 A;
X  U32 B;
X  U32 C;
X  U32 D;
X  U32 X[16];
X  int xfill;
X  U32 bitlen_l;
X  U32 bitlen_h;
X  } ;
X
X#define F(X,Y,Z) (((X)&(Y))|((~(X))&(Z)))
X#define G(X,Y,Z) (((X)&(Z))|((Y)&(~(Z))))
X#define H(X,Y,Z) ((X)^(Y)^(Z))
X#define I(X,Y,Z) ((Y)^((X)|(~(Z))))
X
Xinline static U32 ROTLEFT(U32 v, unsigned int nbits)
X{
X return(LIMIT32(v<<nbits)|(LIMIT32(v)>>(32-nbits)));
X}
X
Xstatic void crunch_block(STATE *state)
X{
X U32 A;
X U32 B;
X U32 C;
X U32 D;
X U32 *X;
X
X A = state->A;
X B = state->B;
X C = state->C;
X D = state->D;
X X = &state->X[0];
X#define OP(a,b,c,d,k,s,i) a = b + ROTLEFT(a+F(b,c,d)+X[k]+T[i-1],s)
X OP(A,B,C,D, 0, 7, 1);OP(D,A,B,C, 1,12, 2);OP(C,D,A,B, 2,17, 3);OP(B,C,D,A, 3,22, 4);
X OP(A,B,C,D, 4, 7, 5);OP(D,A,B,C, 5,12, 6);OP(C,D,A,B, 6,17, 7);OP(B,C,D,A, 7,22, 8);
X OP(A,B,C,D, 8, 7, 9);OP(D,A,B,C, 9,12,10);OP(C,D,A,B,10,17,11);OP(B,C,D,A,11,22,12);
X OP(A,B,C,D,12, 7,13);OP(D,A,B,C,13,12,14);OP(C,D,A,B,14,17,15);OP(B,C,D,A,15,22,16);
X#undef OP
X#define OP(a,b,c,d,k,s,i) a = b + ROTLEFT(a+G(b,c,d)+X[k]+T[i-1],s)
X OP(A,B,C,D, 1, 5,17);OP(D,A,B,C, 6, 9,18);OP(C,D,A,B,11,14,19);OP(B,C,D,A, 0,20,20);
X OP(A,B,C,D, 5, 5,21);OP(D,A,B,C,10, 9,22);OP(C,D,A,B,15,14,23);OP(B,C,D,A, 4,20,24);
X OP(A,B,C,D, 9, 5,25);OP(D,A,B,C,14, 9,26);OP(C,D,A,B, 3,14,27);OP(B,C,D,A, 8,20,28);
X OP(A,B,C,D,13, 5,29);OP(D,A,B,C, 2, 9,30);OP(C,D,A,B, 7,14,31);OP(B,C,D,A,12,20,32);
X#undef OP
X#define OP(a,b,c,d,k,s,i) a = b + ROTLEFT(a+H(b,c,d)+X[k]+T[i-1],s)
X OP(A,B,C,D, 5, 4,33);OP(D,A,B,C, 8,11,34);OP(C,D,A,B,11,16,35);OP(B,C,D,A,14,23,36);
X OP(A,B,C,D, 1, 4,37);OP(D,A,B,C, 4,11,38);OP(C,D,A,B, 7,16,39);OP(B,C,D,A,10,23,40);
X OP(A,B,C,D,13, 4,41);OP(D,A,B,C, 0,11,42);OP(C,D,A,B, 3,16,43);OP(B,C,D,A, 6,23,44);
X OP(A,B,C,D, 9, 4,45);OP(D,A,B,C,12,11,46);OP(C,D,A,B,15,16,47);OP(B,C,D,A, 2,23,48);
X#undef OP
X#define OP(a,b,c,d,k,s,i) a = b + ROTLEFT(a+I(b,c,d)+X[k]+T[i-1],s)
X OP(A,B,C,D, 0, 6,49);OP(D,A,B,C, 7,10,50);OP(C,D,A,B,14,15,51);OP(B,C,D,A, 5,21,52);
X OP(A,B,C,D,12, 6,53);OP(D,A,B,C, 3,10,54);OP(C,D,A,B,10,15,55);OP(B,C,D,A, 1,21,56);
X OP(A,B,C,D, 8, 6,57);OP(D,A,B,C,15,10,58);OP(C,D,A,B, 6,15,59);OP(B,C,D,A,13,21,60);
X OP(A,B,C,D, 4, 6,61);OP(D,A,B,C,11,10,62);OP(C,D,A,B, 2,15,63);OP(B,C,D,A, 9,21,64);
X#undef OP
X state->A += LIMIT32(A);
X state->B += LIMIT32(B);
X state->C += LIMIT32(C);
X state->D += LIMIT32(D);
X}
X
Xstatic void crunch_bytes(STATE *state, const unsigned char *buf, unsigned int nbytes)
X{
X int xfill;
X U32 *X;
X
X xfill = state->xfill;
X X = &state->X[0];
X for (;nbytes>0;nbytes--)
X  { switch (xfill % 4)
X     { case 0:
X         X[xfill/4] = *buf;
X         break;
X       case 1:
X         X[xfill/4] |= ((U32)*buf) << 8;
X         break;
X       case 2:
X         X[xfill/4] |= ((U32)*buf) << 16;
X         break;
X       case 3:
X         X[xfill/4] |= ((U32)*buf) << 24;
X         break;
X     }
X    buf ++;
X    xfill ++;
X    if (xfill >= 64)
X     { crunch_block(state);
X       xfill = 0;
X     }
X  }
X state->xfill = xfill;
X}
X
Xvoid *md5_init(void)
X{
X STATE *s;
X
X s = malloc(sizeof(STATE));
X if (s == 0) return(0);
X s->A = 0x67452301;
X s->B = 0xefcdab89;
X s->C = 0x98badcfe;
X s->D = 0x10325476;
X s->xfill = 0;
X s->bitlen_l = 0;
X s->bitlen_h = 0;
X return(s);
X}
X
Xvoid md5_process_bytes(void *state, const void *vbuf, unsigned int nbytes)
X#define s ((STATE *)state)
X{
X U32 ltmp;
X U32 lsum;
X
X crunch_bytes(s,vbuf,nbytes);
X s->bitlen_h += ((U32)nbytes) >> 29;
X ltmp = ((U32)nbytes) << 3;
X lsum = ltmp + s->bitlen_l;
X if ( (ltmp & s->bitlen_l & 0x80000000) ||
X      ( ((ltmp|s->bitlen_l) & 0x80000000) &&
X       !(lsum & 0x80000000) ) )
X  { s->bitlen_h ++;
X  }
X s->bitlen_l = lsum;
X#undef s
X}
X
Xvoid md5_result(void *state, unsigned char *result)
X#define s ((STATE *)state)
X{
X unsigned char lenbytes[8];
X
X crunch_bytes(s,(const void *)"\200",1);
X while (s->xfill != 56) crunch_bytes(s,(const void *)"\0",1);
X lenbytes[0] =  s->bitlen_l        & 0xff;
X lenbytes[1] = (s->bitlen_l >>  8) & 0xff;
X lenbytes[2] = (s->bitlen_l >> 16) & 0xff;
X lenbytes[3] = (s->bitlen_l >> 24) & 0xff;
X lenbytes[4] =  s->bitlen_h        & 0xff;
X lenbytes[5] = (s->bitlen_h >>  8) & 0xff;
X lenbytes[6] = (s->bitlen_h >> 16) & 0xff;
X lenbytes[7] = (s->bitlen_h >> 24) & 0xff;
X crunch_bytes(s,&lenbytes[0],8);
X result[ 0] =  s->A        & 0xff;
X result[ 1] = (s->A >>  8) & 0xff;
X result[ 2] = (s->A >> 16) & 0xff;
X result[ 3] = (s->A >> 24) & 0xff;
X result[ 4] =  s->B        & 0xff;
X result[ 5] = (s->B >>  8) & 0xff;
X result[ 6] = (s->B >> 16) & 0xff;
X result[ 7] = (s->B >> 24) & 0xff;
X result[ 8] =  s->C        & 0xff;
X result[ 9] = (s->C >>  8) & 0xff;
X result[10] = (s->C >> 16) & 0xff;
X result[11] = (s->C >> 24) & 0xff;
X result[12] =  s->D        & 0xff;
X result[13] = (s->D >>  8) & 0xff;
X result[14] = (s->D >> 16) & 0xff;
X result[15] = (s->D >> 24) & 0xff;
X free(s);
X}
EOF
if test 5767 -ne "`wc -c md5.c`"
then
echo shar: error transmitting md5.c \(should have been 5767 characters\)
fi
echo x - md5.h \(204 characters\)
sed 's/^X//' > md5.h << \EOF
X#ifndef _MD5_H_8322150d_
X#define _MD5_H_8322150d_
X
Xextern void *md5_init(void);
Xextern void md5_process_bytes(void *, const void *, unsigned int);
Xextern void md5_result(void *, unsigned char *);
X
X#endif
EOF
if test 204 -ne "`wc -c md5.h`"
then
echo shar: error transmitting md5.h \(should have been 204 characters\)
fi
echo x - signaltype.h \(907 characters\)
sed 's/^X//' > signaltype.h << \EOF
X#ifndef _SIGNALTYPE_H_bb667591_
X#define _SIGNALTYPE_H_bb667591_
X
X/* signaltype is the type returned by a signal handler.  The modern way
X   is for this to be "void", but some older systems still use "int". */
X
Xtypedef void signaltype;
X/* typedef int signaltype; */
X
X/* SIGNALHANDLERDEF defines a signal handler; SIGNALHANDLERREF declares one.
X   The modern way is to use prototypes; pre-prototype systems need to use
X   the non-prototype versions.  Some systems may need to change the
X   prototypes; unfortunately when the argument pattern to a signal handler
X   isn't just one int, I see no good way to make code using the prototype
X   versions portable. */
X
X#define SIGNALHANDLERDEF(name,sig) signaltype name(int sig)
X/* #define SIGNALHANDLERDEF(name,sig) signaltype name(sig) int sig; */
X
X#define SIGNALHANDLERREF(name) signaltype name(int)
X/* #define SIGNALHANDLERREF(name) signaltype name() */
X
X#endif
EOF
if test 907 -ne "`wc -c signaltype.h`"
then
echo shar: error transmitting signaltype.h \(should have been 907 characters\)
fi
echo x - syscalls.h \(0 characters\)
sed 's/^X//' > syscalls.h << \EOF
EOF
if test 0 -ne "`wc -c syscalls.h`"
then
echo shar: error transmitting syscalls.h \(should have been 0 characters\)
fi
exit 0
# end of shell archive



Current thread: