Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 519202 | Differences between
and this patch

Collapse All | Expand All

(-)buckets/ssl_buckets.c (-36 / +147 lines)
Lines 202-207 struct serf_ssl_certificate_t { Link Here
202
};
202
};
203
203
204
static void disable_compression(serf_ssl_context_t *ssl_ctx);
204
static void disable_compression(serf_ssl_context_t *ssl_ctx);
205
static char *
206
    pstrdup_escape_nul_bytes(const char *buf, int len, apr_pool_t *pool);
205
207
206
#if SSL_VERBOSE
208
#if SSL_VERBOSE
207
/* Log all ssl alerts that we receive from the server. */
209
/* Log all ssl alerts that we receive from the server. */
Lines 427-432 static BIO_METHOD bio_file_method = { Link Here
427
#endif
429
#endif
428
};
430
};
429
431
432
typedef enum san_copy_t {
433
    EscapeNulAndCopy = 0,
434
    ErrorOnNul = 1,
435
} san_copy_t;
436
437
438
static apr_status_t
439
get_subject_alt_names(apr_array_header_t **san_arr, X509 *ssl_cert,
440
                      san_copy_t copy_action, apr_pool_t *pool)
441
{
442
    STACK_OF(GENERAL_NAME) *names;
443
444
    /* assert: copy_action == ErrorOnNul || (san_arr && pool) */
445
446
    if (san_arr) {
447
        *san_arr = NULL;
448
    }
449
450
    /* Get subjectAltNames */
451
    names = X509_get_ext_d2i(ssl_cert, NID_subject_alt_name, NULL, NULL);
452
    if (names) {
453
        int names_count = sk_GENERAL_NAME_num(names);
454
        int name_idx;
455
456
        if (san_arr)
457
            *san_arr = apr_array_make(pool, names_count, sizeof(char*));
458
        for (name_idx = 0; name_idx < names_count; name_idx++) {
459
            char *p = NULL;
460
            GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, name_idx);
461
462
            switch (nm->type) {
463
                case GEN_DNS:
464
                    if (copy_action == ErrorOnNul &&
465
                        strlen(nm->d.ia5->data) != nm->d.ia5->length)
466
                        return SERF_ERROR_SSL_CERT_FAILED;
467
                    if (san_arr && *san_arr)
468
                        p = pstrdup_escape_nul_bytes((const char *)nm->d.ia5->data,
469
                                                     nm->d.ia5->length,
470
                                                     pool);
471
                    break;
472
                default:
473
                    /* Don't know what to do - skip. */
474
                    break;
475
            }
476
477
            if (p) {
478
                APR_ARRAY_PUSH(*san_arr, char*) = p;
479
            }
480
        }
481
        sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
482
    }
483
    
484
    return APR_SUCCESS;
485
}
486
487
static apr_status_t validate_cert_hostname(X509 *server_cert, apr_pool_t *pool)
488
{
489
    char buf[1024];
490
    int length;
491
    apr_status_t ret;
492
493
    ret = get_subject_alt_names(NULL, server_cert, ErrorOnNul, NULL);
494
    if (ret) {
495
      return ret;
496
    } else {
497
        /* Fail if the subject's CN field contains \0 characters. */
498
        X509_NAME *subject = X509_get_subject_name(server_cert);
499
        if (!subject)
500
            return SERF_ERROR_SSL_CERT_FAILED;
501
502
        length = X509_NAME_get_text_by_NID(subject, NID_commonName, buf, 1024);
503
        if (length != -1)
504
            if (strlen(buf) != length)
505
                return SERF_ERROR_SSL_CERT_FAILED;
506
    }
507
508
    return APR_SUCCESS;
509
}
510
430
static int
511
static int
431
validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
512
validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
432
{
513
{
Lines 435-440 validate_server_certificate(int cert_valid, X509_S Link Here
435
    X509 *server_cert;
516
    X509 *server_cert;
436
    int err, depth;
517
    int err, depth;
437
    int failures = 0;
518
    int failures = 0;
519
    apr_status_t status;
438
520
439
    ssl = X509_STORE_CTX_get_ex_data(store_ctx,
521
    ssl = X509_STORE_CTX_get_ex_data(store_ctx,
440
                                     SSL_get_ex_data_X509_STORE_CTX_idx());
522
                                     SSL_get_ex_data_X509_STORE_CTX_idx());
Lines 475-480 validate_server_certificate(int cert_valid, X509_S Link Here
475
        }
557
        }
476
    }
558
    }
477
559
560
    /* Validate hostname */
561
    status = validate_cert_hostname(server_cert, ctx->pool);
562
    if (status)
563
        failures |= SERF_SSL_CERT_UNKNOWN_FAILURE;
564
478
    /* Check certificate expiry dates. */
565
    /* Check certificate expiry dates. */
479
    if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
