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