kernel: fq_codel: dont reinit flow state
[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