OpenWrt – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* Add passphrases to the tpasswd file. Use the last entry in the config
2 file by default or a particular one specified by index. */
3  
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include "config.h"
11 #include "t_pwd.h"
12 #include "t_read.h"
13 #include "t_sha.h"
14 #include "t_defines.h"
15  
16 char *Progname;
17 char Usage[] = "usage: %s [-n configindex] [-p passfile] user\n";
18 #define USAGE() fprintf(stderr, Usage, Progname)
19  
20 void doit(char *);
21  
22 int Configindex = -1;
23 char *Passfile = DEFAULT_PASSWD;
24  
25 int main(int argc, char **argv)
26 {
27 int c;
28  
29 Progname = *argv;
30  
31 /* Parse option arguments. */
32  
33 while ((c = getopt(argc, argv, "n:p:")) != EOF) {
34 switch (c) {
35  
36 case 'n':
37 Configindex = atoi(optarg);
38 break;
39  
40 case 'p':
41 Passfile = optarg;
42 break;
43  
44 default:
45 USAGE();
46 exit(1);
47 }
48 }
49 argc -= optind;
50 argv += optind;
51  
52 if (argc != 1) {
53 USAGE();
54 exit(1);
55 }
56 doit(argv[0]);
57  
58 return 0;
59 }
60  
61 void doit(char *name)
62 {
63 char passphrase[128], passphrase1[128];
64 FILE *f;
65 struct t_confent *tcent;
66 struct t_pw eps_passwd;
67  
68 /* Get the config entry. */
69  
70 if (Configindex <= 0) {
71 Configindex = t_getprecount();
72 }
73 tcent = gettcid(Configindex);
74 if (tcent == NULL) {
75 fprintf(stderr, "Invalid configuration file entry.\n");
76 exit(1);
77 }
78  
79 /* Ask for the passphrase twice. */
80  
81 printf("Setting passphrase for %s\n", name);
82  
83 if (t_getpass(passphrase, sizeof(passphrase), "Enter passphrase: ") < 0) {
84 exit(1);
85 }
86 if (t_getpass(passphrase1, sizeof(passphrase1), "Verify: ") < 0) {
87 exit(1);
88 }
89 if (strcmp(passphrase, passphrase1) != 0) {
90 fprintf(stderr, "mismatch\n");
91 exit(1);
92 }
93  
94 /* Create the passphrase verifier. */
95  
96 t_makepwent(&eps_passwd, name, passphrase, NULL, tcent);
97  
98 /* Don't need these anymore. */
99  
100 memset(passphrase, 0, sizeof(passphrase));
101 memset(passphrase1, 0, sizeof(passphrase1));
102  
103 /* See if the passphrase file is there; create it if not. */
104  
105 if ((f = fopen(Passfile, "r+")) == NULL) {
106 creat(Passfile, 0400);
107 } else {
108 fclose(f);
109 }
110  
111 /* Change the passphrase. */
112  
113 if (t_changepw(Passfile, &eps_passwd.pebuf) < 0) {
114 fprintf(stderr, "Error changing passphrase\n");
115 exit(1);
116 }
117 }
118  
119 /* TODO: Implement a more general method to handle delete/change */
120  
121 _TYPE( int )
122 t_changepw(pwname, diff)
123 const char * pwname;
124 const struct t_pwent * diff;
125 {
126 char * bakfile;
127 char * bakfile2;
128 struct stat st;
129 FILE * passfp;
130 FILE * bakfp;
131  
132 if(pwname == NULL)
133 pwname = DEFAULT_PASSWD;
134  
135 if((passfp = fopen(pwname, "rb")) == NULL || fstat(fileno(passfp), &st) < 0)
136 return -1;
137  
138 if((bakfile = malloc(strlen(pwname) + 5)) == NULL) {
139 fclose(passfp);
140 return -1;
141 }
142 else if((bakfile2 = malloc(strlen(pwname) + 5)) == NULL) {
143 fclose(passfp);
144 free(bakfile);
145 return -1;
146 }
147  
148 sprintf(bakfile, "%s.bak", pwname);
149 sprintf(bakfile2, "%s.sav", pwname);
150  
151 if((bakfp = fopen(bakfile2, "wb")) == NULL &&
152 (unlink(bakfile2) < 0 || (bakfp = fopen(bakfile2, "wb")) == NULL)) {
153 fclose(passfp);
154 free(bakfile);
155 free(bakfile2);
156 return -1;
157 }
158  
159 #ifdef NO_FCHMOD
160 chmod(bakfile2, st.st_mode & 0777);
161 #else
162 fchmod(fileno(bakfp), st.st_mode & 0777);
163 #endif
164  
165 t_pwcopy(bakfp, passfp, diff);
166  
167 fclose(bakfp);
168 fclose(passfp);
169  
170 #ifdef USE_RENAME
171 unlink(bakfile);
172 if(rename(pwname, bakfile) < 0) {
173 free(bakfile);
174 free(bakfile2);
175 return -1;
176 }
177 if(rename(bakfile2, pwname) < 0) {
178 free(bakfile);
179 free(bakfile2);
180 return -1;
181 }
182 #else
183 unlink(bakfile);
184 link(pwname, bakfile);
185 unlink(pwname);
186 link(bakfile2, pwname);
187 unlink(bakfile2);
188 #endif
189 free(bakfile);
190 free(bakfile2);
191  
192 return 0;
193 }
194  
195 _TYPE( struct t_pwent * )
196 t_makepwent(tpw, user, pass, salt, confent)
197 struct t_pw * tpw;
198 const char * user;
199 const char * pass;
200 const struct t_num * salt;
201 const struct t_confent * confent;
202 {
203 BigInteger x, v, n, g;
204 unsigned char dig[SHA_DIGESTSIZE];
205 SHA1_CTX ctxt;
206  
207 tpw->pebuf.name = tpw->userbuf;
208 tpw->pebuf.password.data = tpw->pwbuf;
209 tpw->pebuf.salt.data = tpw->saltbuf;
210  
211 strncpy(tpw->pebuf.name, user, MAXUSERLEN);
212 tpw->pebuf.index = confent->index;
213  
214 if(salt) {
215 tpw->pebuf.salt.len = salt->len;
216 memcpy(tpw->pebuf.salt.data, salt->data, salt->len);
217 }
218 else {
219 memset(dig, 0, SALTLEN); /* salt is 80 bits */
220 tpw->pebuf.salt.len = SALTLEN;
221 do {
222 t_random(tpw->pebuf.salt.data, SALTLEN);
223 } while(memcmp(tpw->pebuf.salt.data, dig, SALTLEN) == 0);
224 if(tpw->pebuf.salt.data[0] == 0)
225 tpw->pebuf.salt.data[0] = 0xff;
226 }
227  
228 n = BigIntegerFromBytes(confent->modulus.data, confent->modulus.len);
229 g = BigIntegerFromBytes(confent->generator.data, confent->generator.len);
230 v = BigIntegerFromInt(0);
231  
232 SHA1Init(&ctxt);
233 SHA1Update(&ctxt, user, strlen(user));
234 SHA1Update(&ctxt, ":", 1);
235 SHA1Update(&ctxt, pass, strlen(pass));
236 SHA1Final(dig, &ctxt);
237  
238 SHA1Init(&ctxt);
239 SHA1Update(&ctxt, tpw->pebuf.salt.data, tpw->pebuf.salt.len);
240 SHA1Update(&ctxt, dig, sizeof(dig));
241 SHA1Final(dig, &ctxt);
242  
243 /* x = H(s, H(u, ':', p)) */
244 x = BigIntegerFromBytes(dig, sizeof(dig));
245  
246 BigIntegerModExp(v, g, x, n);
247 tpw->pebuf.password.len = BigIntegerToBytes(v, tpw->pebuf.password.data);
248  
249 BigIntegerFree(v);
250 BigIntegerFree(x);
251 BigIntegerFree(g);
252 BigIntegerFree(n);
253  
254 return &tpw->pebuf;
255 }
256  
257 int
258 t_pwcopy(pwdest, pwsrc, diff)
259 FILE * pwdest;
260 FILE * pwsrc;
261 struct t_pwent * diff;
262 {
263 struct t_pw * src;
264 struct t_pwent * ent;
265  
266 if((src = t_openpw(pwsrc)) == NULL)
267 return -1;
268  
269 while((ent = t_getpwent(src)) != NULL)
270 if(diff && strcmp(diff->name, ent->name) == 0) {
271 t_putpwent(diff, pwdest);
272 diff = NULL;
273 }
274 else
275 t_putpwent(ent, pwdest);
276  
277 if(diff)
278 t_putpwent(diff, pwdest);
279  
280 return 0;
281 }
282  
283 _TYPE( struct t_pwent * )
284 t_getpwent(tpw)
285 struct t_pw * tpw;
286 {
287 char indexbuf[16];
288 char passbuf[MAXB64PARAMLEN];
289 char saltstr[MAXB64SALTLEN];
290  
291 #ifdef ENABLE_YP
292 struct t_passwd * nisent;
293 /* FIXME: should tell caller to get conf entry from NIS also */
294  
295 if(tpw->state == IN_NIS) {
296 nisent = _yp_gettpent();
297 if(nisent != NULL) {
298 savepwent(tpw, &nisent->tp);
299 return &tpw->pebuf;
300 }
301 tpw->state = FILE_NIS;
302 }
303 #endif
304  
305 while(1) {
306 if(t_nextfield(tpw->instream, tpw->userbuf, MAXUSERLEN) > 0) {
307 #ifdef ENABLE_YP
308 if(tpw->state == FILE_NIS && *tpw->userbuf == '+') {
309 t_nextline(tpw->instream);
310 if(strlen(tpw->userbuf) > 1) { /* +name:... */
311 nisent = _yp_gettpnam(tpw->userbuf + 1);
312 if(nisent != NULL) {
313 savepwent(tpw, nisent);
314 return &tpw->pebuf;
315 }
316 }
317 else { /* +:... */
318 tpw->state = IN_NIS;
319 _yp_settpent();
320 return t_getpwent(tpw);
321 }
322 }
323 #endif
324 if(t_nextfield(tpw->instream, passbuf, MAXB64PARAMLEN) > 0 &&
325 (tpw->pebuf.password.len = t_fromb64(tpw->pwbuf, passbuf)) > 0 &&
326 t_nextfield(tpw->instream, saltstr, MAXB64SALTLEN) > 0 &&
327 (tpw->pebuf.salt.len = t_fromb64(tpw->saltbuf, saltstr)) > 0 &&
328 t_nextfield(tpw->instream, indexbuf, 16) > 0 &&
329 (tpw->pebuf.index = atoi(indexbuf)) > 0) {
330 tpw->pebuf.name = tpw->userbuf;
331 tpw->pebuf.password.data = tpw->pwbuf;
332 tpw->pebuf.salt.data = tpw->saltbuf;
333 t_nextline(tpw->instream);
334 return &tpw->pebuf;
335 }
336 }
337 if(t_nextline(tpw->instream) < 0)
338 return NULL;
339 }
340 }
341  
342 _TYPE( void )
343 t_putpwent(ent, fp)
344 const struct t_pwent * ent;
345 FILE * fp;
346 {
347 char strbuf[MAXB64PARAMLEN];
348 char saltbuf[MAXB64SALTLEN];
349  
350 fprintf(fp, "%s:%s:%s:%d\n", ent->name,
351 t_tob64(strbuf, ent->password.data, ent->password.len),
352 t_tob64(saltbuf, ent->salt.data, ent->salt.len), ent->index);
353 }
354