Rocco Rutte:
[apps/madmutt.git] / pgplib.c
1 /*
2  * Copyright (C) 1997-2000 Thomas Roessler <roessler@does-not-exist.org>
3  * 
4  *     This program is free software; you can redistribute it
5  *     and/or modify it under the terms of the GNU General Public
6  *     License as published by the Free Software Foundation; either
7  *     version 2 of the License, or (at your option) any later
8  *     version.
9  * 
10  *     This program is distributed in the hope that it will be
11  *     useful, but WITHOUT ANY WARRANTY; without even the implied
12  *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13  *     PURPOSE.  See the GNU General Public License for more
14  *     details.
15  * 
16  *     You should have received a copy of the GNU General Public
17  *     License along with this program; if not, write to the Free
18  *     Software Foundation, Inc., 59 Temple Place - Suite 330,
19  *     Boston, MA  02111, USA.
20  */
21
22 /* Generally useful, pgp-related functions. */
23
24 #if HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <time.h>
33
34 #include "mutt.h"
35 #include "lib.h"
36 #include "pgplib.h"
37
38 const char *pgp_pkalgbytype (unsigned char type)
39 {
40   switch (type)
41   {
42   case 1:
43     return "RSA";
44   case 2:
45     return "RSA";
46   case 3:
47     return "RSA";
48   case 16:
49     return "ElG";
50   case 17:
51     return "DSA";
52   case 20:
53     return "ElG";
54   default:
55     return "unk";
56   }
57 }
58
59
60
61 /* unused */
62
63 #if 0
64
65 static const char *hashalgbytype (unsigned char type)
66 {
67   switch (type)
68   {
69   case 1:
70     return "MD5";
71   case 2:
72     return "SHA1";
73   case 3:
74     return "RIPE-MD/160";
75   case 4:
76     return "HAVAL";
77   default:
78     return "unknown";
79   }
80 }
81
82 #endif
83
84 short pgp_canencrypt (unsigned char type)
85 {
86   switch (type)
87   {
88   case 1:
89   case 2:
90   case 16:
91   case 20:
92     return 1;
93   default:
94     return 0;
95   }
96 }
97
98 short pgp_cansign (unsigned char type)
99 {
100   switch (type)
101   {
102   case 1:
103   case 3:
104   case 17:
105   case 20:
106     return 1;
107   default:
108     return 0;
109   }
110 }
111
112 /* return values: 
113
114  * 1 = sign only
115  * 2 = encrypt only
116  * 3 = both
117  */
118
119 short pgp_get_abilities (unsigned char type)
120 {
121   return (pgp_canencrypt (type) << 1) | pgp_cansign (type);
122 }
123
124 void pgp_free_sig (pgp_sig_t **sigp)
125 {
126   pgp_sig_t *sp, *q;
127   
128   if (!sigp || !*sigp)
129     return;
130   
131   for (sp = *sigp; sp; sp = q)
132   {
133     q = sp->next;
134     FREE (&sp);
135   }
136   
137   *sigp = NULL;
138 }
139
140 void pgp_free_uid (pgp_uid_t ** upp)
141 {
142   pgp_uid_t *up, *q;
143
144   if (!upp || !*upp)
145     return;
146   for (up = *upp; up; up = q)
147   {
148     q = up->next;
149     pgp_free_sig (&up->sigs);
150     FREE (&up->addr);
151     FREE (&up);
152   }
153
154   *upp = NULL;
155 }
156
157 pgp_uid_t *pgp_copy_uids (pgp_uid_t *up, pgp_key_t parent)
158 {
159   pgp_uid_t *l = NULL;
160   pgp_uid_t **lp = &l;
161
162   for (; up; up = up->next)
163   {
164     *lp = safe_calloc (1, sizeof (pgp_uid_t));
165     (*lp)->trust  = up->trust;
166     (*lp)->flags  = up->flags;
167     (*lp)->addr   = safe_strdup (up->addr);
168     (*lp)->parent = parent;
169     lp = &(*lp)->next;
170   }
171
172   return l;
173 }
174
175 static void _pgp_free_key (pgp_key_t *kpp)
176 {
177   pgp_key_t kp;
178
179   if (!kpp || !*kpp)
180     return;
181
182   kp = *kpp;
183
184   pgp_free_uid (&kp->address);
185   FREE (&kp->keyid);
186   FREE (kpp);
187 }
188
189 pgp_key_t pgp_remove_key (pgp_key_t *klist, pgp_key_t key)
190 {
191   pgp_key_t *last;
192   pgp_key_t p, q, r;
193
194   if (!klist || !*klist || !key)
195     return NULL;
196
197   if (key->parent && key->parent != key)
198     key = key->parent;
199
200   last = klist;
201   for (p = *klist; p && p != key; p = p->next)
202     last = &p->next;
203
204   if (!p)
205     return NULL;
206
207   for (q = p->next, r = p; q && q->parent == p; q = q->next)
208     r = q;
209
210   if (r)
211     r->next = NULL;
212
213   *last = q;
214   return q;
215 }
216
217 void pgp_free_key (pgp_key_t *kpp)
218 {
219   pgp_key_t p, q, r;
220
221   if (!kpp || !*kpp)
222     return;
223
224   if ((*kpp)->parent && (*kpp)->parent != *kpp)
225     *kpp = (*kpp)->parent;
226   
227   /* Order is important here:
228    *
229    * - First free all children.
230    * - If we are an orphan (i.e., our parent was not in the key list),
231    *   free our parent.
232    * - free ourselves.
233    */
234
235   for (p = *kpp; p; p = q)
236   {
237     for (q = p->next; q && q->parent == p; q = r)
238     {
239       r = q->next;
240       _pgp_free_key (&q);
241     }
242     if (p->parent)
243       _pgp_free_key (&p->parent);
244
245     _pgp_free_key (&p);
246   }
247
248   *kpp = NULL;
249 }
250