crypt.c

Go to the documentation of this file.
00001 /*      crypt() - one-way password encryption function  Author: Kees J. Bot
00002  *                                                              7 Feb 1994
00003  * This routine does not encrypt anything, it uses the pwdauth
00004  * program to do the hard work.
00005  */
00006 #define nil ((void*)0)
00007 #define pipe _pipe
00008 #define fork _fork
00009 #define close _close
00010 #define dup2 _dup2
00011 #define execl _execl
00012 #define read _read
00013 #define _exit __exit
00014 #define write _write
00015 #define waitpid _waitpid
00016 #include <sys/types.h>
00017 #include <unistd.h>
00018 #include <string.h>
00019 #include <stdio.h>
00020 #include <errno.h>
00021 #include <stdarg.h>
00022 #include <sys/wait.h>
00023 
00024 /* Set-uid root program to read /etc/shadow or encrypt passwords. */
00025 static char PWDAUTH[] = "/usr/lib/pwdauth";
00026 #define LEN     1024
00027 
00028 static void tell(const char *s0, ...)
00029 {
00030         va_list ap;
00031         const char *s;
00032 
00033         va_start(ap, s0);
00034         s= s0;
00035         while (s != nil) {
00036                 (void) write(2, s, strlen(s));
00037                 s= va_arg(ap, const char *);
00038         }
00039         va_end(ap);
00040 }
00041 
00042 char *crypt(const char *key, const char *salt)
00043 {
00044         pid_t pid;
00045         int status;
00046         int pfd[2];
00047         static char pwdata[LEN];
00048         char *p= pwdata;
00049         const char *k= key;
00050         const char *s= salt;
00051         int n;
00052 
00053         /* Fill pwdata[] with the key and salt. */
00054         while ((*p++ = *k++) != 0) if (p == pwdata+LEN-1) goto fail;
00055         while ((*p++ = *s++) != 0) if (p == pwdata+LEN-0) goto fail;
00056 
00057         if (pipe(pfd) < 0) goto fail;
00058 
00059         /* Prefill the pipe. */
00060         (void) write(pfd[1], pwdata, p - pwdata);
00061 
00062         switch ((pid= fork())) {
00063         case -1:
00064                 close(pfd[0]);
00065                 close(pfd[1]);
00066                 goto fail;
00067         case 0:
00068                 /* Connect both input and output to the pipe. */
00069                 if (pfd[0] != 0) {
00070                         dup2(pfd[0], 0);
00071                         close(pfd[0]);
00072                 }
00073                 if (pfd[1] != 1) {
00074                         dup2(pfd[1], 1);
00075                         close(pfd[1]);
00076                 }
00077 
00078                 execl(PWDAUTH, PWDAUTH, (char *) nil);
00079 
00080                 tell("crypt(): ", PWDAUTH, ": ", strerror(errno), "\r\n",
00081                                                                 (char *) nil);
00082                 /* No pwdauth?  Fail! */
00083                 (void) read(0, pwdata, LEN);
00084                 _exit(1);
00085         }
00086         close(pfd[1]);
00087 
00088         status= -1;
00089         while (waitpid(pid, &status, 0) == -1 && errno == EINTR) {}
00090         if (status != 0) {
00091                 close(pfd[0]);
00092                 goto fail;
00093         }
00094 
00095         /* Read and return the result.  Check if it contains exactly one
00096          * string.
00097          */
00098         n= read(pfd[0], pwdata, LEN);
00099         close(pfd[0]);
00100         if (n < 0) goto fail;
00101         p = pwdata + n;
00102         n = 0;
00103         while (p > pwdata) if (*--p == 0) n++;
00104         if (n != 1) goto fail;
00105         return pwdata;
00106 
00107 fail:
00108         pwdata[0] = salt[0] ^ 1;                /* make result != salt */
00109         pwdata[1] = 0;
00110         return pwdata;
00111 }
00112 
00113 /*
00114  * $PchId: crypt.c,v 1.5 1996/04/11 07:46:11 philip Exp $
00115  */

Generated on Fri Apr 14 22:57:26 2006 for minix by  doxygen 1.4.6