566
    if (X509_cmp_current_time(X509_get_notBefore(server_cert)) >= 0) {
480
        failures |= SERF_SSL_CERT_NOTYETVALID;
567
        failures |= SERF_SSL_CERT_NOTYETVALID;
Lines 485-491 validate_server_certificate(int cert_valid, X509_S Link Here
485
572
486
    if (ctx->server_cert_callback &&
573
    if (ctx->server_cert_callback &&
487
        (depth == 0 || failures)) {
574
        (depth == 0 || failures)) {
488
        apr_status_t status;
489
        serf_ssl_certificate_t *cert;
575
        serf_ssl_certificate_t *cert;
490
        apr_pool_t *subpool;
576
        apr_pool_t *subpool;
491
577
Lines 512-518 validate_server_certificate(int cert_valid, X509_S Link Here
512
598
513
    if (ctx->server_cert_chain_callback
599
    if (ctx->server_cert_chain_callback
514
        && (depth == 0 || failures)) {
600
        && (depth == 0 || failures)) {
515
        apr_status_t status;
516
        STACK_OF(X509) *chain;
601
        STACK_OF(X509) *chain;
517
        const serf_ssl_certificate_t **certs;
602
        const serf_ssl_certificate_t **certs;
518
        int certs_len;
603
        int certs_len;
Lines 1461-1467 serf_ssl_context_t *serf_bucket_ssl_encrypt_contex Link Here
1461
1546
1462
/* Functions to read a serf_ssl_certificate structure. */
1547
/* Functions to read a serf_ssl_certificate structure. */
1463
1548
1464
/* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). */
1549
/* Takes a counted length string and escapes any NUL bytes so that
1550
 * it can be used as a C string.  NUL bytes are escaped as 3 characters
1551
 * "\00" (that's a literal backslash).
1552
 * The returned string is allocated in POOL.
1553
 */
1554
static char *
1555
pstrdup_escape_nul_bytes(const char *buf, int len, apr_pool_t *pool)
1556
{
1557
    int i, nul_count = 0;
1558
    char *ret;
1559
1560
    /* First determine if there are any nul bytes in the string. */
1561
    for (i = 0; i < len; i++) {
1562
        if (buf[i] == '\0')
1563
            nul_count++;
1564
    }
1565
1566
    if (nul_count == 0) {
1567
        /* There aren't so easy case to just copy the string */
1568
        ret = apr_pstrdup(pool, buf);
1569
    } else {
1570
        /* There are so we have to replace nul bytes with escape codes
1571
         * Proper length is the length of the original string, plus
1572
         * 2 times the number of nulls (for two digit hex code for
1573
         * the value) + the trailing null. */
1574
        char *pos;
1575
        ret = pos = apr_palloc(pool, len + 2 * nul_count + 1);
1576
        for (i = 0; i < len; i++) {
1577
            if (buf[i] != '\0') {
1578
                *(pos++) = buf[i];
1579
            } else {
1580
                *(pos++) = '\\';
1581
                *(pos++) = '0';
1582
                *(pos++) = '0';
1583
            }
1584
        }
1585
        *pos = '\0';
1586
    }
1587
1588
    return ret;
1589
}
1590
1591
/* Creates a hash_table with keys (E, CN, OU, O, L, ST and C). Any NUL bytes in
1592
   these fields in the certificate will be escaped as \00. */
1465
static apr_hash_t *
1593
static apr_hash_t *
1466
convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
1594
convert_X509_NAME_to_table(X509_NAME *org, apr_pool_t *pool)
1467
{
1595
{
Lines 1474-1510 convert_X509_NAME_to_table(X509_NAME *org, apr_poo Link Here
1474
                                    NID_commonName,
1602
                                    NID_commonName,
1475
                                    buf, 1024);
1603
                                    buf, 1024);
1476
    if (ret != -1)
1604
    if (ret != -1)
1477
        apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1605
        apr_hash_set(tgt, "CN", APR_HASH_KEY_STRING,
1606
                     pstrdup_escape_nul_bytes(buf, ret, pool));
1478
    ret = X509_NAME_get_text_by_NID(org,
1607
    ret = X509_NAME_get_text_by_NID(org,
1479
                                    NID_pkcs9_emailAddress,
1608
                                    NID_pkcs9_emailAddress,
1480
                                    buf, 1024);
1609
                                    buf, 1024);
1481
    if (ret != -1)
1610
    if (ret != -1)
1482
        apr_hash_set(tgt, "E", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1611
        apr_hash_set(tgt, "E", APR_HASH_KEY_STRING,
1612
                     pstrdup_escape_nul_bytes(buf, ret, pool));
1483
    ret = X509_NAME_get_text_by_NID(org,
1613
    ret = X509_NAME_get_text_by_NID(org,
1484
                                    NID_organizationalUnitName,
1614
                                    NID_organizationalUnitName,
1485
                                    buf, 1024);
1615
                                    buf, 1024);
1486
    if (ret != -1)
1616
    if (ret != -1)
1487
        apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1617
        apr_hash_set(tgt, "OU", APR_HASH_KEY_STRING,
1618
                     pstrdup_escape_nul_bytes(buf, ret, pool));
1488
    ret = X509_NAME_get_text_by_NID(org,
1619
    ret = X509_NAME_get_text_by_NID(org,
1489
                                    NID_organizationName,
1620
                                    NID_organizationName,
1490
                                    buf, 1024);
1621
                                    buf, 1024);
1491
    if (ret != -1)
1622
    if (ret != -1)
1492
        apr_hash_set(tgt, "O", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1623
        apr_hash_set(tgt, "O", APR_HASH_KEY_STRING,
1624
                     pstrdup_escape_nul_bytes(buf, ret, pool));
1493
    ret = X509_NAME_get_text_by_NID(org,
1625
    ret = X509_NAME_get_text_by_NID(org,
1494
                                    NID_localityName,
1626
                                    NID_localityName,
1495
                                    buf, 1024);
1627
                                    buf, 1024);
1496
    if (ret != -1)
1628
    if (ret != -1)
1497
        apr_hash_set(tgt, "L", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1629
        apr_hash_set(tgt, "L", APR_HASH_KEY_STRING,
1630
                     pstrdup_escape_nul_bytes(buf, ret, pool));
1498
    ret = X509_NAME_get_text_by_NID(org,
1631
    ret = X509_NAME_get_text_by_NID(org,
1499
                                    NID_stateOrProvinceName,
1632
                                    NID_stateOrProvinceName,
1500
                                    buf, 1024);
1633
                                    buf, 1024);
1501
    if (ret != -1)
1634
    if (ret != -1)
1502
        apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1635
        apr_hash_set(tgt, "ST", APR_HASH_KEY_STRING,
1636
                     pstrdup_escape_nul_bytes(buf, ret, pool));
1503
    ret = X509_NAME_get_text_by_NID(org,
1637
    ret = X509_NAME_get_text_by_NID(org,
1504
                                    NID_countryName,
1638
                                    NID_countryName,
1505
                                    buf, 1024);
1639
                                    buf, 1024);
1506
    if (ret != -1)
1640
    if (ret != -1)
1507
        apr_hash_set(tgt, "C", APR_HASH_KEY_STRING, apr_pstrdup(pool, buf));
1641
        apr_hash_set(tgt, "C", APR_HASH_KEY_STRING,
1642
                     pstrdup_escape_nul_bytes(buf, ret, pool));
1508
1643
1509
    return tgt;
1644
    return tgt;
1510
}
1645
}
Lines 1550-1556 apr_hash_t *serf_ssl_cert_certificate( Link Here
1550
    unsigned int md_size, i;
1685
    unsigned int md_size, i;
1551
    unsigned char md[EVP_MAX_MD_SIZE];
1686
    unsigned char md[EVP_MAX_MD_SIZE];
1552
    BIO *bio;
1687
    BIO *bio;
1553
    STACK_OF(GENERAL_NAME) *names;
1688
    apr_array_header_t *san_arr;
1554
1689
1555
    /* sha1 fingerprint */
1690
    /* sha1 fingerprint */
1556
    if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) {
1691
    if (X509_digest(cert->ssl_cert, EVP_sha1(), md, &md_size)) {
Lines 1595-1627 apr_hash_t *serf_ssl_cert_certificate( Link Here
1595
    BIO_free(bio);
1730
    BIO_free(bio);
1596
1731
1597
    /* Get subjectAltNames */
1732
    /* Get subjectAltNames */
1598
    names = X509_get_ext_d2i(cert->ssl_cert, NID_subject_alt_name, NULL, NULL);
1733
    if (!get_subject_alt_names(&san_arr, cert->ssl_cert, EscapeNulAndCopy, pool))
1599
    if (names) {
1600
        int names_count = sk_GENERAL_NAME_num(names);
1601
1602
        apr_array_header_t *san_arr = apr_array_make(pool, names_count,
1603
                                                     sizeof(char*));
1604
        apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr);
1734
        apr_hash_set(tgt, "subjectAltName", APR_HASH_KEY_STRING, san_arr);
1605
        for (i = 0; i < names_count; i++) {
1606
            char *p = NULL;
1607
            GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, i);
1608
1735
1609
            switch (nm->type) {
1610
            case GEN_DNS:
1611
                p = apr_pstrmemdup(pool, (const char *)nm->d.ia5->data,
1612
                                   nm->d.ia5->length);
1613
                break;
1614
            default:
1615
                /* Don't know what to do - skip. */
1616
                break;
1617
            }
1618
            if (p) {
1619
                APR_ARRAY_PUSH(san_arr, char*) = p;
1620
            }
1621
        }
1622
        sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
1623
    }
1624
1625
    return tgt;
1736
    return tgt;
1626
}
1737
}
1627
1738

Return to bug 519202