Coverage Report

Created: 2023-09-25 07:17

/src/neomutt/ncrypt/pgplib.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file
3
 * Misc PGP helper routines
4
 *
5
 * @authors
6
 * Copyright (C) 1997-2002 Thomas Roessler <roessler@does-not-exist.org>
7
 *
8
 * @copyright
9
 * This program is free software: you can redistribute it and/or modify it under
10
 * the terms of the GNU General Public License as published by the Free Software
11
 * Foundation, either version 2 of the License, or (at your option) any later
12
 * version.
13
 *
14
 * This program is distributed in the hope that it will be useful, but WITHOUT
15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17
 * details.
18
 *
19
 * You should have received a copy of the GNU General Public License along with
20
 * this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
/**
24
 * @page crypt_pgplib Misc PGP helper routines
25
 *
26
 * Misc PGP helper routines
27
 */
28
29
#include "config.h"
30
#include <stdbool.h>
31
#include "mutt/lib.h"
32
#ifdef CRYPT_BACKEND_CLASSIC_PGP
33
#include "pgplib.h"
34
#endif
35
36
/**
37
 * pgp_pkalgbytype - Get the name of the algorithm from its ID
38
 * @param type Algorithm ID
39
 * @retval ptr Algorithm name
40
 */
41
const char *pgp_pkalgbytype(unsigned char type)
42
0
{
43
0
  switch (type)
44
0
  {
45
0
    case 1:
46
0
      return "RSA";
47
0
    case 2:
48
0
      return "RSA";
49
0
    case 3:
50
0
      return "RSA";
51
0
    case 16:
52
0
      return "ElG";
53
0
    case 17:
54
0
      return "DSA";
55
0
    case 20:
56
0
      return "ElG";
57
0
    default:
58
0
      return "unk";
59
0
  }
60
0
}
61
62
/**
63
 * pgp_canencrypt - Does this algorithm ID support encryption?
64
 * @param type Algorithm ID
65
 * @retval true Algorithm does support encryption
66
 */
67
bool pgp_canencrypt(unsigned char type)
68
0
{
69
0
  switch (type)
70
0
  {
71
0
    case 1:
72
0
    case 2:
73
0
    case 16:
74
0
    case 20:
75
0
      return true;
76
0
    default:
77
0
      return false;
78
0
  }
79
0
}
80
81
/**
82
 * pgp_cansign - Does this algorithm ID support signing?
83
 * @param type Algorithm ID
84
 * @retval true Algorithm does support signing
85
 */
86
bool pgp_cansign(unsigned char type)
87
0
{
88
0
  switch (type)
89
0
  {
90
0
    case 1:
91
0
    case 3:
92
0
    case 17:
93
0
    case 20:
94
0
      return true;
95
0
    default:
96
0
      return false;
97
0
  }
98
0
}
99
100
/**
101
 * pgp_uid_free - Free a PGP UID
102
 * @param[out] upp PGP UID to free
103
 */
104
static void pgp_uid_free(struct PgpUid **upp)
105
0
{
106
0
  struct PgpUid *up = NULL, *q = NULL;
107
108
0
  if (!upp || !*upp)
109
0
    return;
110
0
  for (up = *upp; up; up = q)
111
0
  {
112
0
    q = up->next;
113
0
    FREE(&up->addr);
114
0
    FREE(&up);
115
0
  }
116
117
0
  *upp = NULL;
118
0
}
119
120
/**
121
 * pgp_copy_uids - Copy a list of PGP UIDs
122
 * @param up     List of PGP UIDs
123
 * @param parent Parent PGP key
124
 * @retval ptr New list of PGP UIDs
125
 */
126
struct PgpUid *pgp_copy_uids(struct PgpUid *up, struct PgpKeyInfo *parent)
127
0
{
128
0
  struct PgpUid *l = NULL;
129
0
  struct PgpUid **lp = &l;
130
131
0
  for (; up; up = up->next)
132
0
  {
133
0
    *lp = mutt_mem_calloc(1, sizeof(struct PgpUid));
134
0
    (*lp)->trust = up->trust;
135
0
    (*lp)->flags = up->flags;
136
0
    (*lp)->addr = mutt_str_dup(up->addr);
137
0
    (*lp)->parent = parent;
138
0
    lp = &(*lp)->next;
139
0
  }
140
141
0
  return l;
142
0
}
143
144
/**
145
 * key_free - Free a PGP Key info
146
 * @param[out] ptr PGP Key info to free
147
 */
148
static void key_free(struct PgpKeyInfo **ptr)
149
0
{
150
0
  if (!ptr || !*ptr)
151
0
    return;
152
153
0
  struct PgpKeyInfo *key = *ptr;
154
155
0
  pgp_uid_free(&key->address);
156
0
  FREE(&key->keyid);
157
0
  FREE(&key->fingerprint);
158
159
0
  FREE(ptr);
160
0
}
161
162
/**
163
 * pgp_remove_key - Remove a PGP key from a list
164
 * @param[out] klist List of PGP Keys
165
 * @param[in]  key   Key to remove
166
 * @retval ptr Updated list of PGP Keys
167
 */
168
struct PgpKeyInfo *pgp_remove_key(struct PgpKeyInfo **klist, struct PgpKeyInfo *key)
169
0
{
170
0
  if (!klist || !*klist || !key)
171
0
    return NULL;
172
173
0
  struct PgpKeyInfo **last = NULL;
174
0
  struct PgpKeyInfo *p = NULL, *q = NULL, *r = NULL;
175
176
0
  if (key->parent && (key->parent != key))
177
0
    key = key->parent;
178
179
0
  last = klist;
180
0
  for (p = *klist; p && p != key; p = p->next)
181
0
    last = &p->next;
182
183
0
  if (!p)
184
0
    return NULL;
185
186
0
  for (q = p->next, r = p; q && q->parent == p; q = q->next)
187
0
    r = q;
188
189
0
  if (r)
190
0
    r->next = NULL;
191
192
0
  *last = q;
193
0
  return q;
194
0
}
195
196
/**
197
 * pgp_key_free - Free a PGP key info
198
 * @param[out] kpp PGP key info to free
199
 */
200
void pgp_key_free(struct PgpKeyInfo **kpp)
201
0
{
202
0
  if (!kpp || !*kpp)
203
0
    return;
204
205
0
  struct PgpKeyInfo *p = NULL, *q = NULL, *r = NULL;
206
207
0
  if ((*kpp)->parent && ((*kpp)->parent != *kpp))
208
0
    *kpp = (*kpp)->parent;
209
210
  /* Order is important here:
211
   *
212
   * - First free all children.
213
   * - If we are an orphan (i.e., our parent was not in the key list),
214
   *   free our parent.
215
   * - free ourselves.  */
216
217
0
  for (p = *kpp; p; p = q)
218
0
  {
219
0
    for (q = p->next; q && q->parent == p; q = r)
220
0
    {
221
0
      r = q->next;
222
0
      key_free(&q);
223
0
    }
224
225
0
    key_free(&p->parent);
226
0
    key_free(&p);
227
0
  }
228
229
0
  *kpp = NULL;
230
0
}