1 /* pwcmp/client.c - Password comparison client library
2  * Copyright (C) 2001  Bruce Guenter <bruce@untroubled.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/wait.h>
21 #include <unistd.h>
22 #include "sysdeps.h"
23 
24 #include "client.h"
25 
26 typedef int (*pwcmpfn)(const char*, const char*);
27 
28 static long pid;
29 static int fd0;
30 static int fd1;
31 static pwcmpfn cmpfn;
32 
33 
pwcmp_plain(const char * plaintext,const char * encoded)34 static int pwcmp_plain(const char* plaintext, const char* encoded)
35 {
36   return strcmp(plaintext, encoded) == 0 ? 0 : 1;
37 }
38 
pwcmp_crypt(const char * plaintext,const char * encoded)39 static int pwcmp_crypt(const char* plaintext, const char* encoded)
40 {
41   extern char* crypt(const char* key, const char* salt);
42   plaintext = crypt(plaintext, encoded);
43   return pwcmp_plain(plaintext, encoded);
44 }
45 
rwrite(int fd,const char * buf,unsigned long len)46 static int rwrite(int fd, const char* buf, unsigned long len)
47 {
48   while (len > 0) {
49     unsigned long wr = write(fd, buf, len);
50     if (wr == (unsigned long)-1) return 0;
51     len -= wr;
52     buf += wr;
53   }
54   return 1;
55 }
56 
pwcmp_pipe(const char * plaintext,const char * encoded)57 static int pwcmp_pipe(const char* plaintext, const char* encoded)
58 {
59   char buf[1];
60   if (!rwrite(fd0, plaintext, strlen(plaintext)+1)) return -1;
61   if (!rwrite(fd0, encoded, strlen(encoded)+1)) return -1;
62   if (read(fd1, buf, 1) != 1) return -1;
63   return buf[0] == 0 ? 0 : 1;
64 }
65 
pwcmp_start_pipe(const char * module)66 static int pwcmp_start_pipe(const char* module)
67 {
68   int pipe0[2];
69   int pipe1[2];
70   if (pipe(pipe0) == -1) return 0;
71   if (pipe(pipe1) == -1) { close(pipe0[0]); close(pipe0[1]); return 0; }
72   if ((pid = fork()) == -1) {
73     close(pipe0[0]); close(pipe0[1]);
74     close(pipe1[0]); close(pipe1[1]);
75     return 0;
76   }
77   if (pid == 0) {
78     close(0);
79     dup2(pipe0[0], 0);
80     close(1);
81     dup2(pipe1[1], 1);
82     close(pipe0[0]); close(pipe0[1]);
83     close(pipe1[0]); close(pipe1[1]);
84     execlp(module, module, NULL);
85     _exit(1);
86   }
87   else {
88     close(pipe0[0]); fd0 = pipe0[1];
89     close(pipe1[1]); fd1 = pipe1[0];
90   }
91   return 1;
92 }
93 
pwcmp_start(const char * module)94 int pwcmp_start(const char* module)
95 {
96   if (!module || module[0] == 0 || strcmp(module, "plain") == 0)
97     cmpfn = pwcmp_plain;
98   else if (strcmp(module, "crypt") == 0)
99     cmpfn = pwcmp_crypt;
100   else {
101     cmpfn = pwcmp_pipe;
102     if (!pwcmp_start_pipe(module)) return 0;
103   }
104   return 1;
105 }
106 
pwcmp_check(const char * plaintext,const char * encoded)107 int pwcmp_check(const char* plaintext, const char* encoded)
108 {
109   if (!cmpfn) return -1;
110   return cmpfn(plaintext, encoded);
111 }
112 
pwcmp_stop(void)113 void pwcmp_stop(void)
114 {
115   if (cmpfn == pwcmp_pipe) {
116     close(fd0);
117     close(fd1);
118     waitpid(pid, 0, WUNTRACED);
119   }
120   cmpfn = 0;
121 }
122