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

  ViewVC Help
Powered by ViewVC 1.1.5