~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/certdb/alg1485.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* alg1485.c - implementation of RFCs 1485, 1779 and 2253.
 
2
 *
 
3
 * The contents of this file are subject to the Mozilla Public
 
4
 * License Version 1.1 (the "License"); you may not use this file
 
5
 * except in compliance with the License. You may obtain a copy of
 
6
 * the License at http://www.mozilla.org/MPL/
 
7
 * 
 
8
 * Software distributed under the License is distributed on an "AS
 
9
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
10
 * implied. See the License for the specific language governing
 
11
 * rights and limitations under the License.
 
12
 * 
 
13
 * The Original Code is the Netscape security libraries.
 
14
 * 
 
15
 * The Initial Developer of the Original Code is Netscape
 
16
 * Communications Corporation.  Portions created by Netscape are 
 
17
 * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
 
18
 * Rights Reserved.
 
19
 * 
 
20
 * Contributor(s):
 
21
 * 
 
22
 * Alternatively, the contents of this file may be used under the
 
23
 * terms of the GNU General Public License Version 2 or later (the
 
24
 * "GPL"), in which case the provisions of the GPL are applicable 
 
25
 * instead of those above.  If you wish to allow use of your 
 
26
 * version of this file only under the terms of the GPL and not to
 
27
 * allow others to use your version of this file under the MPL,
 
28
 * indicate your decision by deleting the provisions above and
 
29
 * replace them with the notice and other provisions required by
 
30
 * the GPL.  If you do not delete the provisions above, a recipient
 
31
 * may use your version of this file under either the MPL or the
 
32
 * GPL.
 
33
 */
 
34
 
 
35
#include "prprf.h"
 
36
#include "cert.h"
 
37
#include "xconst.h"
 
38
#include "genname.h"
 
39
#include "secitem.h"
 
40
#include "secerr.h"
 
41
 
 
42
/* for better RFC 2253 compliance. */
 
43
#define NSS_STRICT_RFC_2253_VALUES_ONLY 1
 
44
 
 
45
struct NameToKind {
 
46
    const char * name;
 
47
    unsigned int maxLen; /* max bytes in UTF8 encoded string value */
 
48
    SECOidTag    kind;
 
49
};
 
50
 
 
51
/* Add new entries to this table, and maybe to function CERT_ParseRFC1485AVA */
 
52
static const struct NameToKind name2kinds[] = {
 
53
/* keywords given in RFC 2253 */
 
54
    { "CN",                      64, SEC_OID_AVA_COMMON_NAME              },
 
55
    { "L",                      128, SEC_OID_AVA_LOCALITY                 },
 
56
    { "ST",                     128, SEC_OID_AVA_STATE_OR_PROVINCE        },
 
57
    { "O",                       64, SEC_OID_AVA_ORGANIZATION_NAME        },
 
58
    { "OU",                      64, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME },
 
59
    { "C",                        2, SEC_OID_AVA_COUNTRY_NAME             },
 
60
    { "STREET",                 128, SEC_OID_AVA_STREET_ADDRESS           },
 
61
    { "DC",                     128, SEC_OID_AVA_DC                       },
 
62
    { "UID",                    256, SEC_OID_RFC1274_UID                  },
 
63
 
 
64
#ifndef NSS_STRICT_RFC_2253_KEYWORDS_ONLY
 
65
/* NSS legacy keywords */
 
66
    { "dnQualifier",          32767, SEC_OID_AVA_DN_QUALIFIER             },
 
67
    { "E",                      128, SEC_OID_PKCS9_EMAIL_ADDRESS          },
 
68
    { "MAIL",                   256, SEC_OID_RFC1274_MAIL                 },
 
69
 
 
70
#ifndef NSS_LEGACY_KEYWORDS_ONLY
 
71
/* values from draft-ietf-ldapbis-user-schema-05 */
 
72
    { "SN",                      64, SEC_OID_AVA_SURNAME                  },
 
73
    { "serialNumber",            64, SEC_OID_AVA_SERIAL_NUMBER            },
 
74
    { "title",                   64, SEC_OID_AVA_TITLE                    },
 
75
    { "postalAddress",          128, SEC_OID_AVA_POSTAL_ADDRESS           },
 
76
    { "postalCode",              40, SEC_OID_AVA_POSTAL_CODE              },
 
77
    { "postOfficeBox",           40, SEC_OID_AVA_POST_OFFICE_BOX          },
 
78
    { "givenName",               64, SEC_OID_AVA_GIVEN_NAME               },
 
79
    { "initials",                64, SEC_OID_AVA_INITIALS                 },
 
80
    { "generationQualifier",     64, SEC_OID_AVA_GENERATION_QUALIFIER     },
 
81
    { "houseIdentifier",         64, SEC_OID_AVA_HOUSE_IDENTIFIER         },
 
82
#if 0 /* removed.  Not yet in any IETF draft or RFC. */
 
83
    { "pseudonym",               64, SEC_OID_AVA_PSEUDONYM                },
 
84
#endif
 
85
#endif
 
86
#endif
 
87
    { 0,                        256, SEC_OID_UNKNOWN                      }
 
88
};
 
89
 
 
90
#define C_DOUBLE_QUOTE '\042'
 
91
 
 
92
#define C_BACKSLASH '\134'
 
93
 
 
94
#define C_EQUAL '='
 
95
 
 
96
#define OPTIONAL_SPACE(c) \
 
97
    (((c) == ' ') || ((c) == '\r') || ((c) == '\n'))
 
98
 
 
99
#define SPECIAL_CHAR(c)                                         \
 
100
    (((c) == ',') || ((c) == '=') || ((c) == C_DOUBLE_QUOTE) || \
 
101
     ((c) == '\r') || ((c) == '\n') || ((c) == '+') ||          \
 
102
     ((c) == '<') || ((c) == '>') || ((c) == '#') ||            \
 
103
     ((c) == ';') || ((c) == C_BACKSLASH))
 
104
 
 
105
 
 
106
#define IS_PRINTABLE(c)                                         \
 
