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