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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 262 - (show annotations) (download)
Wed Sep 18 23:26:17 2002 UTC (10 years, 8 months ago) by rabbi
File MIME type: text/plain
File size: 12085 byte(s)
Added closing comments for all #ifdef statements. All #endif's, as well as
nested braces, should be commented to reference their start.

We need to provide comments before every function as well.
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 OpenPGP key database
9 $Id: pgpdb.c,v 1.12 2002/09/18 23:26:16 rabbi Exp $ */
10
11
12 #include "mix3.h"
13 #ifdef USE_PGP
14 #include "pgp.h"
15 #include <assert.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <time.h>
19
20 static int pgp_readkeyring(BUFFER *keys, char *filename)
21 {
22 FILE *keyfile;
23 BUFFER *armored, *line, *tmp;
24 int err = -1;
25
26 if ((keyfile = mix_openfile(filename, "rb")) == NULL)
27 return (err);
28
29 armored = buf_new();
30 buf_read(armored, keyfile);
31 fclose(keyfile);
32 if (pgp_ispacket(armored)) {
33 err = 0;
34 buf_move(keys, armored);
35 } else {
36 line = buf_new();
37 tmp = buf_new();
38
39 while (1) {
40 do
41 if (buf_getline(armored, line) == -1) {
42 goto end_greedy_dearmor;
43 }
44 while (!bufleft(line, begin_pgp)) ;
45 buf_clear(tmp);
46 buf_cat(tmp, line);
47 buf_appends(tmp, "\n");
48 do {
49 if (buf_getline(armored, line) == -1) {
50 goto end_greedy_dearmor;
51 }
52 buf_cat(tmp, line);
53 buf_appends(tmp, "\n");
54 } while (!bufleft(line, end_pgp)) ;
55
56 if (pgp_dearmor(tmp, tmp) == 0) {
57 err = ARMORED;
58 buf_cat(keys, tmp);
59 }
60 }
61 end_greedy_dearmor:
62 buf_free(line);
63 buf_free(tmp);
64
65 }
66 buf_free(armored);
67 return (err);
68 }
69
70 KEYRING *pgpdb_open(char *keyring, BUFFER *encryptkey, int writer)
71 {
72 KEYRING *keydb;
73
74 keydb = pgpdb_new(keyring, -1, encryptkey);
75 if (writer)
76 keydb->lock = lockfile(keyring);
77 keydb->filetype = pgp_readkeyring(keydb->db, keyring);
78 #if 0
79 if (keydb->filetype == -1) {
80 pgpdb_close(keydb);
81 return (NULL);
82 }
83 #endif /* if 0 */
84 if (encryptkey && encryptkey->length && pgp_isconventional(keydb->db) &&
85 pgp_decrypt(keydb->db, encryptkey, NULL, NULL, NULL) < 0) {
86 user_delpass();
87 return (NULL);
88 }
89 return (keydb);
90 }
91
92 KEYRING *pgpdb_new(char *keyring, int filetype, BUFFER *encryptkey)
93 {
94 KEYRING *keydb;
95
96 keydb = malloc(sizeof(KEYRING));
97
98 if (keydb == NULL)
99 return NULL;
100 keydb->db = buf_new();
101 keydb->modified = 0;
102 keydb->lock = NULL;
103 strncpy(keydb->filename, keyring, sizeof(keydb->filename));
104 keydb->filetype = filetype;
105 if (encryptkey == NULL)
106 keydb->encryptkey = NULL;
107 else {
108 keydb->encryptkey = buf_new();
109 buf_set(keydb->encryptkey, encryptkey);
110 }
111 return (keydb);
112 }
113
114 int pgpdb_close(KEYRING *keydb)
115 {
116 int err = 0;
117
118 if (keydb->modified) {
119 FILE *f;
120
121 if (keydb->encryptkey && keydb->encryptkey->length)
122 pgp_encrypt(PGP_NCONVENTIONAL | PGP_NOARMOR, keydb->db,
123 keydb->encryptkey, NULL, NULL, NULL, NULL);
124 if (keydb->filetype == ARMORED)
125 pgp_armor(keydb->db, PGP_ARMOR_KEY);
126 if (keydb->filetype == -1 || (f = mix_openfile(keydb->filename,
127 keydb->filetype ==
128 ARMORED ? "w" : "wb"))
129 == NULL)
130 err = -1;
131 else {
132 err = buf_write(keydb->db, f);
133 fclose(f);
134 }
135 }
136 if (keydb->lock)
137 unlockfile(keydb->lock);
138 if (keydb->encryptkey)
139 buf_free(keydb->encryptkey);
140 buf_free(keydb->db);
141 free(keydb);
142 return (err);
143 }
144
145 int pgpdb_getnext(KEYRING *keydb, BUFFER *key, BUFFER *keyid, BUFFER *userid)
146 /* store next key from keydb with specified keyid/userid in key. */
147 {
148 int found = 0;
149 int type;
150 long ptr;
151 int tempbuf = 0;
152 BUFFER *p, *i, *thisid;
153
154 p = buf_new();
155 i = buf_new();
156 thisid = buf_new();
157
158 if (key == NULL) {
159 tempbuf = 1;
160 key = buf_new();
161 }
162 assert(key != keyid);
163 while (!found) {
164 buf_clear(key);
165 type = pgp_getpacket(keydb->db, key);
166 if (type == -1)
167 break;
168 if (type != PGP_PUBKEY && type != PGP_SECKEY)
169 continue;
170 if ((keyid == NULL || keyid->length == 0) &&
171 (userid == NULL || userid->length == 0))
172 found = 1;
173
174 if (keyid && keyid->length > 0) {
175 pgp_keyid(key, thisid);
176 if (buf_eq(keyid, thisid))
177 found = 1;
178 }
179
180 pgp_packet(key, type);
181
182 while ((ptr = keydb->db->ptr, type = pgp_getpacket(keydb->db, p)) > 0) {
183 switch (type) {
184 case PGP_SECKEY:
185 case PGP_PUBKEY:
186 keydb->db->ptr = ptr;
187 goto nextkey;
188 case PGP_PUBSUBKEY:
189 case PGP_SECSUBKEY:
190 if (keyid && keyid->length > 0) {
191 pgp_keyid(p, thisid);
192 if (buf_eq(keyid, thisid))
193 found = 1;
194 }
195 break;
196 case PGP_USERID:
197 #ifdef DEBUG
198 printf("%s\n", p->data);
199 #endif /* DEBUG */
200 if (userid && userid->length > 0 && bufifind(p, userid->data))
201 found = 1;
202 break;
203 }
204 pgp_packet(p, type);
205 buf_cat(key, p);
206 }
207 nextkey:
208 ;
209 }
210 if (tempbuf)
211 buf_free(key);
212 buf_free(p);
213 buf_free(i);
214 buf_free(thisid);
215 return (found ? 0 : -1);
216 }
217
218 int pgpdb_append(KEYRING *keydb, BUFFER *p)
219 {
220 assert(keydb->lock);
221 buf_cat(keydb->db, p);
222 keydb->modified = 1;
223 return (0);
224 }
225
226 #define pgp_preferredalgo PGP_ES_RSA
227
228 int pgpdb_getkey(int mode, int algo, int *sym, int *mdc, long *expires, BUFFER *key, BUFFER *userid,
229 BUFFER *founduid, BUFFER *keyid, char *keyring, BUFFER *pass)
230 {
231 KEYRING *r;
232 BUFFER *id, *thisid, *thiskey;
233 int thisalgo, algofound = -1, needpass = 0;
234 int found = 0;
235
236 id = buf_new();
237 thisid = buf_new();
238 thiskey = buf_new();
239 if (keyring)
240 r = pgpdb_open(keyring, pass, 0);
241 else
242 switch (mode) {
243 case PK_DECRYPT:
244 case PK_SIGN:
245 r = pgpdb_open(PGPREMSECRING, NULL, 0);
246 break;
247 case PK_ENCRYPT:
248 case PK_VERIFY:
249 r = pgpdb_open(PGPREMPUBRING, NULL, 0);
250 if (r != NULL && r->filetype == -1) {
251 pgpdb_close(r);
252 r = pgpdb_open(PGPREMPUBASC, NULL, 0);
253 }
254 break;
255 default:
256 r = NULL;
257 }
258 if (r == NULL)
259 goto end;
260
261 for (;;) {
262 /* repeat until success or end of key ring */
263 if (pgpdb_getnext(r, thiskey, keyid, userid) == -1)
264 break;
265 if (keyid) /* pgp_getkey has to chose subkey with given keyid */
266 buf_set(thisid, keyid);
267 thisalgo = pgp_getkey(mode, algo, sym, mdc, expires, thiskey, thiskey, thisid, founduid,
268 pass);
269 if (thisalgo == PGP_PASS)
270 needpass = 1;
271 if (thisalgo > 0) {
272 found++;
273 if ((thisalgo == pgp_preferredalgo && algofound != pgp_preferredalgo
274 && algofound > 0)
275 || (thisalgo != pgp_preferredalgo && algofound == pgp_preferredalgo))
276 found--; /* ignore the non-preferred algorithm */
277 if (found <= 1 || (thisalgo == pgp_preferredalgo &&
278 algofound != pgp_preferredalgo && algofound > 0)) {
279 algofound = thisalgo;
280 if (key)
281 buf_move(key, thiskey);
282 buf_set(id, thisid);
283 }
284 }
285 }
286 pgpdb_close(r);
287 end:
288 if (found < 1) {
289 if (needpass)
290 errlog(DEBUGINFO, "Need passphrase!\n");
291 else if (!sym || *sym != PGP_K_IDEA) { /* kludge: try again with 3DES */
292 if (userid)
293 errlog(NOTICE, "Key %b not found!\n", userid);
294 else if (keyid && keyid->length > 7)
295 errlog(NOTICE, "Key %02X%02X%02X%02X not found!\n", keyid->data[4],
296 keyid->data[5], keyid->data[6], keyid->data[7]);
297 }
298 }
299 if (found > 1) {
300 if (userid)
301 errlog(WARNING, "Key %b not unique!\n", userid);
302 else if (keyid && keyid->length > 7)
303 errlog(ERRORMSG, "Key %02X%02X%02X%02X not unique!\n", keyid->data[4],
304 keyid->data[5], keyid->data[6], keyid->data[7]);
305 else
306 errlog(WARNING, "Key not unique!\n");
307 }
308 if (found && keyid) /* return ID of found key */
309 buf_set(keyid, id);
310
311 buf_free(thiskey);
312 buf_free(thisid);
313 buf_free(id);
314 return (algofound);
315 }
316
317 int pgp_keymgt(int force)
318 {
319 FILE *f = NULL;
320 BUFFER *key, *keybak, *userid, *out, *outkey, *outtxt, *pass, *secout;
321 KEYRING *keys;
322 int err = 0, type = 0, res;
323 long expires;
324 LOCK *seclock;
325
326 key = buf_new();
327 out = buf_new();
328 keybak = buf_new();
329 secout = buf_new();
330
331 userid = buf_new();
332 buf_sets(userid, REMAILERNAME);
333 pass = buf_new();
334 buf_sets(pass, PASSPHRASE);
335 outtxt = buf_new();
336 outkey = buf_new();
337
338 #ifdef USE_RSA
339 /* We only want to build RSA keys if we also can do IDEA
340 * This is to not lose any mail should users try our RSA key
341 * with IDEA.
342 */
343 #ifdef USE_IDEA
344 res = pgpdb_getkey(PK_DECRYPT, PGP_ES_RSA, NULL, NULL, &expires, NULL, NULL,
345 NULL, NULL, NULL, pass);
346 if (force == 2 || res < 0 || (expires > 0 && expires - KEYOVERLAPPERIOD < time(NULL)))
347 pgp_keygen(PGP_ES_RSA, 0, userid, pass, PGPKEY, PGPREMSECRING, 0);
348
349 if (force == 0 && (pgpdb_getkey(PK_ENCRYPT, PGP_ES_RSA, NULL, NULL, NULL, NULL, NULL,
350 NULL, NULL, PGPKEY, NULL) < 0))
351 goto end;
352 #endif /* USE_IDEA */
353 #endif /* USE_RSA */
354 res = pgpdb_getkey(PK_DECRYPT, PGP_E_ELG, NULL, NULL, &expires, NULL, NULL,
355 NULL, NULL, NULL, pass);
356 if (force == 2 || res < 0 || (expires > 0 && expires - KEYOVERLAPPERIOD < time(NULL)))
357 pgp_keygen(PGP_E_ELG, 0, userid, pass, PGPKEY, PGPREMSECRING, 0);
358
359 if (force == 0 && (pgpdb_getkey(PK_ENCRYPT, PGP_E_ELG, NULL, NULL, NULL, NULL, NULL,
360 NULL, NULL, PGPKEY, NULL) > 0))
361 goto end;
362
363 /* write RSA and DSA/ElGamal keys separately to make old PGP
364 versions happy */
365 err = -1;
366 for (type = 0; type < 2; type++) {
367 keys = pgpdb_open(PGPREMSECRING, NULL, 0);
368 if (keys == NULL)
369 goto end;
370 while (pgpdb_getnext(keys, key, NULL, userid) != -1) {
371 buf_clear(outtxt);
372 buf_clear(outkey);
373 buf_clear(keybak);
374 buf_cat(keybak, key);
375 if (pgp_makeseckey(key, outtxt, pass,
376 type == 0 ? PGP_ES_RSA : PGP_S_DSA) == 0) {
377 err = 0;
378 buf_appends(secout, "Type Bits/KeyID Date User ID\n");
379 buf_cat(secout, outtxt);
380 buf_nl(secout);
381 pgp_armor(key, PGP_ARMOR_SECKEY);
382 buf_cat(secout, key);
383 buf_nl(secout);
384 }
385 buf_clear(outtxt);
386 if (pgp_makepubkey(keybak, outtxt, outkey, pass,
387 type == 0 ? PGP_ES_RSA : PGP_S_DSA) == 0) {
388 err = 0;
389 buf_appends(out, "Type Bits/KeyID Date User ID\n");
390 buf_cat(out, outtxt);
391 buf_nl(out);
392 pgp_armor(outkey, PGP_ARMOR_KEY);
393 buf_cat(out, outkey);
394 buf_nl(out);
395 }
396 }
397 pgpdb_close(keys);
398 }
399
400 seclock = lockfile(PGPREMSECRING);
401 if (err == 0 && (f = mix_openfile(PGPREMSECRING, "w")) != NULL) {
402 buf_write(secout, f);
403 fclose(f);
404 } else
405 err = -1;
406 unlockfile(seclock);
407 if (err == 0 && (f = mix_openfile(PGPKEY, "w")) != NULL) {
408 buf_write(out, f);
409 fclose(f);
410 } else
411 err = -1;
412 end:
413 buf_free(key);
414 buf_free(keybak);
415 buf_free(out);
416 buf_free(userid);
417 buf_free(pass);
418 buf_free(outtxt);
419 buf_free(outkey);
420 buf_free(secout);
421 return (err);
422 }
423
424 int pgp_rlist(REMAILER remailer[], int n)
425 /* verify that keys are available */
426 {
427 BUFFER *keyring, *p;
428 int i, type, pgpkey[MAXREM];
429
430 keyring = buf_new();
431 p = buf_new();
432 for (i = 1; i < n; i++)
433 pgpkey[i] = 0;
434 if (pgp_readkeyring(keyring, PGPREMPUBRING) == -1)
435 pgp_readkeyring(keyring, PGPREMPUBASC);
436 while ((type = pgp_getpacket(keyring, p)) != -1)
437 if (type == PGP_USERID)
438 for (i = 1; i < n; i++)
439 if (remailer[i].flags.pgp && bufifind(p, remailer[i].name))
440 pgpkey[i] = 1;
441 for (i = 1; i < n; i++)
442 remailer[i].flags.pgp = pgpkey[i];
443 buf_free(p);
444 buf_free(keyring);
445 return (0);
446 }
447
448 int pgp_rkeylist(REMAILER remailer[], int keyid[], int n)
449 /* Step through all remailers and get keyid */
450 {
451 BUFFER *userid;
452 BUFFER *id;
453 int i, err;
454
455 userid = buf_new();
456 id = buf_new();
457
458 for (i = 1; i < n; i++) {
459 buf_clear(userid);
460 buf_setf(userid, "<%s>", remailer[i].addr);
461
462 keyid[i]=0;
463 if (remailer[i].flags.pgp) {
464 buf_clear(id);
465 err = pgpdb_getkey(PK_VERIFY, PGP_ANY, NULL, NULL, NULL, NULL, userid, NULL, id, NULL, NULL);
466 if (id->length == 8) {
467 /* printf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n",
468 id->data[0], id->data[1], id->data[2], id->data[3], id->data[4], id->data[5], id->data[6], id->data[7], id->data[8], remailer[i].addr); */
469 keyid[i] = (((((id->data[4] << 8) + id->data[5]) << 8) + id->data[6]) << 8) + id->data[7];
470 }
471 }
472 }
473
474 buf_free(userid);
475 return (0);
476 }
477
478 #endif /* USE_PGP */

  ViewVC Help
Powered by ViewVC 1.1.5