107
    ((((c) >= 'a') && ((c) <= 'z')) ||                          \
 
108
     (((c) >= 'A') && ((c) <= 'Z')) ||                          \
 
109
     (((c) >= '0') && ((c) <= '9')) ||                          \
 
110
     ((c) == ' ') ||                                            \
 
111
     ((c) == '\'') ||                                           \
 
112
     ((c) == '\050') ||                         /* ( */         \
 
113
     ((c) == '\051') ||                         /* ) */         \
 
114
     (((c) >= '+') && ((c) <= '/')) ||          /* + , - . / */ \
 
115
     ((c) == ':') ||                                            \
 
116
     ((c) == '=') ||                                            \
 
117
     ((c) == '?'))
 
118
 
 
119
int
 
120
cert_AVAOidTagToMaxLen(SECOidTag tag)
 
121
{
 
122
    const struct NameToKind *n2k = name2kinds;
 
123
 
 
124
    while (n2k->kind != tag && n2k->kind != SEC_OID_UNKNOWN) {
 
125
        ++n2k;
 
126
    }
 
127
    return (n2k->kind != SEC_OID_UNKNOWN) ? n2k->maxLen : -1;
 
128
}
 
129
 
 
130
static PRBool
 
131
IsPrintable(unsigned char *data, unsigned len)
 
132
{
 
133
    unsigned char ch, *end;
 
134
 
 
135
    end = data + len;
 
136
    while (data < end) {
 
137
        ch = *data++;
 
138
        if (!IS_PRINTABLE(ch)) {
 
139
            return PR_FALSE;
 
140
        }
 
141
    }
 
142
    return PR_TRUE;
 
143
}
 
144
 
 
145
static PRBool
 
146
Is7Bit(unsigned char *data, unsigned len)
 
147
{
 
148
    unsigned char ch, *end;
 
149
 
 
150
    end = data + len;
 
151
    while (data < end) {
 
152
        ch = *data++;
 
153
        if ((ch & 0x80)) {
 
154
            return PR_FALSE;
 
155
        }
 
156
    }
 
157
    return PR_TRUE;
 
158
}
 
159
 
 
160
static void
 
161
skipSpace(char **pbp, char *endptr)
 
162
{
 
163
    char *bp = *pbp;
 
164
    while (bp < endptr && OPTIONAL_SPACE(*bp)) {
 
165
        bp++;
 
166
    }
 
167
    *pbp = bp;
 
168
}
 
169
 
 
170
static SECStatus
 
171
scanTag(char **pbp, char *endptr, char *tagBuf, int tagBufSize)
 
172
{
 
173
    char *bp, *tagBufp;
 
174
    int taglen;
 
175
 
 
176
    PORT_Assert(tagBufSize > 0);
 
177
    
 
178
    /* skip optional leading space */
 
179
    skipSpace(pbp, endptr);
 
180
    if (*pbp == endptr) {
 
181
        /* nothing left */
 
182
        return SECFailure;
 
183
    }
 
184
    
 
185
    /* fill tagBuf */
 
186
    taglen = 0;
 
187
    bp = *pbp;
 
188
    tagBufp = tagBuf;
 
189
    while (bp < endptr && !OPTIONAL_SPACE(*bp) && (*bp != C_EQUAL)) {
 
190
        if (++taglen >= tagBufSize) {
 
191
            *pbp = bp;
 
192
            return SECFailure;
 
193
        }
 
194
        *tagBufp++ = *bp++;
 
195
    }
 
196
    /* null-terminate tagBuf -- guaranteed at least one space left */
 
197
    *tagBufp++ = 0;
 
198
    *pbp = bp;
 
199
    
 
200
    /* skip trailing spaces till we hit something - should be an equal sign */
 
201
    skipSpace(pbp, endptr);
 
202
    if (*pbp == endptr) {
 
203
        /* nothing left */
 
204
        return SECFailure;
 
205
    }
 
206
    if (**pbp != C_EQUAL) {
 
207
        /* should be an equal sign */
 
208
        return SECFailure;
 
209
    }
 
210
    /* skip over the equal sign */
 
211
    (*pbp)++;
 
212
    
 
213
    return SECSuccess;
 
214
}
 
215
 
 
216
static SECStatus
 
217
scanVal(char **pbp, char *endptr, char *valBuf, int valBufSize)  
 
218
{
 
219
    char *bp, *valBufp;
 
220
    int vallen;
 
221
    PRBool isQuoted;
 
222
    
 
223
    PORT_Assert(valBufSize > 0);
 
224
    
 
225
    /* skip optional leading space */
 
226
    skipSpace(pbp, endptr);
 
227
    if(*pbp == endptr) {
 
228
        /* nothing left */
 
229
        return SECFailure;
 
230
    }
 
231
    
 
232
    bp = *pbp;
 
233
    
 
234
    /* quoted? */
 
235
    if (*bp == C_DOUBLE_QUOTE) {
 
236
        isQuoted = PR_TRUE;
 
237
        /* skip over it */
 
238
        bp++;
 
239
    } else {
 
240
        isQuoted = PR_FALSE;
 
241
    }
 
242
    
 
243
    valBufp = valBuf;
 
244
    vallen = 0;
 
245
    while (bp < endptr) {
 
246
        char c = *bp;
 
247
        if (c == C_BACKSLASH) {
 
248
            /* escape character */
 
249
            bp++;
 
250
            if (bp >= endptr) {
 
251
                /* escape charater must appear with paired char */
 
252
                *pbp = bp;
 
253
                return SECFailure;
 
254
            }
 
255
        } else if (!isQuoted && SPECIAL_CHAR(c)) {
 
256
            /* unescaped special and not within quoted value */
 
257
            break;
 
258
        } else if (c == C_DOUBLE_QUOTE) {
 
259
            /* reached unescaped double quote */
 
260
            break;
 
261
        }
 
262
        /* append character */
 
263
        vallen++;
 
264
        if (vallen >= valBufSize) {
 
265
            *pbp = bp;
 
266
            return SECFailure;
 
267
        }
 
268
        *valBufp++ = *bp++;
 
269
    }
 
270
    
 
271
    /* stip trailing spaces from unquoted values */
 
272
    if (!isQuoted) {
 
273
        if (valBufp > valBuf) {
 
274
            valBufp--;
 
275
            while ((valBufp > valBuf) && OPTIONAL_SPACE(*valBufp)) {
 
276
                valBufp--;
 
277
            }
 
278
            valBufp++;
 
279
        }
 
280
    }
 
281
    
 
282
    if (isQuoted) {
 
283
        /* insist that we stopped on a double quote */
 
284
        if (*bp != C_DOUBLE_QUOTE) {
 
285
            *pbp = bp;
 
286
            return SECFailure;
 
287
        }
 
288
        /* skip over the quote and skip optional space */
 
289
        bp++;
 
290
        skipSpace(&bp, endptr);
 
291
    }
 
292
    
 
293
    *pbp = bp;
 
294
    
 
295
    if (valBufp == valBuf) {
 
296
        /* empty value -- not allowed */
 
297
        return SECFailure;
 
298
    }
 
299
    
 
300
    /* null-terminate valBuf -- guaranteed at least one space left */
 
301
    *valBufp++ = 0;
 
302
    
 
303
    return SECSuccess;
 
304
}
 
