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