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 #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   case 1:
42     return "RSA";
43   case 2:
44     return "RSA";
45   case 3:
46     return "RSA";
47   case 16:
48     return "ElG";
49   case 17:
50     return "DSA";
51   case 20:
52     return "ElG";
53   default:
54     return "unk";
55   }
56 }
57
58
59
60 /* unused */
61
62 #if 0
63
64 static const char *hashalgbytype (unsigned char type)
65 {
66   switch (type) {
67   case 1:
68     return "MD5";
69   case 2:
70     return "SHA1";
71   case 3:
72     return "RIPE-MD/160";
73   case 4:
74     return "HAVAL";
75   default:
76     return "unknown";
77   }
78 }
79
80 #endif
81
82 short pgp_canencrypt (unsigned char type)
83 {
84   switch (type) {
85   case 1:
86   case 2:
87   case 16:
88   case 20:
89     return 1;
90   default:
91     return 0;
92   }
93 }
94
95 short pgp_cansign (unsigned char type)
96 {
97   switch (type) {
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     q = sp->next;
129     FREE (&sp);
130   }
131
132   *sigp = NULL;
133 }
134
135 void pgp_free_uid (pgp_uid_t ** upp)
136 {
137   pgp_uid_t *up, *q;
138
139   if (!upp || !*upp)
140     return;
141   for (up = *upp; up; up = q) {
142     q = up->next;
143     pgp_free_sig (&up->sigs);
144     FREE (&up->addr);
145     FREE (&up);
146   }
147
148   *upp = NULL;
149 }
150
151 pgp_uid_t *pgp_copy_uids (pgp_uid_t * up, pgp_key_t parent)
152 {
153   pgp_uid_t *l = NULL;
154   pgp_uid_t **lp = &l;
155
156   for (; up; up = up->next) {
157     *lp = safe_calloc (1, sizeof (pgp_uid_t));
158     (*lp)->trust = up->trust;
159     (*lp)->flags = up->flags;
160     (*lp)->addr = safe_strdup (up->addr);
161     (*lp)->parent = parent;
162     lp = &(*lp)->next;
163   }
164
165   return l;
166 }
167
168 static void _pgp_free_key (pgp_key_t * kpp)
169 {
170   pgp_key_t kp;
171
172   if (!kpp || !*kpp)
173     return;
174
175   kp = *kpp;
176
177   pgp_free_uid (&kp->address);
178   FREE (&kp->keyid);
179   FREE (kpp);
180 }
181
182 pgp_key_t pgp_remove_key (pgp_key_t * klist, pgp_key_t key)
183 {
184   pgp_key_t *last;
185   pgp_key_t p, q, r;
186
187   if (!klist || !*klist || !key)
188     return NULL;
189
190   if (key->parent && key->parent != key)
191     key = key->parent;
192
193   last = klist;
194   for (p = *klist; p && p != key; p = p->next)
195     last = &p->next;
196
197   if (!p)
198     return NULL;
199
200   for (q = p->next, r = p; q && q->parent == p; q = q->next)
201     r = q;
202
203   if (r)
204     r->next = NULL;
205
206   *last = q;
207   return q;
208 }
209
210 void pgp_free_key (pgp_key_t * kpp)
211 {
212   pgp_key_t p, q, r;
213
214   if (!kpp || !*kpp)
215     return;
216
217   if ((*kpp)->parent && (*kpp)->parent != *kpp)
218     *kpp = (*kpp)->parent;
219
220   /* Order is important here:
221    *
222    * - First free all children.
223    * - If we are an orphan (i.e., our parent was not in the key list),
224    *   free our parent.
225    * - free ourselves.
226    */
227
228   for (p = *kpp; p; p = q) {
229     for (q = p->next; q && q->parent == p; q = r) {
230       r = q->next;
231       _pgp_free_key (&q);
232     }
233     if (p->parent)
234       _pgp_free_key (&p->parent);
235
236     _pgp_free_key (&p);
237   }
238
239   *kpp = NULL;
240 }