305
 
 
306
CERTAVA *
 
307
CERT_ParseRFC1485AVA(PRArenaPool *arena, char **pbp, char *endptr,
 
308
                    PRBool singleAVA) 
 
309
{
 
310
    CERTAVA *a;
 
311
    const struct NameToKind *n2k;
 
312
    int vt;
 
313
    int valLen;
 
314
    char *bp;
 
315
 
 
316
    char tagBuf[32];
 
317
    char valBuf[384];
 
318
 
 
319
    if (scanTag(pbp, endptr, tagBuf, sizeof(tagBuf)) == SECFailure ||
 
320
        scanVal(pbp, endptr, valBuf, sizeof(valBuf)) == SECFailure) {
 
321
        PORT_SetError(SEC_ERROR_INVALID_AVA);
 
322
        return 0;
 
323
    }
 
324
 
 
325
    /* insist that if we haven't finished we've stopped on a separator */
 
326
    bp = *pbp;
 
327
    if (bp < endptr) {
 
328
        if (singleAVA || (*bp != ',' && *bp != ';')) {
 
329
            PORT_SetError(SEC_ERROR_INVALID_AVA);
 
330
            *pbp = bp;
 
331
            return 0;
 
332
        }
 
333
        /* ok, skip over separator */
 
334
        bp++;
 
335
    }
 
336
    *pbp = bp;
 
337
 
 
338
    for (n2k = name2kinds; n2k->name; n2k++) {
 
339
        if (PORT_Strcasecmp(n2k->name, tagBuf) == 0) {
 
340
            valLen = PORT_Strlen(valBuf);
 
341
            if (n2k->kind == SEC_OID_AVA_COUNTRY_NAME) {
 
342
                vt = SEC_ASN1_PRINTABLE_STRING;
 
343
                if (valLen != 2) {
 
344
                    PORT_SetError(SEC_ERROR_INVALID_AVA);
 
345
                    return 0;
 
346
                }
 
347
                if (!IsPrintable((unsigned char*) valBuf, 2)) {
 
348
                    PORT_SetError(SEC_ERROR_INVALID_AVA);
 
349
                    return 0;
 
350
                }
 
351
            } else if ((n2k->kind == SEC_OID_PKCS9_EMAIL_ADDRESS) ||
 
352
                       (n2k->kind == SEC_OID_RFC1274_MAIL)) {
 
353
                vt = SEC_ASN1_IA5_STRING;
 
354
            } else {
 
355
                /* Hack -- for rationale see X.520 DirectoryString defn */
 
356
                if (IsPrintable((unsigned char*)valBuf, valLen)) {
 
357
                    vt = SEC_ASN1_PRINTABLE_STRING;
 
358
                } else if (Is7Bit((unsigned char *)valBuf, valLen)) {
 
359
                    vt = SEC_ASN1_T61_STRING;
 
360
                } else {
 
361
                    /* according to RFC3280, UTF8String is preferred encoding */
 
362
                    vt = SEC_ASN1_UTF8_STRING;
 
363
                }
 
364
            }
 
365
            a = CERT_CreateAVA(arena, n2k->kind, vt, (char *) valBuf);
 
366
            return a;
 
367
        }
 
368
    }
 
369
    /* matched no kind -- invalid tag */
 
370
    PORT_SetError(SEC_ERROR_INVALID_AVA);
 
371
    return 0;
 
372
}
 
373
 
 
374
static CERTName *
 
375
ParseRFC1485Name(char *buf, int len)
 
376
{
 
377
    SECStatus rv;
 
378
    CERTName *name;
 
379
    char *bp, *e;
 
380
    CERTAVA *ava;
 
381
    CERTRDN *rdn;
 
382
 
 
383
    name = CERT_CreateName(NULL);
 
384
    if (name == NULL) {
 
385
        return NULL;
 
386
    }
 
387
    
 
388
    e = buf + len;
 
389
    bp = buf;
 
390
    while (bp < e) {
 
391
        ava = CERT_ParseRFC1485AVA(name->arena, &bp, e, PR_FALSE);
 
392
        if (ava == 0) goto loser;
 
393
        rdn = CERT_CreateRDN(name->arena, ava, 0);
 
394
        if (rdn == 0) goto loser;
 
395
        rv = CERT_AddRDN(name, rdn);
 
396
        if (rv) goto loser;
 
397
        skipSpace(&bp, e);
 
398
    }
 
399
 
 
400
    if (name->rdns[0] == 0) {
 
401
        /* empty name -- illegal */
 
402
        goto loser;
 
403
    }
 
404
 
 
405
    /* Reverse order of RDNS to comply with RFC */
 
406
    {
 
407
        CERTRDN **firstRdn;
 
408
        CERTRDN **lastRdn;
 
409
        CERTRDN *tmp;
 
410
        
 
411
        /* get first one */
 
412
        firstRdn = name->rdns;
 
413
        
 
414
        /* find last one */
 
415
        lastRdn = name->rdns;
 
416
        while (*lastRdn) lastRdn++;
 
417
        lastRdn--;
 
418
        
 
419
        /* reverse list */
 
420
        for ( ; firstRdn < lastRdn; firstRdn++, lastRdn--) {
 
421
            tmp = *firstRdn;
 
422
            *firstRdn = *lastRdn;
 
423
            *lastRdn = tmp;
 
424
        }
 
425
    }
 
426
    
 
427
    /* return result */
 
428
    return name;
 
429
    
 
430
  loser:
 
431
    CERT_DestroyName(name);
 
432
    return NULL;
 
433
}
 
