/[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 282 - (show annotations) (download)
Thu Sep 26 22:04:58 2002 UTC (10 years, 7 months ago) by weaselp
File MIME type: text/plain
File size: 12265 byte(s)
pass armortype to pgpdb_close - used when file needs to get armored
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.13 2002/09/26 22:04:58 weaselp 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, PGP_ARMOR_KEY);
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, int armortype)
115 /*
116 * armortype whether to use PGP_ARMOR_KEY or PGP_ARMOR_SECKEY if the key is
117 * armored
118 */
119 {
120 int err = 0;
121
122 if (keydb->modified) {
123 FILE *f;
124
125 if (keydb->encryptkey && keydb->encryptkey->length)
126 pgp_encrypt(PGP_NCONVENTIONAL | PGP_NOARMOR, keydb->db,
127 keydb->encryptkey, NULL, NULL, NULL, NULL);
128 if (keydb->filetype == ARMORED)
129 pgp_armor(keydb->db, armortype);
130 if (keydb->filetype == -1 || (f = mix_openfile(keydb->filename,
131 keydb->filetype ==
132 ARMORED ? "w" : "wb"))
133 == NULL)
134 err = -1;
135 else {
136 err = buf_write(keydb->db, f);
137 fclose(f);
138 }
139 }
140 if (keydb->lock)
141 unlockfile(keydb->lock);
142 if (keydb->encryptkey)
143 buf_free(keydb->encryptkey);
144 buf_free(keydb->db);
145 free(keydb);
146 return (err);
147 }
148
149 int pgpdb_getnext(KEYRING *keydb, BUFFER *key, BUFFER *keyid, BUFFER *userid)
150 /* store next key from keydb with specified keyid/userid in key. */
151 {
152 int found = 0;
153 int type;
154 long ptr;
155 int tempbuf = 0;
156 BUFFER *p, *i, *thisid;
157
158 p = buf_new();
159 i = buf_new();
160 thisid = buf_new();
161
162 if (key == NULL) {
163 tempbuf = 1;
164 key = buf_new();
165 }
166 assert(key != keyid);
167 while (!found) {
168 buf_clear(key);
169 type = pgp_getpacket(keydb->db, key);
170 if (type == -1)
171 break;
172 if (type != PGP_PUBKEY && type != PGP_SECKEY)
173 continue;
174 if ((keyid == NULL || keyid->length == 0) &&
175 (userid == NULL || userid->length == 0))
176 found = 1;
177
178 if (keyid && keyid->length > 0) {
179 pgp_keyid(key, thisid);
180 if (buf_eq(keyid, thisid))
181 found = 1;
182 }
183
184 pgp_packet(key, type);
185
186 while ((ptr = keydb->db->ptr, type = pgp_getpacket(keydb->db, p)) > 0) {
187 switch (type) {
188 case PGP_SECKEY:
189 case PGP_PUBKEY:
190 keydb->db->ptr = ptr;
191 goto nextkey;
192 case PGP_PUBSUBKEY:
193 case PGP_SECSUBKEY:
194 if (keyid && keyid->length > 0) {
195 pgp_keyid(p, thisid);
196 if (buf_eq(keyid, thisid))
197 found = 1;
198 }
199 break;
200 case PGP_USERID:
201 #ifdef DEBUG
202 printf("%s\n", p->data);
203 #endif /* DEBUG */
204 if (userid && userid->length > 0 && bufifind(p, userid->data))
205 found = 1;
206 break;
207 }
208 pgp_packet(p, type);
209 buf_cat(key, p);
210 }
211 nextkey:
212 ;
213 }
214 if (tempbuf)
215 buf_free(key);
216 buf_free(p);
217 buf_free(i);
218 buf_free(thisid);
219 return (found ? 0 : -1);
220 }
221
222 int pgpdb_append(KEYRING *keydb, BUFFER *p)
223 {
224 assert(keydb->lock);
225 buf_cat(keydb->db, p);
226 keydb->modified = 1;
227 return (0);
228 }
229
230 #define pgp_preferredalgo PGP_ES_RSA
231
232 int pgpdb_getkey(int mode, int algo, int *sym, int *mdc, long *expires, BUFFER *key, BUFFER *userid,
233 BUFFER *founduid, BUFFER *keyid, char *keyring, BUFFER *pass)
234 {
235 KEYRING *r;
236 BUFFER *id, *thisid, *thiskey;
237 int thisalgo, algofound = -1, needpass = 0;
238 int found = 0;
239
240 id = buf_new();
241 thisid = buf_new();
242 thiskey = buf_new();
243 if (keyring)
244 r = pgpdb_open(keyring, pass, 0);
245 else
246 switch (mode) {
247 case PK_DECRYPT:
248 case PK_SIGN:
249 r = pgpdb_open(PGPREMSECRING, NULL, 0);
250 break;
251 case PK_ENCRYPT:
252 case PK_VERIFY:
253 r = pgpdb_open(PGPREMPUBRING, NULL, 0);
254 if (r != NULL && r->filetype == -1) {
255 pgpdb_close(r, PGP_ARMOR_KEY);
256 r = pgpdb_open(PGPREMPUBASC, NULL, 0);
257 }
258 break;
259 default:
260 r = NULL;
261 }
262 if (r == NULL)
263 goto end;
264
265 for (;;) {
266 /* repeat until success or end of key ring */
267 if (pgpdb_getnext(r, thiskey, keyid, userid) == -1)
268 break;
269 if (keyid) /* pgp_getkey has to chose subkey with given keyid */
270 buf_set(thisid, keyid);
271 thisalgo = pgp_getkey(mode, algo, sym, mdc, expires, thiskey, thiskey, thisid, founduid,
272 pass);
273 if (thisalgo == PGP_PASS)
274 needpass = 1;
275 if (thisalgo > 0) {
276 found++;
277 if ((thisalgo == pgp_preferredalgo && algofound != pgp_preferredalgo
278 && algofound > 0)
279 || (thisalgo != pgp_preferredalgo && algofound == pgp_preferredalgo))
280 found--; /* ignore the non-preferred algorithm */
281 if (found <= 1 || (thisalgo == pgp_preferredalgo &&
282 algofound != pgp_preferredalgo && algofound > 0)) {
283 algofound = thisalgo;
284 if (key)
285 buf_move(key, thiskey);
286 buf_set(id, thisid);
287 }
288 }
289 }
290 pgpdb_close(r, PGP_ARMOR_KEY);
291 end:
292 if (found < 1) {
293 if (needpass)
294 errlog(DEBUGINFO, "Need passphrase!\n");
295 else if (!sym || *sym != PGP_K_IDEA) { /* kludge: try again with 3DES */
296 if (userid)
297 errlog(NOTICE, "Key %b not found!\n", userid);
298 else if (keyid && keyid->length > 7)
299 errlog(NOTICE, "Key %02X%02X%02X%02X not found!\n", keyid->data[4],
300 keyid->data[5], keyid->data[6], keyid->data[7]);
301 }
302 }
303 if (found > 1) {
304 if (userid)
305 errlog(WARNING, "Key %b not unique!\n", userid);
306 else if (keyid && keyid->length > 7)
307 errlog(ERRORMSG, "Key %02X%02X%02X%02X not unique!\n", keyid->data[4],
308 keyid->data[5], keyid->data[6], keyid->data[7]);
309 else
310 errlog(WARNING, "Key not unique!\n");
311 }
312 if (found && keyid) /* return ID of found key */
313 buf_set(keyid, id);
314
315 buf_free(thiskey);
316 buf_free(thisid);
317 buf_free(id);
318 return (algofound);
319 }
320
321 int pgp_keymgt(int force)
322 {
323 FILE *f = NULL;
324 BUFFER *key, *keybak, *userid, *out, *outkey, *outtxt, *pass, *secout;
325 KEYRING *keys;
326 int err = 0, type = 0, res;
327 long expires;
328 LOCK *seclock;
329
330 key = buf_new();
331 out = buf_new();
332 keybak = buf_new();
333 secout = buf_new();
334
335 userid = buf_new();
336 buf_sets(userid, REMAILERNAME);
337 pass = buf_new();
338 buf_sets(pass, PASSPHRASE);
339 outtxt = buf_new();
340 outkey = buf_new();
341
342 #ifdef USE_RSA
343 /* We only want to build RSA keys if we also can do IDEA
344 * This is to not lose any mail should users try our RSA key
345 * with IDEA.
346 */
347 #ifdef USE_IDEA
348 res = pgpdb_getkey(PK_DECRYPT, PGP_ES_RSA, NULL, NULL, &expires, NULL, NULL,
349 NULL, NULL, NULL, pass);
350 if (force == 2 || res < 0 || (expires > 0 && expires - KEYOVERLAPPERIOD < time(NULL)))
351 pgp_keygen(PGP_ES_RSA, 0, userid, pass, PGPKEY, PGPREMSECRING, 0);
352
353 if (force == 0 && (pgpdb_getkey(PK_ENCRYPT, PGP_ES_RSA, NULL, NULL, NULL, NULL, NULL,
354 NULL, NULL, PGPKEY, NULL) < 0))
355 goto end;
356 #endif /* USE_IDEA */
357 #endif /* USE_RSA */
358 res = pgpdb_getkey(PK_DECRYPT, PGP_E_ELG, NULL, NULL, &expires, NULL, NULL,
359 NULL, NULL, NULL, pass);
360 if (force == 2 || res < 0 || (expires > 0 && expires - KEYOVERLAPPERIOD < time(NULL)))
361 pgp_keygen(PGP_E_ELG, 0, userid, pass, PGPKEY, PGPREMSECRING, 0);
362
363 if (force == 0 && (pgpdb_getkey(PK_ENCRYPT, PGP_E_ELG, NULL, NULL, NULL, NULL, NULL,
364 NULL, NULL, PGPKEY, NULL) > 0))
365 goto end;
366
367 /* write RSA and DSA/ElGamal keys separately to make old PGP
368 versions happy */
369 err = -1;
370 for (type = 0; type < 2; type++) {
371 keys = pgpdb_open(PGPREMSECRING, NULL, 0);
372 if (keys == NULL)
373 goto end;
374 while (pgpdb_getnext(keys, key, NULL, userid) != -1) {
375 buf_clear(outtxt);
376 buf_clear(outkey);
377 buf_clear(keybak);
378 buf_cat(keybak, key);
379 if (pgp_makeseckey(key, outtxt, pass,
380 type == 0 ? PGP_ES_RSA : PGP_S_DSA) == 0) {
381 err = 0;
382 buf_appends(secout, "Type Bits/KeyID Date User ID\n");
383 buf_cat(secout, outtxt);
384 buf_nl(secout);
385 pgp_armor(key, PGP_ARMOR_SECKEY);
386 buf_cat(secout, key);
387 buf_nl(secout);
388 }
389 buf_clear(outtxt);
390 if (pgp_makepubkey(keybak, outtxt, outkey, pass,
391 type == 0 ? PGP_ES_RSA : PGP_S_DSA) == 0) {
392 err = 0;
393 buf_appends(out, "Type Bits/KeyID Date User ID\n");
394 buf_cat(out, outtxt);
395 buf_nl(out);
396 pgp_armor(outkey, PGP_ARMOR_KEY);
397 buf_cat(out, outkey);
398 buf_nl(out);
399 }
400 }
401 pgpdb_close(keys, PGP_ARMOR_KEY);
402 }
403
404 seclock = lockfile(PGPREMSECRING);
405 if (err == 0 && (f = mix_openfile(PGPREMSECRING, "w")) != NULL) {
406 buf_write(secout, f);
407 fclose(f);
408 } else
409 err = -1;
410 unlockfile(seclock);
411 if (err == 0 && (f = mix_openfile(PGPKEY, "w")) != NULL) {
412 buf_write(out, f);
413 fclose(f);
414 } else
415 err = -1;
416 end:
417 buf_free(key);
418 buf_free(keybak);
419 buf_free(out);
420 buf_free(userid);
421 buf_free(pass);
422 buf_free(outtxt);
423 buf_free(outkey);
424 buf_free(secout);
425 return (err);
426 }
427
428 int pgp_rlist(REMAILER remailer[], int n)
429 /* verify that keys are available */
430 {
431 BUFFER *keyring, *p;
432 int i, type, pgpkey[MAXREM];
433
434 keyring = buf_new();
435 p = buf_new();
436 for (i = 1; i < n; i++)
437 pgpkey[i] = 0;
438 if (pgp_readkeyring(keyring, PGPREMPUBRING) == -1)
439 pgp_readkeyring(keyring, PGPREMPUBASC);
440 while ((type = pgp_getpacket(keyring, p)) != -1)
441 if (type == PGP_USERID)
442 for (i = 1; i < n; i++)
443 if (remailer[i].flags.pgp && bufifind(p, remailer[i].name))
444 pgpkey[i] = 1;
445 for (i = 1; i < n; i++)
446 remailer[i].flags.pgp = pgpkey[i];
447 buf_free(p);
448 buf_free(keyring);
449 return (0);
450 }
451
452 int pgp_rkeylist(REMAILER remailer[], int keyid[], int n)
453 /* Step through all remailers and get keyid */
454 {
455 BUFFER *userid;
456 BUFFER *id;
457 int i, err;
458
459 userid = buf_new();
460 id = buf_new();
461
462 for (i = 1; i < n; i++) {
463 buf_clear(userid);
464 buf_setf(userid, "<%s>", remailer[i].addr);
465
466 keyid[i]=0;
467 if (remailer[i].flags.pgp) {
468 buf_clear(id);
469 err = pgpdb_getkey(PK_VERIFY, PGP_ANY, NULL, NULL, NULL, NULL, userid, NULL, id, NULL, NULL);
470 if (id->length == 8) {
471 /* printf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n",
472 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); */
473 keyid[i] = (((((id->data[4] << 8) + id->data[5]) << 8) + id->data[6]) << 8) + id->data[7];
474 }
475 }
476 }
477
478 buf_free(userid);
479 return (0);
480 }
481
482 #endif /* USE_PGP */

  ViewVC Help
Powered by ViewVC 1.1.5