7c111bd4cc8a5a320adb77214420f43a0a00aa62
[apps/madmutt.git] / pgplib.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1997-2000 Thomas Roessler <roessler@does-not-exist.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 /* Generally useful, pgp-related functions. */
11
12 #if HAVE_CONFIG_H
13 # include "config.h"
14 #endif
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <time.h>
21
22 #include "mutt.h"
23 #include "lib.h"
24 #include "pgplib.h"
25
26 const char *pgp_pkalgbytype (unsigned char type)
27 {
28   switch (type) {
29   case 1:
30     return "RSA";
31   case 2:
32     return "RSA";
33   case 3:
34     return "RSA";
35   case 16:
36     return "ElG";
37   case 17:
38     return "DSA";
39   case 20:
40     return "ElG";
41   default:
42     return "unk";
43   }
44 }
45
46
47
48 /* unused */
49
50 #if 0
51
52 static const char *hashalgbytype (unsigned char type)
53 {
54   switch (type) {
55   case 1:
56     return "MD5";
57   case 2:
58     return "SHA1";
59   case 3:
60     return "RIPE-MD/160";
61   case 4:
62     return "HAVAL";
63   default:
64     return "unknown";
65   }
66 }
67
68 #endif
69
70 short pgp_canencrypt (unsigned char type)
71 {
72   switch (type) {
73   case 1:
74   case 2:
75   case 16:
76   case 20:
77     return 1;
78   default:
79     return 0;
80   }
81 }
82
83 short pgp_cansign (unsigned char type)
84 {
85   switch (type) {
86   case 1:
87   case 3:
88   case 17:
89   case 20:
90     return 1;
91   default:
92     return 0;
93   }
94 }
95
96 /* return values: 
97
98  * 1 = sign only
99  * 2 = encrypt only
100  * 3 = both
101  */
102
103 short pgp_get_abilities (unsigned char type)
104 {
105   return (pgp_canencrypt (type) << 1) | pgp_cansign (type);
106 }
107
108 void pgp_free_sig (pgp_sig_t ** sigp)
109 {
110   pgp_sig_t *sp, *q;
111
112   if (!sigp || !*sigp)
113     return;
114
115   for (sp = *sigp; sp; sp = q) {
116     q = sp->next;
117     FREE (&sp);
118   }
119
120   *sigp = NULL;
121 }
122
123 void pgp_free_uid (pgp_uid_t ** upp)
124 {
125   pgp_uid_t *up, *q;
126
127   if (!upp || !*upp)
128     return;
129   for (up = *upp; up; up = q) {
130     q = up->next;
131     pgp_free_sig (&up->sigs);
132     FREE (&up->addr);
133     FREE (&up);
134   }
135
136   *upp = NULL;
137 }
138
139 pgp_uid_t *pgp_copy_uids (pgp_uid_t * up, pgp_key_t parent)
140 {
141   pgp_uid_t *l = NULL;
142   pgp_uid_t **lp = &l;
143
144   for (; up; up = up->next) {
145     *lp = safe_calloc (1, sizeof (pgp_uid_t));
146     (*lp)->trust = up->trust;
147     (*lp)->flags = up->flags;
148     (*lp)->addr = safe_strdup (up->addr);
149     (*lp)->parent = parent;
150     lp = &(*lp)->next;
151   }
152
153   return l;
154 }
155
156 static void _pgp_free_key (pgp_key_t * kpp)
157 {
158   pgp_key_t kp;
159
160   if (!kpp || !*kpp)
161     return;
162
163   kp = *kpp;
164
165   pgp_free_uid (&kp->address);
166   FREE (&kp->keyid);
167   FREE (kpp);
168 }
169
170 pgp_key_t pgp_remove_key (pgp_key_t * klist, pgp_key_t key)
171 {
172   pgp_key_t *last;
173   pgp_key_t p, q, r;
174
175   if (!klist || !*klist || !key)
176     return NULL;
177
178   if (key->parent && key->parent != key)
179     key = key->parent;
180
181   last = klist;
182   for (p = *klist; p && p != key; p = p->next)
183     last = &p->next;
184
185   if (!p)
186     return NULL;
187
188   for (q = p->next, r = p; q && q->parent == p; q = q->next)
189     r = q;
190
191   if (r)
192     r->next = NULL;
193
194   *last = q;
195   return q;
196 }
197
198 void pgp_free_key (pgp_key_t * kpp)
199 {
200   pgp_key_t p, q, r;
201
202   if (!kpp || !*kpp)
203     return;
204
205   if ((*kpp)->parent && (*kpp)->parent != *kpp)
206     *kpp = (*kpp)->parent;
207
208   /* Order is important here:
209    *
210    * - First free all children.
211    * - If we are an orphan (i.e., our parent was not in the key list),
212    *   free our parent.
213    * - free ourselves.
214    */
215
216   for (p = *kpp; p; p = q) {
217     for (q = p->next; q && q->parent == p; q = r) {
218       r = q->next;
219       _pgp_free_key (&q);
220     }
221     if (p->parent)
222       _pgp_free_key (&p->parent);
223
224     _pgp_free_key (&p);
225   }
226
227   *kpp = NULL;
228 }