/[pkg-mixmaster]/trunk/Mix/Src/keymgt.c
ViewVC logotype

Contents of /trunk/Mix/Src/keymgt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 448 - (hide annotations) (download)
Fri Dec 27 20:43:41 2002 UTC (10 years, 4 months ago) by rabbi
File MIME type: text/plain
File size: 11118 byte(s)
Added missing newline characters.
1 rabbi 1 /* Mixmaster version 3 -- (C) 1999 Anonymizer Inc.
2    
3     Mixmaster may be redistributed and modified under certain conditions.
4     This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5     ANY KIND, either express or implied. See the file COPYRIGHT for
6     details.
7    
8     Key management
9 rabbi 448 $Id: keymgt.c,v 1.22 2002/12/27 20:43:40 rabbi Exp $ */
10 rabbi 1
11    
12     #include "mix3.h"
13     #include <string.h>
14 weaselp 214 #include <time.h>
15 rabbi 1 #include <assert.h>
16    
17 rabbi 186 int getv2seckey(byte keyid[], BUFFER *key);
18 rabbi 1 static int getv3seckey(byte keyid[], BUFFER *key);
19     static int getv2pubkey(byte keyid[], BUFFER *key);
20     static int getv3pubkey(byte keyid[], BUFFER *key);
21    
22     int db_getseckey(byte keyid[], BUFFER *key)
23     {
24     if (getv3seckey(keyid, key) == -1 && getv2seckey(keyid, key) == -1)
25     return (-1);
26     else
27     return (0);
28     }
29    
30     int db_getpubkey(byte keyid[], BUFFER *key)
31     {
32     if (getv3pubkey(keyid, key) == -1 && getv2pubkey(keyid, key) == -1)
33     return (-1);
34     else
35     return (0);
36     }
37    
38     static int getv3seckey(byte keyid[], BUFFER *key)
39     {
40     return -1; /* XXX */
41     }
42    
43     static int getv3pubkey(byte keyid[], BUFFER *key)
44     {
45     return -1; /* XXX */
46     }
47    
48     #ifdef USE_RSA
49 rabbi 186 /* now accepts NULL keyid too, with NULL keyid any key
50     * will be matched, with valid passphrase of course */
51     int getv2seckey(byte keyid[], BUFFER *key)
52 rabbi 1 {
53     FILE *keyring;
54     BUFFER *iv, *pass, *temp;
55     char idstr[33];
56     char line[LINELEN];
57 rabbi 186 int err = -1;
58 weaselp 214 char *res;
59     time_t created, expires;
60 rabbi 1
61     pass = buf_new();
62     iv = buf_new();
63     temp = buf_new();
64 rabbi 186 if (keyid)
65     id_encode(keyid, idstr);
66     else
67     idstr[0] = 0;
68 rabbi 1 strcat(idstr, "\n");
69     if ((keyring = mix_openfile(SECRING, "r")) == NULL) {
70     errlog(ERRORMSG, "No secret key file!\n");
71 weaselp 195 } else {
72     while (err == -1) {
73     buf_clear(key);
74 rabbi 1 if (fgets(line, sizeof(line), keyring) == NULL)
75     break;
76 weaselp 195 if (strleft(line, begin_key)) {
77 weaselp 214 expires = 0;
78     created = 0;
79     do {
80     res = fgets(line, sizeof(line), keyring);
81     if (strileft(line, "created:")) {
82     created = parse_yearmonthday(strchr(line, ':')+1);
83     if (created == -1)
84     created = 0;
85     } else if (strileft(line, "expires:")) {
86     expires = parse_yearmonthday(strchr(line, ':')+1);
87     if (expires == -1)
88     expires = 0;
89     }
90     /* Fetch lines until we fail or get a non-header line */
91     } while ( res != NULL && strchr(line, ':') != NULL );
92     if (res == NULL)
93 rabbi 1 break;
94 weaselp 195 if (keyid && !streq(line, idstr))
95     continue;
96 weaselp 214 if (created != 0 && (created > time(NULL))) {
97 rabbi 376 errlog(ERRORMSG, "Key is not valid yet (creation date in the future): %s", idstr);
98 weaselp 214 break;
99     }
100     if (expires != 0 && (expires + KEYGRACEPERIOD < time(NULL))) {
101     errlog(ERRORMSG, "Key is expired: %s", idstr);
102     break;
103     }
104 weaselp 195 fgets(line, sizeof(line), keyring);
105     fgets(line, sizeof(line), keyring);
106     buf_sets(iv, line);
107     decode(iv, iv);
108     for (;;) {
109     if (fgets(line, sizeof(line), keyring) == NULL)
110 rabbi 186 break;
111 weaselp 195 if (strleft(line, end_key)) {
112     if (decode(key, key) == -1) {
113     errlog(ERRORMSG, "Corrupt secret key.\n");
114     break;
115     }
116     buf_sets(pass, PASSPHRASE);
117     digest_md5(pass, pass);
118     buf_crypt(key, pass, iv, DECRYPT);
119     err = check_seckey(key, keyid);
120     if (err == -1)
121     errlog(ERRORMSG, "Corrupt secret key. Bad passphrase?\n");
122     break;
123 rabbi 186 }
124 weaselp 195 buf_append(key, line, strlen(line) - 1);
125 rabbi 186 }
126 weaselp 195 break;
127 rabbi 1 }
128     }
129 weaselp 195 fclose(keyring);
130     }
131 rabbi 1
132     buf_free(pass);
133     buf_free(iv);
134     buf_free(temp);
135     return (err);
136     }
137    
138     static int getv2pubkey(byte keyid[], BUFFER *key)
139     {
140     FILE *keyring;
141     BUFFER *b, *temp, *iv;
142     char idstr[33];
143     char line[LINELEN];
144     int err = 0;
145    
146     b = buf_new();
147     iv = buf_new();
148     temp = buf_new();
149     id_encode(keyid, idstr);
150     if ((keyring = mix_openfile(PUBRING, "r")) == NULL) {
151     errlog(ERRORMSG, "Can't open %s!\n", PUBRING);
152     err = -1;
153     goto end;
154     }
155     for (;;) {
156     if (fgets(line, sizeof(line), keyring) == NULL)
157     break;
158     if (strleft(line, begin_key)) {
159     if (fgets(line, sizeof(line), keyring) == NULL)
160     break;
161 weaselp 276 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n'))
162     line[strlen(line)-1] = '\0';
163     if ((strlen(line) > 0) && (line[strlen(line)-1] == '\r'))
164     line[strlen(line)-1] = '\0';
165 rabbi 1 if (!streq(line, idstr))
166     continue;
167     fgets(line, sizeof(line), keyring); /* ignore length */
168     for (;;) {
169     if (fgets(line, sizeof(line), keyring) == NULL)
170     goto done;
171     if (strleft(line, end_key))
172     goto done;
173 weaselp 276 buf_append(key, line, strlen(line));
174 rabbi 1 }
175     break;
176     }
177     }
178     done:
179     fclose(keyring);
180    
181     if (key->length == 0) {
182 rabbi 448 errlog(ERRORMSG, "No such public key: %s\n", idstr);
183 rabbi 1 err = -1;
184     goto end;
185     }
186     err = decode(key, key);
187     if (err != -1)
188     err = check_pubkey(key, keyid);
189     if (err == -1)
190 rabbi 448 errlog(ERRORMSG, "Corrupt public key %s\n", idstr);
191 rabbi 1 end:
192     buf_free(b);
193     buf_free(iv);
194     buf_free(temp);
195     return (err);
196     }
197    
198 rabbi 262 #else /* end of USE_RSA */
199 rabbi 186 int getv2seckey(byte keyid[], BUFFER *key)
200 rabbi 1 {
201     return -1;
202     }
203    
204     static int getv2pubkey(byte keyid[], BUFFER *key)
205     {
206     return -1;
207     }
208 rabbi 262 #endif /* else not USE_RSA */
209 rabbi 1
210     int key(BUFFER *out)
211     {
212     int err = -1;
213     FILE *f;
214 weaselp 298 BUFFER *tmpkey;
215 rabbi 1
216 weaselp 298 tmpkey = buf_new();
217    
218 rabbi 1 buf_sets(out, "Subject: Remailer key for ");
219     buf_appends(out, SHORTNAME);
220     buf_appends(out, "\n\n");
221    
222     keymgt(0);
223    
224     conf_premail(out);
225     buf_nl(out);
226    
227     if (PGP) {
228 weaselp 298 if (pgp_latestkeys(tmpkey, PGP_ES_RSA) == 0) {
229     buf_appends(out, "Here is the RSA PGP key:\n\n");
230     buf_cat(out, tmpkey);
231 rabbi 1 buf_nl(out);
232     err = 0;
233     }
234 weaselp 298 if (pgp_latestkeys(tmpkey, PGP_S_DSA) == 0) {
235     buf_appends(out, "Here is the DSA PGP key:\n\n");
236     buf_cat(out, tmpkey);
237     buf_nl(out);
238     err = 0;
239     }
240 rabbi 1 }
241     if (MIX) {
242     if ((f = mix_openfile(KEYFILE, "r")) != NULL) {
243     buf_appends(out, "Here is the Mixmaster key:\n\n");
244     buf_appends(out, "=-=-=-=-=-=-=-=-=-=-=-=\n");
245     buf_read(out, f);
246     buf_nl(out);
247     fclose(f);
248     err = 0;
249     }
250     }
251     if (err == -1 && UNENCRYPTED) {
252     buf_appends(out, "The remailer accepts unencrypted messages.\n");
253     err = 0;
254     }
255     if (err == -1)
256     errlog(ERRORMSG, "Cannot create remailer keys!");
257    
258 weaselp 298 buf_free(tmpkey);
259    
260 rabbi 1 return (err);
261     }
262    
263     int adminkey(BUFFER *out)
264     {
265 weaselp 332 int err = -1;
266     FILE *f;
267 rabbi 1
268 weaselp 332 buf_sets( out, "Subject: Admin key for the " );
269     buf_appends( out, SHORTNAME );
270     buf_appends( out, " remailer\n\n" );
271 rabbi 1
272 weaselp 332 if ( (f = mix_openfile( ADMKEYFILE, "r" )) != NULL ) {
273     buf_read( out, f );
274     buf_nl( out );
275     fclose( f );
276     err = 0;
277     }
278 rabbi 1
279 weaselp 332 if ( err == -1 )
280     errlog( ERRORMSG, "Can not read admin key file!\n" );
281 rabbi 1
282 weaselp 332 return err;
283 rabbi 1 }
284    
285     #ifdef USE_RSA
286 weaselp 120 int v2keymgt(int force)
287 weaselp 214 /*
288     * Mixmaster v2 Key Management
289 weaselp 332 *
290 weaselp 214 * This function triggers creation of mix keys (see parameter force) which are
291     * stored in secring.mix. One public mix key is also written to key.txt. This
292 rabbi 376 * is the key with the latest expiration date (keys with no expiration date
293     * are always considered newer if they appear later in the secret mix file
294     * - key creation appends keys).
295 weaselp 214 *
296     * force:
297     * 0, 1: create key when necessary:
298     * - no key exists as of yet
299     * - old keys are due to expire/already expired
300     * 2: always create a new mix key.
301     *
302     * (force = 0 is used in mix_daily, and before remailer-key replies)
303     * (force = 1 is used by mixmaster -K)
304     * (force = 2 is used by mixmaster -G)
305     */
306 rabbi 1 {
307     FILE *keyring, *f;
308     char line[LINELEN];
309 weaselp 214 byte k1[16], k1_found[16];
310     BUFFER *b, *temp, *iv, *pass, *pk, *pk_found;
311 rabbi 1 int err = 0;
312 weaselp 214 int found, foundnonexpiring;
313     time_t created, expires, created_found, expires_found;
314     char *res;
315 rabbi 1
316     b = buf_new();
317     temp = buf_new();
318     iv = buf_new();
319     pass = buf_new();
320     pk = buf_new();
321 weaselp 214 pk_found = buf_new();
322 rabbi 1
323 weaselp 214 foundnonexpiring = 0;
324     for (;;) {
325     found = 0;
326     created_found = 0;
327     expires_found = 0;
328 rabbi 1
329 weaselp 214 keyring = mix_openfile(SECRING, "r");
330     if (keyring != NULL) {
331     for (;;) {
332 rabbi 1 if (fgets(line, sizeof(line), keyring) == NULL)
333     break;
334 weaselp 214 if (strleft(line, begin_key)) {
335     expires = 0;
336     created = 0;
337     do {
338     res = fgets(line, sizeof(line), keyring);
339     if (strileft(line, "created:")) {
340     created = parse_yearmonthday(strchr(line, ':')+1);
341     if (created == -1)
342     created = 0;
343     } else if (strileft(line, "expires:")) {
344     expires = parse_yearmonthday(strchr(line, ':')+1);
345     if (expires == -1)
346     expires = 0;
347     }
348     /* Fetch lines until we fail or get a non-header line */
349     } while ( res != NULL && strchr(line, ':') != NULL );
350     if (res == NULL)
351     break;
352     if (((created != 0) && (created > time(NULL))) ||
353     ((expires != 0) && (expires < time(NULL)))) {
354     /* Key already is expired or has creation date in the future */
355     continue;
356     }
357     id_decode(line, k1);
358     fgets(line, sizeof(line), keyring);
359 rabbi 1 if (fgets(line, sizeof(line), keyring) == NULL)
360     break;
361 weaselp 214 buf_sets(iv, line);
362     decode(iv, iv);
363     buf_reset(b);
364     for (;;) {
365     if (fgets(line, sizeof(line), keyring) == NULL)
366     break;
367     if (strleft(line, end_key))
368     break;
369     buf_append(b, line, strlen(line) - 1);
370     }
371     if (decode(b, b) == -1)
372 rabbi 1 break;
373 weaselp 214 buf_sets(temp, PASSPHRASE);
374     digest_md5(temp, pass);
375     buf_crypt(b, pass, iv, DECRYPT);
376     buf_clear(pk);
377     if (seckeytopub(pk, b, k1) == 0) {
378     found = 1;
379     if (expires == 0 || (expires - KEYOVERLAPPERIOD >= time(NULL)))
380     foundnonexpiring = 1;
381 uid23509 229 if (expires == 0 || (expires_found <= expires)) {
382 weaselp 214 buf_clear(pk_found);
383     buf_cat(pk_found, pk);
384     memcpy(&k1_found, &k1, sizeof(k1));
385     expires_found = expires;
386     created_found = created;
387     }
388     }
389 rabbi 1 }
390     }
391 weaselp 214 fclose(keyring);
392 rabbi 1 }
393 weaselp 332
394 weaselp 214 if (!foundnonexpiring || (force == 2)) {
395     v2createkey();
396     foundnonexpiring = 1;
397     force = 1;
398 weaselp 332 } else
399 weaselp 214 break;
400     };
401    
402 rabbi 1 if (found) {
403     if ((f = mix_openfile(KEYFILE, "w")) != NULL) {
404 weaselp 214 id_encode(k1_found, line);
405 rabbi 371 fprintf(f, "%s %s %s %s:%s %s%s", SHORTNAME,
406     REMAILERADDR, line, mixmaster_protocol, VERSION,
407 rabbi 7 MIDDLEMAN ? "M" : "",
408 rabbi 1 NEWS[0] == '\0' ? "C" : (strchr(NEWS, '@') ? "CNm" : "CNp"));
409 weaselp 214 if (created_found) {
410     struct tm *gt;
411     gt = gmtime(&created_found);
412     strftime(line, LINELEN, "%Y-%m-%d", gt);
413     fprintf(f, " %s", line);
414     if (expires_found) {
415     struct tm *gt;
416     gt = gmtime(&expires_found);
417     strftime(line, LINELEN, "%Y-%m-%d", gt);
418     fprintf(f, " %s", line);
419     }
420     }
421     fprintf(f, "\n\n%s\n", begin_key);
422     id_encode(k1_found, line);
423 rabbi 1 fprintf(f, "%s\n258\n", line);
424 weaselp 214 encode(pk_found, 40);
425     buf_write(pk_found, f);
426 rabbi 1 fprintf(f, "%s\n\n", end_key);
427     fclose(f);
428     }
429     } else
430     err = -1;
431    
432     buf_free(b);
433     buf_free(temp);
434     buf_free(iv);
435     buf_free(pass);
436     buf_free(pk);
437 weaselp 214 buf_free(pk_found);
438 rabbi 1
439     return (err);
440     }
441 rabbi 262 #endif /* USE_RSA */
442 rabbi 1
443     int keymgt(int force)
444     {
445     /* force = 0: write key file if there is none
446     force = 1: update key file
447     force = 2: generate new key */
448     int err = 0;
449    
450 weaselp 108 if (REMAIL || force == 2) {
451 rabbi 1 #ifdef USE_RSA
452 rabbi 81 if (MIX && (err = v2keymgt(force)) == -1)
453     err = -1;
454 rabbi 262 #endif /* USE_RSA */
455 rabbi 1 #ifdef USE_PGP
456 rabbi 81 if (PGP && (err = pgp_keymgt(force)) == -1)
457     err = -1;
458 rabbi 262 #endif /* USE_PGP */
459 rabbi 81 }
460 rabbi 1 return (err);
461     }

  ViewVC Help
Powered by ViewVC 1.1.5