~ubuntu-branches/ubuntu/maverick/postfix/maverick-security

« back to all changes in this revision

Viewing changes to src/tls/tls_verify.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones, Wietse Venema, LaMont Jones
  • Date: 2009-06-03 14:17:08 UTC
  • mfrom: (1.1.22 upstream)
  • Revision ID: james.westby@ubuntu.com-20090603141708-o9u59xlor7nmd2x1
[Wietse Venema]

* New upstream release: 2.6.2~rc1

[LaMont Jones]

* move postfix-add-{filter,policy} manpages to section 8, and deliver
* provide: default-mta on ubuntu

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
/*      tls_peer_CN() returns the text CommonName for the peer
31
31
/*      certificate subject, or an empty string if no CommonName was
32
32
/*      found. The result is allocated with mymalloc() and must be
33
 
/*      freed by the caller.
 
33
/*      freed by the caller; it contains UTF-8 without non-printable
 
34
/*      ASCII characters.
34
35
/*
35
36
/*      tls_issuer_CN() returns the text CommonName for the peer
36
37
/*      certificate issuer, or an empty string if no CommonName was
37
38
/*      found. The result is allocated with mymalloc() and must be
38
 
/*      freed by the caller.
 
39
/*      freed by the caller; it contains UTF-8 without non-printable
 
40
/*      ASCII characters.
39
41
/*
40
42
/*      tls_dns_name() returns the string value of a GENERAL_NAME
41
43
/*      from a DNS subjectAltName extension. If non-printable characters
278
280
    int     pos;
279
281
    X509_NAME_ENTRY *entry;
280
282
    ASN1_STRING *entry_str;
281
 
    int     typ;
282
 
    int     len;
283
 
    unsigned char *val;
284
 
    unsigned char *utf;
285
 
    char   *cp;
 
283
    int     asn1_type;
 
284
    int     utf8_length;
 
285
    unsigned char *utf8_value;
 
286
    int     ch;
 
287
    unsigned char *cp;
286
288
 
287
289
    if (name == 0 || (pos = X509_NAME_get_index_by_NID(name, nid, -1)) < 0) {
288
290
        if (gripe != DONT_GRIPE) {
321
323
    }
322
324
 
323
325
    /*
324
 
     * Peername checks are security sensitive, carefully scrutinize the
325
 
     * input!
326
 
     */
327
 
    typ = ASN1_STRING_type(entry_str);
328
 
    len = ASN1_STRING_length(entry_str);
329
 
    val = ASN1_STRING_data(entry_str);
330
 
 
331
 
    /*
332
 
     * http://www.apps.ietf.org/rfc/rfc3280.html#sec-4.1.2.4 Quick Summary:
333
 
     * 
334
 
     * The DirectoryString type is defined as a choice of PrintableString,
335
 
     * TeletexString, BMPString, UTF8String, and UniversalString.  The
336
 
     * UTF8String encoding is the preferred encoding, and all certificates
337
 
     * issued after December 31, 2003 MUST use the UTF8String encoding of
338
 
     * DirectoryString (except as noted below).
339
 
     * 
340
 
     * XXX: 2007, the above has not happened yet (of course), and we continue to
341
 
     * see new certificates with T61STRING (Teletex) attribute values.
342
 
     * 
343
 
     * XXX: 2007, at this time there are only two ASN.1 fixed width multi-byte
344
 
     * string encodings, BMPSTRING (16 bit Unicode) and UniversalString
345
 
     * (32-bit Unicode). The only variable width ASN.1 string encoding is
346
 
     * UTF8 with all the other encodings being 1 byte wide subsets or subsets
347
 
     * of ASCII.
348
 
     * 
349
 
     * Relying on this could simplify the code, because we would never convert
350
 
     * unexpected single-byte encodings, but is involves too many cases to be
351
 
     * sure that we have a complete set and the assumptions may become false.
352
 
     * So, we pessimistically convert encodings not blessed by RFC 2459, and
353
 
     * filter out all types that are not string types as a side-effect of
354
 
     * UTF8 conversion (the ASN.1 library knows which types are string types
355
 
     * and how wide they are...).
356
 
     * 
357
 
     * XXX: Two possible states after switch, either "utf == val" and it MUST
358
 
     * NOT be freed with OPENSSL_free(), or "utf != val" and it MUST be freed
359
 
     * with OPENSSL_free().
360
 
     */