434
 
 
435
CERTName *
 
436
CERT_AsciiToName(char *string)
 
437
{
 
438
    CERTName *name;
 
439
    name = ParseRFC1485Name(string, PORT_Strlen(string));
 
440
    return name;
 
441
}
 
442
 
 
443
/************************************************************************/
 
444
 
 
445
typedef struct stringBufStr {
 
446
    char *buffer;
 
447
    unsigned offset;
 
448
    unsigned size;
 
449
} stringBuf;
 
450
 
 
451
#define DEFAULT_BUFFER_SIZE 200
 
452
 
 
453
static SECStatus
 
454
AppendStr(stringBuf *bufp, char *str)
 
455
{
 
456
    char *buf;
 
457
    unsigned bufLen, bufSize, len;
 
458
    int size = 0;
 
459
 
 
460
    /* Figure out how much to grow buf by (add in the '\0') */
 
461
    buf = bufp->buffer;
 
462
    bufLen = bufp->offset;
 
463
    len = PORT_Strlen(str);
 
464
    bufSize = bufLen + len;
 
465
    if (!buf) {
 
466
        bufSize++;
 
467
        size = PR_MAX(DEFAULT_BUFFER_SIZE,bufSize*2);
 
468
        buf = (char *) PORT_Alloc(size);
 
469
        bufp->size = size;
 
470
    } else if (bufp->size < bufSize) {
 
471
        size = bufSize*2;
 
472
        buf =(char *) PORT_Realloc(buf,size);
 
473
        bufp->size = size;
 
474
    }
 
475
    if (!buf) {
 
476
        PORT_SetError(SEC_ERROR_NO_MEMORY);
 
477
        return SECFailure;
 
478
    }
 
479
    bufp->buffer = buf;
 
480
    bufp->offset = bufSize;
 
481
 
 
482
    /* Concatenate str onto buf */
 
483
    buf = buf + bufLen;
 
484
    if (bufLen) buf--;                  /* stomp on old '\0' */
 
485
    PORT_Memcpy(buf, str, len+1);               /* put in new null */
 
486
    return SECSuccess;
 
487
}
 
488
 
 
489
SECStatus
 
490
CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, int srclen)
 
491
{
 
492
    int i, reqLen=0;
 
493
    char *d = dst;
 
494
    PRBool needsQuoting = PR_FALSE;
 
495
    char lastC = 0;
 
496
    
 
497
    /* need to make an initial pass to determine if quoting is needed */
 
498
    for (i = 0; i < srclen; i++) {
 
499
        char c = src[i];
 
500
        reqLen++;
 
501
        if (!needsQuoting && (SPECIAL_CHAR(c) ||
 
502
            (OPTIONAL_SPACE(c) && OPTIONAL_SPACE(lastC)))) {
 
503
            /* entirety will need quoting */
 
504
            needsQuoting = PR_TRUE;
 
505
        }
 
506
        if (c == C_DOUBLE_QUOTE || c == C_BACKSLASH) {
 
507
            /* this char will need escaping */
 
508
            reqLen++;
 
509
        }
 
510
        lastC = c;
 
511
    }
 
512
    /* if it begins or ends in optional space it needs quoting */
 
513
    if (!needsQuoting && srclen > 0 && 
 
514
        (OPTIONAL_SPACE(src[srclen-1]) || OPTIONAL_SPACE(src[0]))) {
 
515
        needsQuoting = PR_TRUE;
 
516
    }
 
517
    
 
518
    if (needsQuoting) reqLen += 2;
 
519
 
 
520
    /* space for terminal null */
 
521
    reqLen++;
 
522
    
 
523
    if (reqLen > dstlen) {
 
524
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
 
525
        return SECFailure;
 
526
    }
 
527
    
 
528
    d = dst;
 
529
    if (needsQuoting) *d++ = C_DOUBLE_QUOTE;
 
530
    for (i = 0; i < srclen; i++) {
 
531
        char c = src[i];
 
532
        if (c == C_DOUBLE_QUOTE || c == C_BACKSLASH) {
 
533
            /* escape it */
 
534
            *d++ = C_BACKSLASH;
 
535
        }
 
536
        *d++ = c;
 
537
    }
 
538
    if (needsQuoting) *d++ = C_DOUBLE_QUOTE;
 
539
    *d++ = 0;
 
540
    return SECSuccess;
 
541
}
 
542
 
 
543
/* convert an OID to dotted-decimal representation */
 
544
/* Returns a string that must be freed with PR_smprintf_free(), */
 
545
char *
 
546
CERT_GetOidString(const SECItem *oid)
 
