/[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 298 - (show annotations) (download)
Wed Oct 2 07:54:12 2002 UTC (10 years, 7 months ago) by weaselp
File MIME type: text/plain
File size: 11190 byte(s)
Only return latest pgp keys to remailer-key requests
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 $Id: keymgt.c,v 1.17 2002/10/02 07:54:12 weaselp Exp $ */
10
11
12 #include "mix3.h"
13 #include <string.h>
14 #include <time.h>
15 #include <assert.h>
16
17 int getv2seckey(byte keyid[], BUFFER *key);
18 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 /* 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 {
53 FILE *keyring;
54 BUFFER *iv, *pass, *temp;
55 char idstr[33];
56 char line[LINELEN];
57 int err = -1;
58 char *res;
59 time_t created, expires;
60
61 pass = buf_new();
62 iv = buf_new();
63 temp = buf_new();
64 if (keyid)
65 id_encode(keyid, idstr);
66 else
67 idstr[0] = 0;
68 strcat(idstr, "\n");
69 if ((keyring = mix_openfile(SECRING, "r")) == NULL) {
70 errlog(ERRORMSG, "No secret key file!\n");
71 } else {
72 while (err == -1) {
73 buf_clear(key);
74 if (fgets(line, sizeof(line), keyring) == NULL)
75 break;
76 if (strleft(line, begin_key)) {
77 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 break;
94 if (keyid && !streq(line, idstr))
95 continue;
96 if (created != 0 && (created > time(NULL))) {
97 errlog(ERRORMSG, "Key is not valid yet (create date in the future): %s", idstr);
98 break;
99 }
100 if (expires != 0 && (expires + KEYGRACEPERIOD < time(NULL))) {
101 errlog(ERRORMSG, "Key is expired: %s", idstr);
102 break;
103 }
104 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 break;
111 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 }
124 buf_append(key, line, strlen(line) - 1);
125 }
126 break;
127 }
128 }
129 fclose(keyring);
130 }
131
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 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 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 buf_append(key, line, strlen(line));
174 }
175 break;
176 }
177 }
178 done:
179 fclose(keyring);
180
181 if (key->length == 0) {
182 errlog(ERRORMSG, "No such public key: %s", idstr);
183 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 errlog(ERRORMSG, "Corrupt public key %s", idstr);
191 end:
192 buf_free(b);
193 buf_free(iv);
194 buf_free(temp);
195 return (err);
196 }
197
198 #else /* end of USE_RSA */
199 int getv2seckey(byte keyid[], BUFFER *key)
200 {
201 return -1;
202 }
203
204 static int getv2pubkey(byte keyid[], BUFFER *key)
205 {
206 return -1;
207 }
208 #endif /* else not USE_RSA */
209
210 int key(BUFFER *out)
211 {
212 int err = -1;
213 FILE *f;
214 BUFFER *tmpkey;
215
216 tmpkey = buf_new();
217
218 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 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 buf_nl(out);
232 err = 0;
233 }
234 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 }
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 buf_free(tmpkey);
259
260 return (err);
261 }
262
263 int adminkey(BUFFER *out)
264 {
265 int err = -1;
266 FILE *f;
267
268 buf_sets( out, "Subject: Admin key for the " );
269 buf_appends( out, SHORTNAME );
270 buf_appends( out, " remailer\n\n" );
271
272 if ( (f = mix_openfile( ADMKEYFILE, "r" )) != NULL ) {
273 buf_read( out, f );
274 buf_nl( out );
275 fclose( f );
276 err = 0;
277 }
278
279 if ( err == -1 )
280 errlog( ERRORMSG, "Can not read admin key file!\n" );
281
282 return err;
283 }
284
285 #ifdef USE_RSA
286 int v2keymgt(int force)
287 /*
288 * Mixmaster v2 Key Management
289 *
290 * 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 * is the key with the latest expire date (keys with no expiration date are
293 * always considered newer if they appear later in the secret mix file - key
294 * creation appends keys).
295 *
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 {
307 FILE *keyring, *f;
308 char line[LINELEN];
309 byte k1[16], k1_found[16];
310 BUFFER *b, *temp, *iv, *pass, *pk, *pk_found;
311 int err = 0;
312 int found, foundnonexpiring;
313 time_t created, expires, created_found, expires_found;
314 char *res;
315
316 b = buf_new();
317 temp = buf_new();
318 iv = buf_new();
319 pass = buf_new();
320 pk = buf_new();
321 pk_found = buf_new();
322
323 foundnonexpiring = 0;
324 for (;;) {
325 found = 0;
326 created_found = 0;
327 expires_found = 0;
328
329 keyring = mix_openfile(SECRING, "r");
330 if (keyring != NULL) {
331 for (;;) {
332 if (fgets(line, sizeof(line), keyring) == NULL)
333 break;
334 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 if (fgets(line, sizeof(line), keyring) == NULL)
360 break;
361 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 break;
373 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 if (expires == 0 || (expires_found <= expires)) {
382 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 }
390 }
391 fclose(keyring);
392 }
393
394 if (!foundnonexpiring || (force == 2)) {
395 v2createkey();
396 foundnonexpiring = 1;
397 force = 1;
398 } else
399 break;
400 };
401
402 if (found) {
403 if ((f = mix_openfile(KEYFILE, "w")) != NULL) {
404 id_encode(k1_found, line);
405 fprintf(f, "%s %s %s %s %s%s", SHORTNAME,
406 REMAILERADDR, line, VERSION,
407 MIDDLEMAN ? "M" : "",
408 NEWS[0] == '\0' ? "C" : (strchr(NEWS, '@') ? "CNm" : "CNp"));
409 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 fprintf(f, "%s\n258\n", line);
424 encode(pk_found, 40);
425 buf_write(pk_found, f);
426 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 buf_free(pk_found);
438
439 return (err);
440 }
441 #endif /* USE_RSA */
442
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 if (REMAIL || force == 2) {
451 #ifdef USE_RSA
452 if (MIX && (err = v2keymgt(force)) == -1)
453 err = -1;
454 #endif /* USE_RSA */
455 #ifdef USE_PGP
456 if (PGP && (err = pgp_keymgt(force)) == -1)
457 err = -1;
458 #endif /* USE_PGP */
459 }
460 return (err);
461 }

  ViewVC Help
Powered by ViewVC 1.1.5