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

Properties

Name Value
svn:keywords Id

  ViewVC Help
Powered by ViewVC 1.1.5