547
{
 
548
    PRUint8 *end;
 
549
    PRUint8 *d;
 
550
    PRUint8 *e;
 
551
    char *a         = NULL;
 
552
    char *b;
 
553
 
 
554
#define MAX_OID_LEN 1024 /* bytes */
 
555
 
 
556
    if (oid->len > MAX_OID_LEN) {
 
557
        PORT_SetError(SEC_ERROR_INPUT_LEN);
 
558
        return NULL;
 
559
    }
 
560
 
 
561
    /* d will point to the next sequence of bytes to decode */
 
562
    d = (PRUint8 *)oid->data;
 
563
    /* end points to one past the legitimate data */
 
564
    end = &d[ oid->len ];
 
565
 
 
566
    /*
 
567
     * Check for our pseudo-encoded single-digit OIDs
 
568
     */
 
569
    if( (*d == 0x80) && (2 == oid->len) ) {
 
570
        /* Funky encoding.  The second byte is the number */
 
571
        a = PR_smprintf("%lu", (PRUint32)d[1]);
 
572
        if( (char *)NULL == a ) {
 
573
            PORT_SetError(SEC_ERROR_NO_MEMORY);
 
574
            return (char *)NULL;
 
575
        }
 
576
        return a;
 
577
    }
 
578
 
 
579
    for( ; d < end; d = &e[1] ) {
 
580
    
 
581
        for( e = d; e < end; e++ ) {
 
582
            if( 0 == (*e & 0x80) ) {
 
583
                break;
 
584
            }
 
585
        }
 
586
    
 
587
        if( ((e-d) > 4) || (((e-d) == 4) && (*d & 0x70)) ) {
 
588
            /* More than a 32-bit number */
 
589
        } else {
 
590
            PRUint32 n = 0;
 
591
      
 
592
            switch( e-d ) {
 
593
            case 4:
 
594
                n |= ((PRUint32)(e[-4] & 0x0f)) << 28;
 
595
            case 3:
 
596
                n |= ((PRUint32)(e[-3] & 0x7f)) << 21;
 
597
            case 2:
 
598
                n |= ((PRUint32)(e[-2] & 0x7f)) << 14;
 
599
            case 1:
 
600
                n |= ((PRUint32)(e[-1] & 0x7f)) <<  7;
 
601
            case 0:
 
602
                n |= ((PRUint32)(e[-0] & 0x7f))      ;
 
603
            }
 
604
      
 
605
            if( (char *)NULL == a ) {
 
606
                /* This is the first number.. decompose it */
 
607
                PRUint32 one = PR_MIN(n/40, 2); /* never > 2 */
 
608
                PRUint32 two = n - one * 40;
 
609
        
 
610
                a = PR_smprintf("OID.%lu.%lu", one, two);
 
611
                if( (char *)NULL == a ) {
 
612
                    PORT_SetError(SEC_ERROR_NO_MEMORY);
 
613
                    return (char *)NULL;
 
614
                }
 
615
            } else {
 
616
                b = PR_smprintf("%s.%lu", a, n);
 
617
                if( (char *)NULL == b ) {
 
618
                    PR_smprintf_free(a);
 
619
                    PORT_SetError(SEC_ERROR_NO_MEMORY);
 
620
                    return (char *)NULL;
 
621
                }
 
622
        
 
623
                PR_smprintf_free(a);
 
624
                a = b;
 
625
            }
 
626
        }
 
627
    }
 
628
 
 
629
    return a;
 
630
}
 
631
 
 
632
/* convert DER-encoded hex to a string */
 
633
static SECItem *
 
634
get_hex_string(SECItem *data)
 
635
{
 
636
    SECItem *rv;
 
637
    unsigned int i, j;
 
638
    static const char hex[] = { "0123456789ABCDEF" };
 
639
 
 
640
    /* '#' + 2 chars per octet + terminator */
 
641
    rv = SECITEM_AllocItem(NULL, NULL, data->len*2 + 2);
 
642
    if (!rv) {
 
643
        return NULL;
 
644
    }
 
645
    rv->data[0] = '#';
 
646
    rv->len = 1 + 2 * data->len;
 
647
    for (i=0; i<data->len; i++) {
 
648
        j = data->data[i];
 
649
        rv->data[2*i+1] = hex[j >> 4];
 
650
        rv->data[2*i+2] = hex[j & 15];
 
651
    }
 
652
    rv->data[rv->len] = 0;
 
653
    return rv;
 
654
}
 
655
 
 
656
static SECStatus
 
657
AppendAVA(stringBuf *bufp, CERTAVA *ava)
 
658
{
 
659
    const struct NameToKind *n2k = name2kinds;
 
660
    const char *tagName;
 
661
    unsigned len, maxLen;
 
662
    int tag;
 
663
    SECStatus rv;
 
664
    SECItem *avaValue = NULL;
 
665
    char *unknownTag = NULL;
 
666
    PRBool hexValue = PR_FALSE;
 
667
    char tmpBuf[384];
 
668
 
 
669
    tag = CERT_GetAVATag(ava);
 
670
    while (n2k->kind != tag && n2k->kind != SEC_OID_UNKNOWN) {
 
671
        ++n2k;
 
672
    }
 
673
    if (n2k->kind != SEC_OID_UNKNOWN) {
 
674
        tagName = n2k->name;
 
675
    } else {
 
676
        /* handle unknown attribute types per RFC 2253 */
 
677
        tagName = unknownTag = CERT_GetOidString(&ava->type);
 
678
        if (!tagName)
 
679
            return SECFailure;
 
680
    }
 
681
    maxLen = n2k->maxLen;
 
682
 
 
683
#ifdef NSS_STRICT_RFC_2253_VALUES_ONLY
 
684
    if (!unknownTag)
 
685
#endif
 
686
    avaValue = CERT_DecodeAVAValue(&ava->value);
 
687
    if(!avaValue) {
 
688
        /* the attribute value is not recognized, get the hex value */
 
689
        avaValue = get_hex_string(&ava->value);
 
690
        if(!avaValue) {
 
691
            if (unknownTag) PR_smprintf_free(unknownTag);
 
692
            return SECFailure;
 
693
        }
 
694
        hexValue = PR_TRUE;
 
695
    }
 
696
 
 
697
    /* Check value length */
 
698
    if (avaValue->len > maxLen + 3) {  /* must be room for "..." */
 
699
        /* avaValue is a UTF8 string, freshly allocated and returned to us 
 
700
        ** by CERT_DecodeAVAValue just above, so we can modify it here.
 
701
        ** See if we're in the middle of a multi-byte UTF8 character.
 
702
        */
 
703
        while (((avaValue->data[maxLen] & 0xc0) == 0x80) && maxLen > 0) {
 
704
           maxLen--;
 
705
        }
 
706
        /* add elipsis to signify truncation. */
 
707
        avaValue->data[maxLen++] = '.'; 
 
708
        avaValue->data[maxLen++] = '.';
 
709
        avaValue->data[maxLen++] = '.';
 
710
        avaValue->data[maxLen]   = 0;
 
711
        avaValue->len = maxLen;
 
712
    }
 
713
 
 
714
    len = PORT_Strlen(tagName);
 
715
    if (len+1 > sizeof(tmpBuf)) {
 
716
        if (unknownTag) PR_smprintf_free(unknownTag);
 
717
        SECITEM_FreeItem(avaValue, PR_TRUE);
 
718
        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
 
719
        return SECFailure;
 
720
    }
 
721
    PORT_Memcpy(tmpBuf, tagName, len);
 
722
    if (unknownTag) PR_smprintf_free(unknownTag);
 
723
    tmpBuf[len++] = '=';
 
724
    
 
725
    /* escape and quote as necessary - don't quote hex strings */
 
726
    if (hexValue) {
 
727
        /* appent avaValue to tmpBuf */
 
728
        if (avaValue->len + len + 1 > sizeof tmpBuf) {
 
729
            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
730
            rv = SECFailure;
 
731
        } else {
 
732
            PORT_Strncpy(tmpBuf+len, (char *)avaValue->data, avaValue->len + 1);
 
733
            rv = SECSuccess;
 
734
        }
 
735
    } else 
 
736
        rv = CERT_RFC1485_EscapeAndQuote(tmpBuf+len, sizeof(tmpBuf)-len, 
 
737
                                     (char *)avaValue->data, avaValue->len);
 
738
    SECITEM_FreeItem(avaValue, PR_TRUE);
 
739
    if (rv) return SECFailure;
 
740
    
 
741
    rv = AppendStr(bufp, tmpBuf);
 
742
    return rv;
 
743
}
 
