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

  ViewVC Help
Powered by ViewVC 1.1.5