/[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 171 - (hide annotations) (download)
Thu Aug 22 08:13:36 2002 UTC (10 years, 10 months ago) by weaselp
File MIME type: text/plain
File size: 10990 byte(s)
Also list cypherpunk remailers in remailer-conf reply. Thanks to Ulf and
Disastry for their help.
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     OpenPGP key database
9 weaselp 171 $Id: pgpdb.c,v 1.7 2002/08/22 08:13:36 weaselp Exp $ */
10 rabbi 1
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 weaselp 115 BUFFER *armored, *line, *tmp;
24 rabbi 1 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 weaselp 115 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 rabbi 1 }
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, 2);
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 rabbi 135 int pgpdb_getkey(int mode, int algo, int *sym, int *mdc, BUFFER *key, BUFFER *userid,
222 rabbi 1 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 rabbi 135 thisalgo = pgp_getkey(mode, algo, sym, mdc, thiskey, thiskey, thisid, founduid,
261 rabbi 1 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 rabbi 102 buf_sets(pass, PASSPHRASE);
324 rabbi 1 outtxt = buf_new();
325     outkey = buf_new();
326    
327     #ifdef USE_RSA
328 weaselp 104 /* 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 rabbi 135 if (force == 2 || (pgpdb_getkey(PK_DECRYPT, PGP_ES_RSA, NULL, NULL, NULL, NULL,
334 rabbi 1 NULL, NULL, NULL, pass) < 0))
335     pgp_keygen(PGP_ES_RSA, 0, userid, pass, PGPKEY, PGPREMSECRING, 0);
336    
337 rabbi 135 if (force == 0 && (pgpdb_getkey(PK_ENCRYPT, PGP_ES_RSA, NULL, NULL, NULL, NULL,
338 rabbi 1 NULL, NULL, PGPKEY, NULL) < 0))
339     goto end;
340     #endif
341 weaselp 104 #endif
342 rabbi 135 if (force == 2 || (pgpdb_getkey(PK_DECRYPT, PGP_E_ELG, NULL, NULL, NULL, NULL,
343 rabbi 1 NULL, NULL, NULL, pass) < 0))
344     pgp_keygen(PGP_E_ELG, 0, userid, pass, PGPKEY, PGPREMSECRING, 0);
345    
346 rabbi 135 if (force == 0 && (pgpdb_getkey(PK_ENCRYPT, PGP_E_ELG, NULL, NULL, NULL, NULL,
347 rabbi 1 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, 2);
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 weaselp 171 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 rabbi 1 #endif /* USE_PGP */

  ViewVC Help
Powered by ViewVC 1.1.5