744
 
 
745
char *
 
746
CERT_NameToAscii(CERTName *name)
 
747
{
 
748
    CERTRDN** rdns;
 
749
    CERTRDN** lastRdn;
 
750
    CERTRDN** rdn;
 
751
    PRBool first = PR_TRUE;
 
752
    stringBuf strBuf = { NULL, 0, 0 };
 
753
    
 
754
    rdns = name->rdns;
 
755
    if (rdns == NULL) {
 
756
        return NULL;
 
757
    }
 
758
    
 
759
    /* find last RDN */
 
760
    lastRdn = rdns;
 
761
    while (*lastRdn) lastRdn++;
 
762
    lastRdn--;
 
763
    
 
764
    /*
 
765
     * Loop over name contents in _reverse_ RDN order appending to string
 
766
     */
 
767
    for (rdn = lastRdn; rdn >= rdns; rdn--) {
 
768
        CERTAVA** avas = (*rdn)->avas;
 
769
        CERTAVA* ava;
 
770
        PRBool newRDN = PR_TRUE;
 
771
 
 
772
        /* 
 
773
         * XXX Do we need to traverse the AVAs in reverse order, too?
 
774
         */
 
775
        while (avas && (ava = *avas++) != NULL) {
 
776
            SECStatus rv;
 
777
            /* Put in comma or plus separator */
 
778
            if (!first) {
 
779
                /* Use of spaces is deprecated in RFC 2253. */
 
780
                rv = AppendStr(&strBuf, newRDN ? "," : "+");
 
781
                if (rv) goto loser;
 
782
            } else {
 
783
                first = PR_FALSE;
 
784
            }
 
785
            
 
786
            /* Add in tag type plus value into buf */
 
787
            rv = AppendAVA(&strBuf, ava);
 
788
            if (rv) goto loser;
 
789
            newRDN = PR_FALSE;
 
790
        }
 
791
    }
 
792
    return strBuf.buffer;
 
793
loser:
 
794
    if (strBuf.buffer) {
 
795
        PORT_Free(strBuf.buffer);
 
796
    }
 
797
    return NULL;
 
798
}
 
799
 
 
800
/*
 
801
 * Return the string representation of a DER encoded distinguished name
 
802
 * "dername" - The DER encoded name to convert
 
803
 */
 
804
char *
 
805
CERT_DerNameToAscii(SECItem *dername)
 
806
{
 
807
    int rv;
 
808
    PRArenaPool *arena = NULL;
 
809
    CERTName name;
 
810
    char *retstr = NULL;
 
811
    
 
812
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
813
    
 
814
    if ( arena == NULL) {
 
815
        goto loser;
 
816
    }
 
817
    
 
818
    rv = SEC_QuickDERDecodeItem(arena, &name, CERT_NameTemplate, dername);
 
819
    
 
820
    if ( rv != SECSuccess ) {
 
821
        goto loser;
 
822
    }
 
823
 
 
824
    retstr = CERT_NameToAscii(&name);
 
825
 
 
826
loser:
 
827
    if ( arena != NULL ) {
 
828
        PORT_FreeArena(arena, PR_FALSE);
 
829
    }
 
830
    
 
831
    return(retstr);
 
832
}
 
833
 
 
834
static char *
 
835
CERT_GetNameElement(PRArenaPool *arena, CERTName *name, int wantedTag)
 
836
{
 
837
    CERTRDN** rdns;
 
838
    CERTRDN *rdn;
 
839
    char *buf = 0;
 
840
    
 
841
    rdns = name->rdns;
 
842
    while (rdns && (rdn = *rdns++) != 0) {
 
843
        CERTAVA** avas = rdn->avas;
 
844
        CERTAVA*  ava;
 
845
        while (avas && (ava = *avas++) != 0) {
 
846
            int tag = CERT_GetAVATag(ava);
 
847
            if ( tag == wantedTag ) {
 
848
                SECItem *decodeItem = CERT_DecodeAVAValue(&ava->value);
 
849
                if(!decodeItem) {
 
850
                    return NULL;
 
851
                }
 
852
                if (arena) {
 
853
                    buf = (char *)PORT_ArenaZAlloc(arena,decodeItem->len + 1);
 
854
                } else {
 
855
                    buf = (char *)PORT_ZAlloc(decodeItem->len + 1);
 
856
                }
 
857
                if ( buf ) {
 
858
                    PORT_Memcpy(buf, decodeItem->data, decodeItem->len);
 
859
                    buf[decodeItem->len] = 0;
 
860
                }
 
861
                SECITEM_FreeItem(decodeItem, PR_TRUE);
 
862
                goto done;
 
863
            }
 
864
        }
 
865
    }
 
866
    
 
867
  done:
 
868
    return buf;
 
869
}
 
870
 
 
871
char *
 
872
CERT_GetCertificateEmailAddress(CERTCertificate *cert)
 
