/[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 135 - (show annotations) (download)
Fri Aug 16 19:03:37 2002 UTC (10 years, 10 months ago) by rabbi
File MIME type: text/plain
File size: 10067 byte(s)
Mixmaster now uses the OpenPGP MDC packets (as specified in RFC 2440-bis06).

Mixmaster will use MDC packets if the MDC flag is found in the recipient's
PGP key, or by default if it is encrypting with AES.

New keys generated with Mixmaster will have the MDC flag placed in the key's
preferences. Also, cipher preferences are now advertised as CAST5, AES128,
3DES.
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.6 2002/08/16 19:03:37 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_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, 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 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, 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 #endif /* USE_PGP */

  ViewVC Help
Powered by ViewVC 1.1.5