/[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 91 - (show annotations) (download)
Wed Jul 10 01:58:49 2002 UTC (10 years, 10 months ago) by rabbi
File MIME type: text/plain
File size: 9476 byte(s)
Added the ability to store the key passphrase in the mix.cfg file instead of
having it compiled into the binary. This offers a number of advantages over the
compiled-in method and still allows for encrypted remote storage of keys.

In order to take advantage of the new changes, the Install script will need to
be modified. As this is being replaced with a proper autoconf system, we're
defering that until later.

The changes we're committing replace PASSPHRASE with PASS_PHRASE, which is read
from the config. If the compiled-in passphrase, PASSPHRASE, is set, that is
used instead. (This is how Mixmaster will function if you use the Install
script.)
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.2 2002/07/10 01:58:49 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, PASS_PHRASE);
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