[package] opkg: fallback to dest->root_dir if specified overlay_root does not exist...
[openwrt.git] / package / ead / src / tinysrp / tphrase.c
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_conf *tc;
66 struct t_confent *tcent;
67 struct t_pw eps_passwd;
68
69 /* Get the config entry. */
70
71 if (Configindex <= 0) {
72 Configindex = t_getprecount();
73 }
74 tcent = gettcid(Configindex);
75 if (tcent == NULL) {
76 fprintf(stderr, "Invalid configuration file entry.\n");
77 exit(1);
78 }
79
80 /* Ask for the passphrase twice. */
81
82 printf("Setting passphrase for %s\n", name);
83
84 if (t_getpass(passphrase, sizeof(passphrase), "Enter passphrase: ") < 0) {
85 exit(1);
86 }
87 if (t_getpass(passphrase1, sizeof(passphrase1), "Verify: ") < 0) {
88 exit(1);
89 }
90 if (strcmp(passphrase, passphrase1) != 0) {
91 fprintf(stderr, "mismatch\n");
92 exit(1);
93 }
94
95 /* Create the passphrase verifier. */
96
97 t_makepwent(&eps_passwd, name, passphrase, NULL, tcent);
98
99 /* Don't need these anymore. */
100
101 memset(passphrase, 0, sizeof(passphrase));
102 memset(passphrase1, 0, sizeof(passphrase1));
103
104 /* See if the passphrase file is there; create it if not. */
105
106 if ((f = fopen(Passfile, "r+")) == NULL) {
107 creat(Passfile, 0400);
108 } else {
109 fclose(f);
110 }
111
112 /* Change the passphrase. */
113
114 if (t_changepw(Passfile, &eps_passwd.pebuf) < 0) {
115 fprintf(stderr, "Error changing passphrase\n");
116 exit(1);
117 }
118 }
119
120 /* TODO: Implement a more general method to handle delete/change */
121
122 _TYPE( int )
123 t_changepw(pwname, diff)
124 const char * pwname;
125 const struct t_pwent * diff;
126 {
127 char * bakfile;
128 char * bakfile2;
129 struct stat st;
130 FILE * passfp;
131 FILE * bakfp;
132
133 if(pwname == NULL)
134 pwname = DEFAULT_PASSWD;
135
136 if((passfp = fopen(pwname, "rb")) == NULL || fstat(fileno(passfp), &st) < 0)
137 return -1;
138
139 if((bakfile = malloc(strlen(pwname) + 5)) == NULL) {
140 fclose(passfp);
141 return -1;
142 }
143 else if((bakfile2 = malloc(strlen(pwname) + 5)) == NULL) {
144 fclose(passfp);
145 free(bakfile);
146 return -1;
147 }
148
149 sprintf(bakfile, "%s.bak", pwname);
150 sprintf(bakfile2, "%s.sav", pwname);
151
152 if((bakfp = fopen(bakfile2, "wb")) == NULL &&
153 (unlink(bakfile2) < 0 || (bakfp = fopen(bakfile2, "wb")) == NULL)) {
154 fclose(passfp);
155 fclose(bakfp);
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 return -1;
174 if(rename(bakfile2, pwname) < 0)
175 return -1;
176 #else
177 unlink(bakfile);
178 link(pwname, bakfile);
179 unlink(pwname);
180 link(bakfile2, pwname);
181 unlink(bakfile2);
182 #endif
183 free(bakfile);
184 free(bakfile2);
185
186 return 0;
187 }
188
189 _TYPE( struct t_pwent * )
190 t_makepwent(tpw, user, pass, salt, confent)
191 struct t_pw * tpw;
192 const char * user;
193 const char * pass;
194 const struct t_num * salt;
195 const struct t_confent * confent;
196 {
197 BigInteger x, v, n, g;
198 unsigned char dig[SHA_DIGESTSIZE];
199 SHA1_CTX ctxt;
200
201 tpw->pebuf.name = tpw->userbuf;
202 tpw->pebuf.password.data = tpw->pwbuf;
203 tpw->pebuf.salt.data = tpw->saltbuf;
204
205 strncpy(tpw->pebuf.name, user, MAXUSERLEN);
206 tpw->pebuf.index = confent->index;
207
208 if(salt) {
209 tpw->pebuf.salt.len = salt->len;
210 memcpy(tpw->pebuf.salt.data, salt->data, salt->len);
211 }
212 else {
213 memset(dig, 0, SALTLEN); /* salt is 80 bits */
214 tpw->pebuf.salt.len = SALTLEN;
215 do {
216 t_random(tpw->pebuf.salt.data, SALTLEN);
217 } while(memcmp(tpw->pebuf.salt.data, dig, SALTLEN) == 0);
218 if(tpw->pebuf.salt.data[0] == 0)
219 tpw->pebuf.salt.data[0] = 0xff;
220 }
221
222 n = BigIntegerFromBytes(confent->modulus.data, confent->modulus.len);
223 g = BigIntegerFromBytes(confent->generator.data, confent->generator.len);
224 v = BigIntegerFromInt(0);
225
226 SHA1Init(&ctxt);
227 SHA1Update(&ctxt, user, strlen(user));
228 SHA1Update(&ctxt, ":", 1);
229 SHA1Update(&ctxt, pass, strlen(pass));
230 SHA1Final(dig, &ctxt);
231
232 SHA1Init(&ctxt);
233 SHA1Update(&ctxt, tpw->pebuf.salt.data, tpw->pebuf.salt.len);
234 SHA1Update(&ctxt, dig, sizeof(dig));
235 SHA1Final(dig, &ctxt);
236
237 /* x = H(s, H(u, ':', p)) */
238 x = BigIntegerFromBytes(dig, sizeof(dig));
239
240 BigIntegerModExp(v, g, x, n);
241 tpw->pebuf.password.len = BigIntegerToBytes(v, tpw->pebuf.password.data);
242
243 BigIntegerFree(v);
244 BigIntegerFree(x);
245 BigIntegerFree(g);
246 BigIntegerFree(n);
247
248 return &tpw->pebuf;
249 }
250
251 int
252 t_pwcopy(pwdest, pwsrc, diff)
253 FILE * pwdest;
254 FILE * pwsrc;
255 struct t_pwent * diff;
256 {
257 struct t_pw * src;
258 struct t_pwent * ent;
259
260 if((src = t_openpw(pwsrc)) == NULL)
261 return -1;
262
263 while((ent = t_getpwent(src)) != NULL)
264 if(diff && strcmp(diff->name, ent->name) == 0) {
265 t_putpwent(diff, pwdest);
266 diff = NULL;
267 }
268 else
269 t_putpwent(ent, pwdest);
270
271 if(diff)
272 t_putpwent(diff, pwdest);
273
274 return 0;
275 }
276
277 _TYPE( struct t_pwent * )
278 t_getpwent(tpw)
279 struct t_pw * tpw;
280 {
281 char indexbuf[16];
282 char passbuf[MAXB64PARAMLEN];
283 char saltstr[MAXB64SALTLEN];
284
285 #ifdef ENABLE_YP
286 struct t_passwd * nisent;
287 /* FIXME: should tell caller to get conf entry from NIS also */
288
289 if(tpw->state == IN_NIS) {
290 nisent = _yp_gettpent();
291 if(nisent != NULL) {
292 savepwent(tpw, &nisent->tp);
293 return &tpw->pebuf;
294 }
295 tpw->state = FILE_NIS;
296 }
297 #endif
298
299 while(1) {
300 if(t_nextfield(tpw->instream, tpw->userbuf, MAXUSERLEN) > 0) {
301 #ifdef ENABLE_YP
302 if(tpw->state == FILE_NIS && *tpw->userbuf == '+') {
303 t_nextline(tpw->instream);
304 if(strlen(tpw->userbuf) > 1) { /* +name:... */
305 nisent = _yp_gettpnam(tpw->userbuf + 1);
306 if(nisent != NULL) {
307 savepwent(tpw, nisent);
308 return &tpw->pebuf;
309 }
310 }
311 else { /* +:... */
312 tpw->state = IN_NIS;
313 _yp_settpent();
314 return t_getpwent(tpw);
315 }
316 }
317 #endif
318 if(t_nextfield(tpw->instream, passbuf, MAXB64PARAMLEN) > 0 &&
319 (tpw->pebuf.password.len = t_fromb64(tpw->pwbuf, passbuf)) > 0 &&
320 t_nextfield(tpw->instream, saltstr, MAXB64SALTLEN) > 0 &&
321 (tpw->pebuf.salt.len = t_fromb64(tpw->saltbuf, saltstr)) > 0 &&
322 t_nextfield(tpw->instream, indexbuf, 16) > 0 &&
323 (tpw->pebuf.index = atoi(indexbuf)) > 0) {
324 tpw->pebuf.name = tpw->userbuf;
325 tpw->pebuf.password.data = tpw->pwbuf;
326 tpw->pebuf.salt.data = tpw->saltbuf;
327 t_nextline(tpw->instream);
328 return &tpw->pebuf;
329 }
330 }
331 if(t_nextline(tpw->instream) < 0)
332 return NULL;
333 }
334 }
335
336 _TYPE( void )
337 t_putpwent(ent, fp)
338 const struct t_pwent * ent;
339 FILE * fp;
340 {
341 char strbuf[MAXB64PARAMLEN];
342 char saltbuf[MAXB64SALTLEN];
343
344 fprintf(fp, "%s:%s:%s:%d\n", ent->name,
345 t_tob64(strbuf, ent->password.data, ent->password.len),
346 t_tob64(saltbuf, ent->salt.data, ent->salt.len), ent->index);
347 }
348
This page took 0.093353 seconds and 5 git commands to generate.