361
 
    switch (typ) {
362
 
    case V_ASN1_PRINTABLESTRING:                /* X.500 portable ASCII
363
 
                                                 * printables */
364
 
    case V_ASN1_IA5STRING:                      /* ISO 646 ~ ASCII */
365
 
    case V_ASN1_T61STRING:                      /* Essentially ISO-Latin */
366
 
    case V_ASN1_UTF8STRING:                     /* UTF8 */
367
 
        utf = val;
368
 
        break;
369
 
 
370
 
    default:
371
 
 
372
 
        /*
373
 
         * May shrink in wash, but BMPSTRING only shrinks by 50%. Others may
374
 
         * shrink by up to 75%. We Sanity check the length before bothering
375
 
         * to copy any large strings to convert to UTF8, only to find out
376
 
         * they don't fit. So long as no new MB types are introduced, and
377
 
         * weird string encodings unsanctioned by RFC 3280, are used in the
378
 
         * issuer or subject DN, this "conservative" estimate will be exact.
379
 
         */
380
 
        len >>= (typ == V_ASN1_BMPSTRING) ? 1 : 2;
381
 
        if (len >= CCERT_BUFSIZ) {
382
 
            msg_warn("%s: %s: peer %s too long: %d",
383
 
                     myname, TLScontext->namaddr, label, len);
384
 
            return (0);
385
 
        }
386
 
        if ((len = ASN1_STRING_to_UTF8(&utf, entry_str)) < 0) {
387
 
            msg_warn("%s: %s: error decoding peer %s of ASN.1 type=%d",
388
 
                     myname, TLScontext->namaddr, label, typ);
389
 
            tls_print_errors();
390
 
            return (0);
391
 
        }
 
326
     * XXX Convert everything into UTF-8. This is a super-set of ASCII, so we
 
327
     * don't have to bother with separate code paths for ASCII-like content.
 
328
     * If the payload is ASCII then we won't waste lots of CPU cycles
 
329
     * converting it into UTF-8. It's up to OpenSSL to do something
 
330
     * reasonable when converting ASCII formats that contain non-ASCII
 
331
     * content.
 
332
     * 
 
333
     * XXX Don't bother optimizing the string length error check. It is not
 
334
     * worth the complexity.
 
335
     */
 
336
    asn1_type = ASN1_STRING_type(entry_str);
 
337
    if ((utf8_length = ASN1_STRING_to_UTF8(&utf8_value, entry_str)) < 0) {
 
338
        msg_warn("%s: %s: error decoding peer %s of ASN.1 type=%d",
 
339
                 myname, TLScontext->namaddr, label, asn1_type);
 
340
        tls_print_errors();
 
341
        return (0);
392
342
    }
393
 
#define RETURN(x) do { if (utf!=val) OPENSSL_free(utf); return (x); } while (0)
394
 
 
395
 
    if (len >= CCERT_BUFSIZ) {
 
343
 
 
344
    /*
 
345
     * No returns without cleaning up. A good optimizer will replace multiple
 
346
     * blocks of identical code by jumps to just one such block.
 
347
     */
 
348
#define TLS_TEXT_NAME_RETURN(x) do { \
 
349
        char *__tls_text_name_temp = (x); \
 
350
        OPENSSL_free(utf8_value); \
 
351
        return (__tls_text_name_temp); \
 
352
    } while (0)
 
353
 
 
354
    /*
 
355
     * Remove trailing null characters. They would give false alarms with the
 
356
     * length check and with the embedded null check.
 
357
     */
 
358
#define TRIM0(s, l) do { while ((l) > 0 && (s)[(l)-1] == 0) --(l); } while (0)
 
359
 
 
360
    TRIM0(utf8_value, utf8_length);
 
361
 
 
362
    /*
 
363
     * Enforce the length limit, because the caller will copy the result into
 
364
     * a fixed-length buffer.
 
365
     */
 
366
    if (utf8_length >= CCERT_BUFSIZ) {
396
367
        msg_warn("%s: %s: peer %s too long: %d",
397
 
                 myname, TLScontext->namaddr, label, len);
398
 
        RETURN(0);
 
368
                 myname, TLScontext->namaddr, label, utf8_length);
 
369
        TLS_TEXT_NAME_RETURN(0);
399
370
    }
