Coverage Report

Created: 2023-06-07 06:15

/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] kpp PGP Key info to free
147
 */
148
static void key_free(struct PgpKeyInfo **kpp)
149
0
{
150
0
  if (!kpp || !*kpp)
151
0
    return;
152
153
0
  struct PgpKeyInfo *kp = *kpp;
154
155
0
  pgp_uid_free(&kp->address);
156
0
  FREE(&kp->keyid);
157
0
  FREE(&kp->fingerprint);
158
0
  FREE(kpp);
159
0
}
160
161
/**
162
 * pgp_remove_key - Remove a PGP key from a list
163
 * @param[out] klist List of PGP Keys
164
 * @param[in]  key   Key to remove
165
 * @retval ptr Updated list of PGP Keys
166
 */
167
struct PgpKeyInfo *pgp_remove_key(struct PgpKeyInfo **klist, struct PgpKeyInfo *key)
168
0
{
169
0
  if (!klist || !*klist || !key)
170
0
    return NULL;
171
172
0
  struct PgpKeyInfo **last = NULL;
173
0
  struct PgpKeyInfo *p = NULL, *q = NULL, *r = NULL;
174
175
0
  if (key->parent && (key->parent != key))
176
0
    key = key->parent;
177
178
0
  last = klist;
179
0
  for (p = *klist; p && p != key; p = p->next)
180
0
    last = &p->next;
181
182
0
  if (!p)
183
0
    return NULL;
184
185
0
  for (q = p->next, r = p; q && q->parent == p; q = q->next)
186
0
    r = q;
187
188
0
  if (r)
189
0
    r->next = NULL;
190
191
0
  *last = q;
192
0
  return q;
193
0
}
194
195
/**
196
 * pgp_key_free - Free a PGP key info
197
 * @param[out] kpp PGP key info to free
198
 */
199
void pgp_key_free(struct PgpKeyInfo **kpp)
200
0
{
201
0
  if (!kpp || !*kpp)
202
0
    return;
203
204
0
  struct PgpKeyInfo *p = NULL, *q = NULL, *r = NULL;
205
206
0
  if ((*kpp)->parent && ((*kpp)->parent != *kpp))
207
0
    *kpp = (*kpp)->parent;
208
209
  /* Order is important here:
210
   *
211
   * - First free all children.
212
   * - If we are an orphan (i.e., our parent was not in the key list),
213
   *   free our parent.
214
   * - free ourselves.  */
215
216
0
  for (p = *kpp; p; p = q)
217
0
  {
218
0
    for (q = p->next; q && q->parent == p; q = r)
219
0
    {
220
0
      r = q->next;
221
0
      key_free(&q);
222
0
    }
223
224
0
    key_free(&p->parent);
225
0
    key_free(&p);
226
0
  }
227
228
0
  *kpp = NULL;
229
0
}