-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy patherror.c
More file actions
241 lines (227 loc) · 7.07 KB
/
error.c
File metadata and controls
241 lines (227 loc) · 7.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/*
* Error reporting functions
*/
#include <stdio.h>
#include <time.h>
#include "pgpr_internal.h"
static const char unknown_error[] = "Unknown error";
const char *pgprErrorStr(pgprRC rc)
{
switch (rc) {
case PGPR_OK:
return "No error";
case PGPR_ERROR_INTERNAL:
return "Internal PGP parser error";
case PGPR_ERROR_BAD_ARGUMENT:
return "Bad argument";
case PGPR_ERROR_NO_MEMORY:
return "Out of memory";
case PGPR_ERROR_CORRUPT_PGP_PACKET:
return "Corrupt PGP packet";
case PGPR_ERROR_UNEXPECTED_PGP_PACKET:
return "Unexpected PGP packet";
case PGPR_ERROR_UNSUPPORTED_VERSION:
return "Unsupported packet version";
case PGPR_ERROR_UNSUPPORTED_ALGORITHM:
return "Unsupported pubkey algorithm";
case PGPR_ERROR_UNSUPPORTED_CURVE:
return "Unsupported pubkey curve";
case PGPR_ERROR_UNSUPPORTED_DIGEST:
return "Unsupported digest algorithm";
case PGPR_ERROR_NO_CREATION_TIME:
return "Signature without creation time";
case PGPR_ERROR_DUPLICATE_DATA:
return "Duplicate data in signature";
case PGPR_ERROR_UNKNOWN_CRITICAL_PKT:
return "Unknown critical packet in signature";
case PGPR_ERROR_BAD_PUBKEY_STRUCTURE:
return "Bad pubkey structure";
case PGPR_ERROR_MISSING_SELFSIG:
return "Pubkey misses a self-signature";
case PGPR_ERROR_SELFSIG_VERIFICATION:
return "Pubkey self-signature verification failure";
case PGPR_ERROR_BAD_SIGNATURE:
return "Bad signature";
case PGPR_ERROR_REJECTED_PUBKEY:
return "Pubkey not accepted by crypto backend";
case PGPR_ERROR_REJECTED_SIGNATURE:
return "Signature not accepted by crypto backend";
case PGPR_ERROR_SIGNATURE_FROM_FUTURE:
return "Signature was created in the future";
case PGPR_ERROR_SIGNATURE_EXPIRED:
return "Signature has expired";
case PGPR_ERROR_KEY_EXPIRED:
return "Key has expired";
case PGPR_ERROR_KEY_REVOKED:
return "Key has been revoked";
case PGPR_ERROR_PRIMARY_REVOKED:
return "Primary key has been revoked";
case PGPR_ERROR_KEY_NOT_VALID:
return "Key has no valid binding signature";
case PGPR_ERROR_KEY_NO_SIGNING:
return "Key is not suitable for signing";
case PGPR_ERROR_KEY_CREATED_AFTER_SIG:
return "Key has been created after the signature";
case PGPR_ERROR_ARMOR_NO_BEGIN_PGP:
return "Armored data begin mismatch";
case PGPR_ERROR_ARMOR_NO_END_PGP:
return "Armored data end mismatch";
case PGPR_ERROR_ARMOR_CRC_CHECK:
return "Armored data CRC mismatch";
case PGPR_ERROR_ARMOR_BODY_DECODE:
return "Armored data decoding failed";
case PGPR_ERROR_ARMOR_CRC_DECODE:
return "Armored data CRC decoding failed";
default:
break;
}
return unknown_error;
}
static char *format_keyid(pgprKeyID_t keyid, char *userid)
{
static const char hex[] = "0123456789abcdef";
char *keyidstr = pgprMalloc(sizeof(pgprKeyID_t) * 2 + 1);
int i;
if (!keyidstr)
return NULL;
for (i = 0; i < sizeof(pgprKeyID_t); i++) {
keyidstr[2 * i] = hex[keyid[i] >> 4 & 15];
keyidstr[2 * i + 1] = hex[keyid[i] & 15];
}
keyidstr[2 * i] = 0;
if (!userid) {
return keyidstr;
} else {
char *ret = NULL;
pgprAsprintf(&ret, "%s (%s)", keyidstr, userid);
free(keyidstr);
return ret;
}
}
static char *format_time(time_t *t)
{
char dbuf[BUFSIZ];
struct tm _tm, *tms;
char *ret = NULL;
tms = localtime_r(t, &_tm);
if (!(tms && strftime(dbuf, sizeof(dbuf), "%Y-%m-%d %H:%M:%S", tms) > 0)) {
pgprAsprintf(&ret, "Invalid date (%lld)", (long long int)t);
} else {
ret = pgprStrdup(dbuf);
}
return ret;
}
static void pgprAddKeyLint(pgprItem key, char **lints, const char *msg)
{
char *keyid = format_keyid(key->keyid, key->tag == PGPRTAG_PUBLIC_SUBKEY ? NULL : key->userid);
char *main_keyid = key->tag == PGPRTAG_PUBLIC_SUBKEY ? format_keyid(key->mainid, key->userid) : NULL;
if (!msg || !keyid || (key->tag == PGPRTAG_PUBLIC_SUBKEY && !main_keyid))
goto done;
if (key->tag == PGPRTAG_PUBLIC_SUBKEY) {
/* special case the message about subkeys with a revoked primary key */
if (key->revoked == 2)
pgprAsprintf(lints, "Key %s is a subkey of key %s, which has been revoked", keyid, main_keyid);
else
pgprAsprintf(lints, "Subkey %s of key %s %s", keyid, main_keyid, msg);
} else {
pgprAsprintf(lints, "Key %s %s", keyid, msg);
}
done:
free(keyid);
free(main_keyid);
}
static void pgprAddSigLint(pgprItem sig, char **lints, const char *msg)
{
if (msg)
pgprAsprintf(lints, "Signature %s", msg);
}
static char *format_expired(uint32_t created, uint32_t expire)
{
time_t exptime = (time_t)created + expire;
char *expdate = format_time(&exptime);
char *msg = NULL;
if (!expdate)
return NULL;
pgprAsprintf(&msg, "expired on %s", expdate);
free(expdate);
return msg;
}
void pgprAddLint(pgprItem item, char **lints, pgprRC error)
{
const char *msg = NULL;
char *exp_msg;
if (error == PGPR_OK || !lints)
return;
if (*lints)
free(*lints);
*lints = NULL;
/* if we have a suitable item we can make a better error message */
if (item && (item->tag == PGPRTAG_PUBLIC_KEY || item->tag == PGPRTAG_PUBLIC_SUBKEY)) {
switch (error) {
case PGPR_ERROR_UNSUPPORTED_VERSION:
pgprAsprintf(lints, "Unsupported pubkey version (V%d)", item->version);
return;
case PGPR_ERROR_KEY_EXPIRED:
exp_msg = format_expired(item->time, item->key_expire);
pgprAddKeyLint(item, lints, exp_msg);
free(exp_msg);
return;
case PGPR_ERROR_KEY_REVOKED:
case PGPR_ERROR_PRIMARY_REVOKED:
pgprAddKeyLint(item, lints, "has been revoked");
return;
case PGPR_ERROR_KEY_NOT_VALID:
pgprAddKeyLint(item, lints, "has no valid binding signature");
return;
case PGPR_ERROR_KEY_NO_SIGNING:
pgprAddKeyLint(item, lints, "is not suitable for signing");
return;
case PGPR_ERROR_KEY_CREATED_AFTER_SIG:
pgprAddKeyLint(item, lints, "has been created after the signature");
return;
default:
break;
}
}
if (item && item->tag == PGPRTAG_SIGNATURE) {
switch (error) {
case PGPR_ERROR_UNSUPPORTED_VERSION:
pgprAsprintf(lints, "Unsupported signature version (V%d)", item->version);
return;
case PGPR_ERROR_UNSUPPORTED_DIGEST:
pgprAsprintf(lints, "Unsupported digest algorithm (%d)", item->hash_algo);
return;
case PGPR_ERROR_SIGNATURE_EXPIRED:
exp_msg = format_expired(item->time, item->sig_expire);
pgprAddSigLint(item, lints, exp_msg);
free(exp_msg);
return;
default:
break;
}
}
if (item) {
switch (error) {
case PGPR_ERROR_UNSUPPORTED_VERSION:
pgprAsprintf(lints, "Unsupported packet version (V%d)", item->version);
return;
case PGPR_ERROR_UNSUPPORTED_ALGORITHM:
pgprAsprintf(lints, "Unsupported pubkey algorithm (%d)", item->pubkey_algo);
return;
case PGPR_ERROR_UNSUPPORTED_CURVE:
if (item->alg)
pgprAsprintf(lints, "Unsupported pubkey curve (%d)", item->alg->curve);
else
pgprAsprintf(lints, "Unsupported pubkey curve");
return;
default:
break;
}
}
msg = pgprErrorStr(error);
if (msg == unknown_error) {
pgprAsprintf(lints, "Unknown error (%d)", error);
} else {
*lints = pgprStrdup(msg);
}
}