Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/certhigh/certhtml.c
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
/*
6
 * certhtml.c --- convert a cert to html
7
 */
8
9
#include "seccomon.h"
10
#include "secitem.h"
11
#include "sechash.h"
12
#include "cert.h"
13
#include "keyhi.h"
14
#include "secder.h"
15
#include "prprf.h"
16
#include "secport.h"
17
#include "secasn1.h"
18
#include "pk11func.h"
19
20
static char *hex = "0123456789ABCDEF";
21
22
/*
23
** Convert a der-encoded integer to a hex printable string form
24
*/
25
char *
26
CERT_Hexify(SECItem *i, int do_colon)
27
0
{
28
0
    unsigned char *cp, *end;
29
0
    char *rv, *o;
30
31
0
    if (!i->len) {
32
0
        return PORT_Strdup("00");
33
0
    }
34
35
0
    rv = o = (char *)PORT_Alloc(i->len * 3);
36
0
    if (!rv)
37
0
        return rv;
38
39
0
    cp = i->data;
40
0
    end = cp + i->len;
41
0
    while (cp < end) {
42
0
        unsigned char ch = *cp++;
43
0
        *o++ = hex[(ch >> 4) & 0xf];
44
0
        *o++ = hex[ch & 0xf];
45
0
        if (cp != end) {
46
0
            if (do_colon) {
47
0
                *o++ = ':';
48
0
            }
49
0
        }
50
0
    }
51
0
    *o = 0; /* Null terminate the string */
52
0
    return rv;
53
0
}
54
55
0
#define BREAK "<br>"
56
0
#define BREAKLEN 4
57
0
#define COMMA ", "
58
0
#define COMMALEN 2
59
60
0
#define MAX_OUS 20
61
0
#define MAX_DC MAX_OUS
62
63
char *
64
CERT_FormatName(CERTName *name)
65
0
{
66
0
    CERTRDN **rdns;
67
0
    CERTRDN *rdn;
68
0
    CERTAVA **avas;
69
0
    CERTAVA *ava;
70
0
    char *buf = 0;
71
0
    char *tmpbuf = 0;
72
0
    SECItem *cn = 0;
73
0
    SECItem *email = 0;
74
0
    SECItem *org = 0;
75
0
    SECItem *loc = 0;
76
0
    SECItem *state = 0;
77
0
    SECItem *country = 0;
78
0
    SECItem *dq = 0;
79
80
0
    unsigned len = 0;
81
0
    int tag;
82
0
    int i;
83
0
    int ou_count = 0;
84
0
    int dc_count = 0;
85
0
    PRBool first;
86
0
    SECItem *orgunit[MAX_OUS];
87
0
    SECItem *dc[MAX_DC];
88
89
    /* Loop over name components and gather the interesting ones */
90
0
    rdns = name->rdns;
91
0
    while ((rdn = *rdns++) != 0) {
92
0
        avas = rdn->avas;
93
0
        while ((ava = *avas++) != 0) {
94
0
            tag = CERT_GetAVATag(ava);
95
0
            switch (tag) {
96
0
                case SEC_OID_AVA_COMMON_NAME:
97
0
                    if (cn) {
98
0
                        break;
99
0
                    }
100
0
                    cn = CERT_DecodeAVAValue(&ava->value);
101
0
                    if (!cn) {
102
0
                        goto loser;
103
0
                    }
104
0
                    len += cn->len;
105
                    // cn will always have BREAK after it
106
0
                    len += BREAKLEN;
107
0
                    break;
108
0
                case SEC_OID_AVA_COUNTRY_NAME:
109
0
                    if (country) {
110
0
                        break;
111
0
                    }
112
0
                    country = CERT_DecodeAVAValue(&ava->value);
113
0
                    if (!country) {
114
0
                        goto loser;
115
0
                    }
116
0
                    len += country->len;
117
                    // country may have COMMA after it (if we over-count len,
118
                    // that's fine - we'll just allocate a buffer larger than we
119
                    // need)
120
0
                    len += COMMALEN;
121
0
                    break;
122
0
                case SEC_OID_AVA_LOCALITY:
123
0
                    if (loc) {
124
0
                        break;
125
0
                    }
126
0
                    loc = CERT_DecodeAVAValue(&ava->value);
127
0
                    if (!loc) {
128
0
                        goto loser;
129
0
                    }
130
0
                    len += loc->len;
131
                    // loc may have COMMA after it
132
0
                    len += COMMALEN;
133
0
                    break;
134
0
                case SEC_OID_AVA_STATE_OR_PROVINCE:
135
0
                    if (state) {
136
0
                        break;
137
0
                    }
138
0
                    state = CERT_DecodeAVAValue(&ava->value);
139
0
                    if (!state) {
140
0
                        goto loser;
141
0
                    }
142
0
                    len += state->len;
143
                    // state currently won't have COMMA after it, but this is a
144
                    // (probably vain) attempt to future-proof this code
145
0
                    len += COMMALEN;
146
0
                    break;
147
0
                case SEC_OID_AVA_ORGANIZATION_NAME:
148
0
                    if (org) {
149
0
                        break;
150
0
                    }
151
0
                    org = CERT_DecodeAVAValue(&ava->value);
152
0
                    if (!org) {
153
0
                        goto loser;
154
0
                    }
155
0
                    len += org->len;
156
                    // org will have BREAK after it
157
0
                    len += BREAKLEN;
158
0
                    break;
159
0
                case SEC_OID_AVA_DN_QUALIFIER:
160
0
                    if (dq) {
161
0
                        break;
162
0
                    }
163
0
                    dq = CERT_DecodeAVAValue(&ava->value);
164
0
                    if (!dq) {
165
0
                        goto loser;
166
0
                    }
167
0
                    len += dq->len;
168
                    // dq will have BREAK after it
169
0
                    len += BREAKLEN;
170
0
                    break;
171
0
                case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
172
0
                    if (ou_count < MAX_OUS) {
173
0
                        orgunit[ou_count] = CERT_DecodeAVAValue(&ava->value);
174
0
                        if (!orgunit[ou_count]) {
175
0
                            goto loser;
176
0
                        }
177
0
                        len += orgunit[ou_count++]->len;
178
                        // each ou will have BREAK after it
179
0
                        len += BREAKLEN;
180
0
                    }
181
0
                    break;
182
0
                case SEC_OID_AVA_DC:
183
0
                    if (dc_count < MAX_DC) {
184
0
                        dc[dc_count] = CERT_DecodeAVAValue(&ava->value);
185
0
                        if (!dc[dc_count]) {
186
0
                            goto loser;
187
0
                        }
188
0
                        len += dc[dc_count++]->len;
189
                        // each dc will have BREAK after it
190
0
                        len += BREAKLEN;
191
0
                    }
192
0
                    break;
193
0
                case SEC_OID_PKCS9_EMAIL_ADDRESS:
194
0
                case SEC_OID_RFC1274_MAIL:
195
0
                    if (email) {
196
0
                        break;
197
0
                    }
198
0
                    email = CERT_DecodeAVAValue(&ava->value);
199
0
                    if (!email) {
200
0
                        goto loser;
201
0
                    }
202
0
                    len += email->len;
203
                    // email will have BREAK after it
204
0
                    len += BREAKLEN;
205
0
                    break;
206
0
                default:
207
0
                    break;
208
0
            }
209
0
        }
210
0
    }
211
212
    // there may be a final BREAK
213
0
    len += BREAKLEN;
214
215
    /* allocate buffer */
216
0
    buf = (char *)PORT_Alloc(len);
217
0
    if (!buf) {
218
0
        goto loser;
219
0
    }
220
221
0
    tmpbuf = buf;
222
223
0
    if (cn) {
224
0
        PORT_Memcpy(tmpbuf, cn->data, cn->len);
225
0
        tmpbuf += cn->len;
226
0
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
227
0
        tmpbuf += BREAKLEN;
228
0
    }
229
0
    if (email) {
230
0
        PORT_Memcpy(tmpbuf, email->data, email->len);
231
0
        tmpbuf += (email->len);
232
0
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
233
0
        tmpbuf += BREAKLEN;
234
0
    }
235
0
    for (i = ou_count - 1; i >= 0; i--) {
236
0
        PORT_Memcpy(tmpbuf, orgunit[i]->data, orgunit[i]->len);
237
0
        tmpbuf += (orgunit[i]->len);
238
0
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
239
0
        tmpbuf += BREAKLEN;
240
0
    }
241
0
    if (dq) {
242
0
        PORT_Memcpy(tmpbuf, dq->data, dq->len);
243
0
        tmpbuf += (dq->len);
244
0
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
245
0
        tmpbuf += BREAKLEN;
246
0
    }
247
0
    if (org) {
248
0
        PORT_Memcpy(tmpbuf, org->data, org->len);
249
0
        tmpbuf += (org->len);
250
0
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
251
0
        tmpbuf += BREAKLEN;
252
0
    }
253
0
    for (i = dc_count - 1; i >= 0; i--) {
254
0
        PORT_Memcpy(tmpbuf, dc[i]->data, dc[i]->len);
255
0
        tmpbuf += (dc[i]->len);
256
0
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
257
0
        tmpbuf += BREAKLEN;
258
0
    }
259
0
    first = PR_TRUE;
260
0
    if (loc) {
261
0
        PORT_Memcpy(tmpbuf, loc->data, loc->len);
262
0
        tmpbuf += (loc->len);
263
0
        first = PR_FALSE;
264
0
    }
265
0
    if (state) {
266
0
        if (!first) {
267
0
            PORT_Memcpy(tmpbuf, COMMA, COMMALEN);
268
0
            tmpbuf += COMMALEN;
269
0
        }
270
0
        PORT_Memcpy(tmpbuf, state->data, state->len);
271
0
        tmpbuf += (state->len);
272
0
        first = PR_FALSE;
273
0
    }
274
0
    if (country) {
275
0
        if (!first) {
276
0
            PORT_Memcpy(tmpbuf, COMMA, COMMALEN);
277
0
            tmpbuf += COMMALEN;
278
0
        }
279
0
        PORT_Memcpy(tmpbuf, country->data, country->len);
280
0
        tmpbuf += (country->len);
281
0
        first = PR_FALSE;
282
0
    }
283
0
    if (!first) {
284
0
        PORT_Memcpy(tmpbuf, BREAK, BREAKLEN);
285
0
        tmpbuf += BREAKLEN;
286
0
    }
287
288
0
    *tmpbuf = 0;
289
290
/* fall through and clean */
291
0
loser:
292
0
    if (cn) {
293
0
        SECITEM_FreeItem(cn, PR_TRUE);
294
0
    }
295
0
    if (email) {
296
0
        SECITEM_FreeItem(email, PR_TRUE);
297
0
    }
298
0
    for (i = ou_count - 1; i >= 0; i--) {
299
0
        SECITEM_FreeItem(orgunit[i], PR_TRUE);
300
0
    }
301
0
    if (dq) {
302
0
        SECITEM_FreeItem(dq, PR_TRUE);
303
0
    }
304
0
    if (org) {
305
0
        SECITEM_FreeItem(org, PR_TRUE);
306
0
    }
307
0
    for (i = dc_count - 1; i >= 0; i--) {
308
0
        SECITEM_FreeItem(dc[i], PR_TRUE);
309
0
    }
310
0
    if (loc) {
311
0
        SECITEM_FreeItem(loc, PR_TRUE);
312
0
    }
313
0
    if (state) {
314
0
        SECITEM_FreeItem(state, PR_TRUE);
315
0
    }
316
0
    if (country) {
317
0
        SECITEM_FreeItem(country, PR_TRUE);
318
0
    }
319
320
0
    return (buf);
321
0
}