400
 
    if (len != strlen((char *) utf)) {
401
 
        msg_warn("%s: %s: internal NUL in peer %s",
 
371
 
 
372
    /*
 
373
     * Reject embedded nulls in ASCII or UTF-8 names. OpenSSL is responsible
 
374
     * for producing properly-formatted UTF-8.
 
375
     */
 
376
    if (utf8_length != strlen((char *) utf8_value)) {
 
377
        msg_warn("%s: %s: NULL character in peer %s",
402
378
                 myname, TLScontext->namaddr, label);
403
 
        RETURN(0);
 
379
        TLS_TEXT_NAME_RETURN(0);
404
380
    }
405
 
    for (cp = (char *) utf; *cp; cp++) {
406
 
        if (!ISASCII(*cp) || !ISPRINT(*cp)) {
407
 
            msg_warn("%s: %s: non-printable characters in peer %s",
 
381
 
 
382
    /*
 
383
     * Reject non-printable ASCII characters in UTF-8 content.
 
384
     * 
 
385
     * Note: the code below does not find control characters in illegal UTF-8
 
386
     * sequences. It's OpenSSL's job to produce valid UTF-8, and reportedly,
 
387
     * it does validation.
 
388
     */
 
389
    for (cp = utf8_value; (ch = *cp) != 0; cp++) {
 
390
        if (ISASCII(ch) && !ISPRINT(ch)) {
 
391
            msg_warn("%s: %s: non-printable content in peer %s",
408
392
                     myname, TLScontext->namaddr, label);
409
 
            RETURN(0);
 
393
            TLS_TEXT_NAME_RETURN(0);
410
394
        }
411
395
    }
412
 
    cp = mystrdup((char *) utf);
413
 
    RETURN(cp);
 
396
    TLS_TEXT_NAME_RETURN(mystrdup((char *) utf8_value));
414
397
}
415
398
 
416
399
/* tls_dns_name - Extract valid DNS name from subjectAltName value */
421
404
    const char *myname = "tls_dns_name";
422
405
    char   *cp;
423
406
    const char *dnsname;
 
407
    int     len;
424
408
 
425
409
    /*
426
410
     * Peername checks are security sensitive, carefully scrutinize the
443
427
     * Safe to treat as an ASCII string possibly holding a DNS name
444
428
     */
445
429
    dnsname = (char *) ASN1_STRING_data(gn->d.ia5);
 
430
    len = ASN1_STRING_length(gn->d.ia5);
 
431
    TRIM0(dnsname, len);
446
432
 
447
433
    /*
448
434
     * Per Dr. Steven Henson of the OpenSSL development team, ASN1_IA5STRING
451
437
     * always appended to make sure that the string is terminated, but the
452
438
     * ASN.1 length may differ from strlen().
453
439
     */
454
 
    if (ASN1_STRING_length(gn->d.ia5) != strlen(dnsname)) {
 
440
    if (len != strlen(dnsname)) {
455
441
        msg_warn("%s: %s: internal NUL in subjectAltName",
456
442
                 myname, TLScontext->namaddr);
457
443
        return 0;
463
449
     * compare equal to the expected peername, so being more strict than
464
450
     * "printable" is likely excessive...
465
451
     */
466
 
    for (cp = (char *) dnsname; cp && *cp; cp++)
467
 
        if (!ISASCII(*cp) || !ISPRINT(*cp)) {
468
 
            cp = mystrdup(dnsname);
469
 
            msg_warn("%s: %s: non-printable characters in subjectAltName: %s",
470
 
                     myname, TLScontext->namaddr, printable(cp, '?'));
471
 
            myfree(cp);
472
 
            return 0;
473
 
        }
 
452
    if (*dnsname && !allprint(dnsname)) {
 
453
        cp = mystrdup(dnsname);
 
454
        msg_warn("%s: %s: non-printable characters in subjectAltName: %.100s",
 
455
                 myname, TLScontext->namaddr, printable(cp, '?'));
 
456
        myfree(cp);
 
457
        return 0;
 
458
    }
474
459
    return (dnsname);
475
460
}
476
461