873
{
 
874
    char *rawEmailAddr = NULL;
 
875
    SECItem subAltName;
 
876
    SECStatus rv;
 
877
    CERTGeneralName *nameList = NULL;
 
878
    CERTGeneralName *current;
 
879
    PRArenaPool *arena = NULL;
 
880
    int i;
 
881
    
 
882
    subAltName.data = NULL;
 
883
 
 
884
    rawEmailAddr = CERT_GetNameElement(cert->arena, &(cert->subject),
 
885
                                                 SEC_OID_PKCS9_EMAIL_ADDRESS);
 
886
    if ( rawEmailAddr == NULL ) {
 
887
        rawEmailAddr = CERT_GetNameElement(cert->arena, &(cert->subject), 
 
888
                                                        SEC_OID_RFC1274_MAIL);
 
889
    }
 
890
    if ( rawEmailAddr == NULL) {
 
891
 
 
892
        rv = CERT_FindCertExtension(cert,  SEC_OID_X509_SUBJECT_ALT_NAME, 
 
893
                                                                &subAltName);
 
894
        if (rv != SECSuccess) {
 
895
            goto finish;
 
896
        }
 
897
        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
898
        if (!arena) {
 
899
            goto finish;
 
900
        }
 
901
        nameList = current = CERT_DecodeAltNameExtension(arena, &subAltName);
 
902
        if (!nameList ) {
 
903
            goto finish;
 
904
        }
 
905
        if (nameList != NULL) {
 
906
            do {
 
907
                if (current->type == certDirectoryName) {
 
908
                    rawEmailAddr = CERT_GetNameElement(cert->arena,
 
909
                        &(current->name.directoryName), 
 
910
                                               SEC_OID_PKCS9_EMAIL_ADDRESS);
 
911
                    if ( rawEmailAddr == NULL ) {
 
912
                        rawEmailAddr = CERT_GetNameElement(cert->arena,
 
913
                          &(current->name.directoryName), SEC_OID_RFC1274_MAIL);
 
914
                    }
 
915
                } else if (current->type == certRFC822Name) {
 
916
                    rawEmailAddr = (char*)PORT_ArenaZAlloc(cert->arena,
 
917
                                                current->name.other.len + 1);
 
918
                    if (!rawEmailAddr) {
 
919
                        goto finish;
 
920
                    }
 
921
                    PORT_Memcpy(rawEmailAddr, current->name.other.data, 
 
922
                                current->name.other.len);
 
923
                    rawEmailAddr[current->name.other.len] = '\0';
 
924
                }
 
925
                if (rawEmailAddr) {
 
926
                    break;
 
927
                }
 
928
                current = cert_get_next_general_name(current);
 
929
            } while (current != nameList);
 
930
        }
 
931
    }
 
932
    if (rawEmailAddr) {
 
933
        for (i = 0; i <= (int) PORT_Strlen(rawEmailAddr); i++) {
 
934
            rawEmailAddr[i] = tolower(rawEmailAddr[i]);
 
935
        }
 
936
    } 
 
937
 
 
938
finish:
 
939
 
 
940
    /* Don't free nameList, it's part of the arena. */
 
941
 
 
942
    if (arena) {
 
943
        PORT_FreeArena(arena, PR_FALSE);
 
944
    }
 
945
 
 
946
    if ( subAltName.data ) {
 
947
        SECITEM_FreeItem(&subAltName, PR_FALSE);
 
948
    }
 
949
 
 
950
    return(rawEmailAddr);
 
951
}
 
952
 
 
953
static char *
 
954
appendStringToBuf(char *dest, char *src, PRUint32 *pRemaining)
 
955
{
 
956
    PRUint32 len;
 
957
    if (dest && src && src[0] && *pRemaining > (len = PL_strlen(src))) {
 
958
        PRUint32 i;
 
959
        for (i = 0; i < len; ++i)
 
960
            dest[i] = tolower(src[i]);
 
961
        dest[len] = 0;
 
962
        dest        += len + 1;
 
963
        *pRemaining -= len + 1;
 
964
    }
 
965
    return dest;
 
966
}
 
967
 
 
968
static char *
 
969
appendItemToBuf(char *dest, SECItem *src, PRUint32 *pRemaining)
 
970
{
 
971
    if (dest && src && src->data && src->len && src->data[0] && 
 
972
        *pRemaining > src->len + 1 ) {
 
973
        PRUint32 len = src->len;
 
974
        PRUint32 i;
 
975
        for (i = 0; i < len && src->data[i] ; ++i)
 
976
            dest[i] = tolower(src->data[i]);
 
977
        dest[len] = 0;
 
978
        dest        += len + 1;
 
979
        *pRemaining -= len + 1;
 
980
    }
 
981
    return dest;
 
982
}
 
983
 
 
984
/* Returns a pointer to an environment-like string, a series of 
 
985
** null-terminated strings, terminated by a zero-length string.
 
986
** This function is intended to be internal to NSS.
 
987
*/
 
988
char *
 
989
cert_GetCertificateEmailAddresses(CERTCertificate *cert)
 
990
{
 
991
    char *           rawEmailAddr = NULL;
 
992
    char *           addrBuf      = NULL;
 
993
    char *           pBuf         = NULL;
 
994
    PRArenaPool *    tmpArena     = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
995
    PRUint32         maxLen       = 0;
 
996
    PRInt32          finalLen     = 0;
 
997
    SECStatus        rv;
 
998
    SECItem          subAltName;
 
999
    
 
1000
    if (!tmpArena) 
 
1001
        return addrBuf;
 
1002
 
 
1003
    subAltName.data = NULL;
 
1004
    maxLen = cert->derCert.len;
 
1005
    PORT_Assert(maxLen);
 
1006
    if (!maxLen) 
 
1007
        maxLen = 2000;  /* a guess, should never happen */
 
1008
 
 
1009
    pBuf = addrBuf = (char *)PORT_ArenaZAlloc(tmpArena, maxLen + 1);
 
1010
    if (!addrBuf) 
 
1011
        goto loser;
 
1012
 
 
1013
    rawEmailAddr = CERT_GetNameElement(tmpArena, &cert->subject,
 
1014
                                       SEC_OID_PKCS9_EMAIL_ADDRESS);
 
1015
    pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen);
 
1016
 
 
1017
    rawEmailAddr = CERT_GetNameElement(tmpArena, &cert->subject, 
 
1018
                                       SEC_OID_RFC1274_MAIL);
 
1019
    pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen);
 
1020
 
 
1021
    rv = CERT_FindCertExtension(cert,  SEC_OID_X509_SUBJECT_ALT_NAME, 
 
1022
                                &subAltName);
 
1023
    if (rv == SECSuccess && subAltName.data) {
 
1024
        CERTGeneralName *nameList     = NULL;
 
1025
 
 
1026
        if (!!(nameList = CERT_DecodeAltNameExtension(tmpArena, &subAltName))) {
 
1027
            CERTGeneralName *current = nameList;
 
1028
            do {
 
1029
                if (current->type == certDirectoryName) {
 
1030
                    rawEmailAddr = CERT_GetNameElement(tmpArena,
 
1031
                                               &current->name.directoryName, 
 
1032
                                               SEC_OID_PKCS9_EMAIL_ADDRESS);
 
1033
                    pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen);
 
1034
 
 
1035
                    rawEmailAddr = CERT_GetNameElement(tmpArena,
 
1036
                                              &current->name.directoryName, 
 
1037
                                              SEC_OID_RFC1274_MAIL);
 
1038
                    pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen);
 
1039
                } else if (current->type == certRFC822Name) {
 
1040
                    pBuf = appendItemToBuf(pBuf, &current->name.other, &maxLen);
 
1041
                }
 
1042
                current = cert_get_next_general_name(current);
 
1043
            } while (current != nameList);
 
1044
        }
 
1045
        SECITEM_FreeItem(&subAltName, PR_FALSE);
 
1046
        /* Don't free nameList, it's part of the tmpArena. */
 
1047
    }
 
1048
    /* now copy superstring to cert's arena */
 
1049
    finalLen = (pBuf - addrBuf) + 1;
 
1050
    pBuf = NULL;
 
1051
    if (finalLen > 1) {
 
1052
        pBuf = PORT_ArenaAlloc(cert->arena, finalLen);
 
1053
        if (pBuf) {
 
1054
            PORT_Memcpy(pBuf, addrBuf, finalLen);
 
1055
        }
 
1056
    }
 
1057
loser:
 
1058
    if (tmpArena)
 
1059
        PORT_FreeArena(tmpArena, PR_FALSE);
 
1060
 
 
1061
    return pBuf;
 
1062
}
 
1063
 
 
1064
/* returns pointer to storage in cert's arena.  Storage remains valid
 
1065
** as long as cert's reference count doesn't go to zero.
 
1066
** Caller should strdup or otherwise copy.
 
1067
*/
 
1068
const char *    /* const so caller won't muck with it. */
 
1069
CERT_GetFirstEmailAddress(CERTCertificate * cert)
 
1070
{
 
1071
    if (cert && cert->emailAddr && cert->emailAddr[0])
 
1072
        return (const char *)cert->emailAddr;
 
1073
    return NULL;
 
1074
}
 
1075
 
 
1076
/* returns pointer to storage in cert's arena.  Storage remains valid
 
1077
** as long as cert's reference count doesn't go to zero.
 
1078
** Caller should strdup or otherwise copy.
 
1079
*/
 
1080
const char *    /* const so caller won't muck with it. */
 
1081
CERT_GetNextEmailAddress(CERTCertificate * cert, const char * prev)
 
1082
{
 
1083
    if (cert && prev && prev[0]) {
 
1084
        PRUint32 len = PL_strlen(prev);
 
1085
        prev += len + 1;
 
1086
        if (prev && prev[0])
 
1087
            return prev;
 
1088
    }
 
1089
    return NULL;
 
1090
}
 
1091
 
 
1092
/* This is seriously bogus, now that certs store their email addresses in
 
1093
** subject Alternative Name extensions. 
 
1094
** Returns a string allocated by PORT_StrDup, which the caller must free.
 
1095
*/
 
1096
char *
 
1097
CERT_GetCertEmailAddress(CERTName *name)
 
1098
{
 
1099
    char *rawEmailAddr;
 
1100
    char *emailAddr;
 
1101
 
 
1102
    
 
1103
    rawEmailAddr = CERT_GetNameElement(NULL, name, SEC_OID_PKCS9_EMAIL_ADDRESS);
 
1104
    if ( rawEmailAddr == NULL ) {
 
1105
        rawEmailAddr = CERT_GetNameElement(NULL, name, SEC_OID_RFC1274_MAIL);
 
1106
    }
 
1107
    emailAddr = CERT_FixupEmailAddr(rawEmailAddr);
 
1108
    if ( rawEmailAddr ) {
 
1109
        PORT_Free(rawEmailAddr);
 
1110
    }
 
1111
    return(emailAddr);
 
1112
}
 
1113
 
 
1114
/* The return value must be freed with PORT_Free. */
 
1115
char *
 
1116
CERT_GetCommonName(CERTName *name)
 
1117
{
 
1118
    return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_COMMON_NAME));
 
1119
}
 
1120
 
 
1121
char *
 
1122
CERT_GetCountryName(CERTName *name)
 
1123
{
 
1124
    return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_COUNTRY_NAME));
 
1125
}
 
1126
 
 
1127
char *
 
1128
CERT_GetLocalityName(CERTName *name)
 
1129
{
 
1130
    return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_LOCALITY));
 
1131
}
 
1132
 
 
1133
char *
 
1134
CERT_GetStateName(CERTName *name)
 
1135
{
 
1136
    return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_STATE_OR_PROVINCE));
 
1137
}
 
1138
 
 
1139
char *
 
1140
CERT_GetOrgName(CERTName *name)
 
1141
{
 
1142
    return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_ORGANIZATION_NAME));
 
1143
}
 
1144
 
 
1145
char *
 
1146
CERT_GetDomainComponentName(CERTName *name)
 
1147
{
 
1148
    return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_DC));
 
1149
}
 
1150
 
 
1151
char *
 
1152
CERT_GetOrgUnitName(CERTName *name)
 
1153
{
 
1154
    return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME));
 
1155
}
 
1156
 
 
1157
char *
 
1158
CERT_GetDnQualifier(CERTName *name)
 
1159
{
 
1160
    return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_DN_QUALIFIER));
 
1161
}
 
1162
 
 
1163
char *
 
1164
CERT_GetCertUid(CERTName *name)
 
1165
{
 
1166
    return(CERT_GetNameElement(NULL, name, SEC_OID_RFC1274_UID));
 
1167
}
 
1168