View | Details | Raw Unified | Return to bug 47514
Collapse All | Expand All

(-)httpd-trunk/modules/ssl/ssl_private.h (-1 / +9 lines)
Lines 199-205 Link Here
199
#define SSL_OPT_FAKEBASICAUTH  (1<<4)
199
#define SSL_OPT_FAKEBASICAUTH  (1<<4)
200
#define SSL_OPT_STRICTREQUIRE  (1<<5)
200
#define SSL_OPT_STRICTREQUIRE  (1<<5)
201
#define SSL_OPT_OPTRENEGOTIATE (1<<6)
201
#define SSL_OPT_OPTRENEGOTIATE (1<<6)
202
#define SSL_OPT_ALL            (SSL_OPT_STDENVVARS|SSL_OPT_EXPORTCERTDATA|SSL_OPT_FAKEBASICAUTH|SSL_OPT_STRICTREQUIRE|SSL_OPT_OPTRENEGOTIATE)
202
#define SSL_OPT_SUBJECTDIRATTR (1<<7)
203
#define SSL_OPT_ALL            (SSL_OPT_STDENVVARS|SSL_OPT_EXPORTCERTDATA|SSL_OPT_FAKEBASICAUTH|SSL_OPT_STRICTREQUIRE|SSL_OPT_OPTRENEGOTIATE|SSL_OPT_SUBJECTDIRATTR)
203
typedef int ssl_opt_t;
204
typedef int ssl_opt_t;
204
205
205
/**
206
/**
Lines 504-509 Link Here
504
    apr_size_t    nRenegBufferSize;
505
    apr_size_t    nRenegBufferSize;
505
} SSLDirConfigRec;
506
} SSLDirConfigRec;
506
507
508
507
/**
509
/**
508
 *  function prototypes
510
 *  function prototypes
509
 */
511
 */
Lines 690-696 Link Here
690
void         ssl_var_register(apr_pool_t *p);
692
void         ssl_var_register(apr_pool_t *p);
691
char        *ssl_var_lookup(apr_pool_t *, server_rec *, conn_rec *, request_rec *, char *);
693
char        *ssl_var_lookup(apr_pool_t *, server_rec *, conn_rec *, request_rec *, char *);
692
apr_array_header_t *ssl_ext_list(apr_pool_t *p, conn_rec *c, int peer, const char *extension);
694
apr_array_header_t *ssl_ext_list(apr_pool_t *p, conn_rec *c, int peer, const char *extension);
695
apr_array_header_t *ssl_ext_subject_dir_attr_lookup(apr_pool_t *p, X509 *xs, int nid);
696
apr_array_header_t *ssl_ext_get_subject_dir_attr_values_by_NID(apr_pool_t *p, void *sda_object_ptr, int pdaNID);
697
void *ssl_ext_get_subject_dir_attrs_object_ptr(X509 *xs);
698
void ssl_ext_free_subject_dir_attrs_object_ptr(void *sda_object_ptr);
699
char *get_age_from_generalizedtime_str(apr_pool_t *p, char *str);
693
700
701
694
void         ssl_var_log_config_register(apr_pool_t *p);
702
void         ssl_var_log_config_register(apr_pool_t *p);
695
703
696
/* Extract SSL_*_DN_* variables into table 't' from SSL object 'ssl',
704
/* Extract SSL_*_DN_* variables into table 't' from SSL object 'ssl',
(-)httpd-trunk/modules/ssl/ssl_engine_config.c (+3 lines)
Lines 1100-1105 Link Here
1100
        else if (strcEQ(w, "OptRenegotiate")) {
1100
        else if (strcEQ(w, "OptRenegotiate")) {
1101
            opt = SSL_OPT_OPTRENEGOTIATE;
1101
            opt = SSL_OPT_OPTRENEGOTIATE;
1102
        }
1102
        }
1103
        else if (strcEQ(w, "SubjectDirAttrVars")) {
1104
            opt = SSL_OPT_SUBJECTDIRATTR;
1105
        }
1103
        else {
1106
        else {
1104
            return apr_pstrcat(cmd->pool,
1107
            return apr_pstrcat(cmd->pool,
1105
                               "SSLOptions: Illegal option '", w, "'",
1108
                               "SSLOptions: Illegal option '", w, "'",
(-)httpd-trunk/modules/ssl/ssl_engine_vars.c (+214 lines)
Lines 32-37 Link Here
32
32
33
#include "apr_time.h"
33
#include "apr_time.h"
34
34
35
#ifdef HAVE_OPENSSL
36
37
#include <openssl/asn1.h>
38
#include <openssl/asn1t.h>
39
40
/**
41
 * Subject Directory Attributes extension
42
 */
43
typedef STACK_OF(X509_ATTRIBUTE) SUBJECT_DIRECTORY_ATTRIBUTES;
44
45
ASN1_ITEM_TEMPLATE(SUBJECT_DIRECTORY_ATTRIBUTES) =
46
       ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Attributes, X509_ATTRIBUTE)
47
ASN1_ITEM_TEMPLATE_END(SUBJECT_DIRECTORY_ATTRIBUTES)
48
49
DECLARE_ASN1_FUNCTIONS(SUBJECT_DIRECTORY_ATTRIBUTES)
50
51
IMPLEMENT_ASN1_FUNCTIONS(SUBJECT_DIRECTORY_ATTRIBUTES)
52
53
#endif
54
35
/*  _________________________________________________________________
55
/*  _________________________________________________________________
36
**
56
**
37
**  Variable Lookup
57
**  Variable Lookup
Lines 51-56 Link Here
51
static void  ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize);
71
static void  ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize);
52
static char *ssl_var_lookup_ssl_version(apr_pool_t *p, char *var);
72
static char *ssl_var_lookup_ssl_version(apr_pool_t *p, char *var);
53
static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl);
73
static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl);
74
static char *ssl_var_lookup_ssl_cert_ext_subject_dir_attrs(apr_pool_t *p, X509 *xs, char *var);
54
75
55
static int ssl_is_https(conn_rec *c)
76
static int ssl_is_https(conn_rec *c)
56
{
77
{
Lines 399-404 Link Here
399
                             (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid));
420
                             (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid));
400
        resdup = FALSE;
421
        resdup = FALSE;
401
    }
422
    }
423
    else if (strcEQn(var, "EXT_SDA_", 8)) {
424
        result = ssl_var_lookup_ssl_cert_ext_subject_dir_attrs(p, xs, var+8);
425
        resdup = FALSE;
426
    }
402
    else if (strcEQ(var, "CERT")) {
427
    else if (strcEQ(var, "CERT")) {
403
        result = ssl_var_lookup_ssl_cert_PEM(p, xs);
428
        result = ssl_var_lookup_ssl_cert_PEM(p, xs);
404
    }
429
    }
Lines 408-413 Link Here
408
    return result;
433
    return result;
409
}
434
}
410
435
436
static char *ssl_var_lookup_ssl_cert_ext_subject_dir_attrs(apr_pool_t *p, X509 *xs, char *var)
437
{
438
    char *result = NULL;
439
440
    if (strcEQ(var, "GENDER")) {
441
        apr_array_header_t *values = ssl_ext_subject_dir_attr_lookup(p, xs, NID_id_pda_gender);
442
        if(values != NULL) {
443
            char **elts = (char **) values->elts;
444
            result = elts[0];
445
        }
446
    }
447
    else if (strlen(var) > 21 && strcEQn(var, "COUNTRYOFCITIZENSHIP_", 21)) {
448
        int index = atoi(var+21);
449
        apr_array_header_t *values = ssl_ext_subject_dir_attr_lookup(p, xs, NID_id_pda_countryOfCitizenship);
450
        if((values != NULL) && (index < values->nelts)) {
451
            char **elts = (char **) values->elts;
452
            result = elts[index];
453
        }
454
    }
455
    else if (strlen(var) > 19 && strcEQn(var, "COUNTRYOFRESIDENCE_", 19)) {
456
        int index = atoi(var+19);
457
        apr_array_header_t *values = ssl_ext_subject_dir_attr_lookup(p, xs, NID_id_pda_countryOfResidence);
458
        if((values != NULL) && (index < values->nelts)) {
459
            char **elts = (char **) values->elts;
460
            result = elts[index];
461
        }
462
    }
463
    else if (strcEQ(var, "PLACEOFBIRTH")) {
464
        apr_array_header_t *values = ssl_ext_subject_dir_attr_lookup(p, xs, NID_id_pda_placeOfBirth);
465
        if(values != NULL) {
466
            char **elts = (char **) values->elts;
467
            result = elts[0];
468
        }
469
    }
470
    else if (strcEQ(var, "DATEOFBIRTH")) {
471
        apr_array_header_t *values = ssl_ext_subject_dir_attr_lookup(p, xs, NID_id_pda_dateOfBirth);
472
        if(values != NULL) {
473
            char **elts = (char **) values->elts;
474
            result = elts[0];
475
        }
476
    }
477
    else if (strcEQ(var, "AGE")) {
478
        apr_array_header_t *values = ssl_ext_subject_dir_attr_lookup(p, xs, NID_id_pda_dateOfBirth);
479
        if(values != NULL) {
480
            char **elts = (char **) values->elts;
481
            result = get_age_from_generalizedtime_str(p, elts[0]);
482
        }
483
    }
484
    return result;
485
}
486
487
488
char *get_age_from_generalizedtime_str(apr_pool_t *p, char *str)
489
{
490
    char *result = NULL;
491
    char format[] = "%Y%m%d%H%M%S";
492
    char tmp[20];
493
    struct tm dateOfBirth;
494
    struct tm today;
495
    time_t now = time(0);
496
    gmtime_r(&now, &today);
497
    strptime(str, format, &dateOfBirth);
498
    int age = today.tm_year - dateOfBirth.tm_year - 1;
499
    if( (today.tm_mon > dateOfBirth.tm_mon) || ((today.tm_mon == dateOfBirth.tm_mon) && (today.tm_mday > dateOfBirth.tm_mday)) ) {
500
        age++;
501
    }
502
503
    sprintf(tmp, "%d", age);
504
    result = apr_pstrdup(p, tmp);
505
    return result;
506
}
507
508
411
/* In this table, .extract is non-zero if RDNs using the NID should be
509
/* In this table, .extract is non-zero if RDNs using the NID should be
412
 * extracted to for the SSL_{CLIENT,SERVER}_{I,S}_DN_* environment
510
 * extracted to for the SSL_{CLIENT,SERVER}_{I,S}_DN_* environment
413
 * variables. */
511
 * variables. */
Lines 849-854 Link Here
849
    return array;
947
    return array;
850
}
948
}
851
949
950
951
void *ssl_ext_get_subject_dir_attrs_object_ptr(X509 *xs)
952
{
953
    void *retval = NULL;
954
955
#ifdef HAVE_OPENSSL
956
    X509_EXTENSION *ext = NULL;
957
    ASN1_OCTET_STRING *ext_data_ocstr = NULL;
958
    const unsigned char *ext_data;
959
    int sdaIndex;
960
961
    if (xs == NULL) {
962
        return NULL;
963
    }
964
965
    /* Search "Subject Directory Attributes" extension */
966
    sdaIndex = X509_get_ext_by_NID(xs, NID_subject_directory_attributes, -1);
967
    if(sdaIndex < 0) {
968
	return NULL;
969
    }
970
971
    /* Get Subject Directory Attributes OCTET_STRING */
972
    ext = X509_get_ext(xs, sdaIndex);
973
    ext_data_ocstr = X509_EXTENSION_get_data(ext);
974
    if(ext_data_ocstr == NULL) {
975
        return NULL;
976
    }
977
978
    /* Convert extension data (OCTET_STRING) to internal representation object */
979
    ext_data = ext_data_ocstr->data;
980
    retval = (void *)d2i_SUBJECT_DIRECTORY_ATTRIBUTES(NULL, &ext_data, (long)ext_data_ocstr->length);
981
#endif
982
983
    return retval;
984
}
985
986
987
void ssl_ext_free_subject_dir_attrs_object_ptr(void *sda_object_ptr)
988
{
989
#ifdef HAVE_OPENSSL
990
    SUBJECT_DIRECTORY_ATTRIBUTES *sda = (SUBJECT_DIRECTORY_ATTRIBUTES *)sda_object_ptr;
991
    if(sda != NULL) SUBJECT_DIRECTORY_ATTRIBUTES_free(sda);
992
#endif
993
}
994
995
996
apr_array_header_t *ssl_ext_get_subject_dir_attr_values_by_NID(apr_pool_t *p, void *sda_object_ptr, int pdaNID)
997
{
998
    apr_array_header_t *array = NULL;
999
1000
#ifdef HAVE_OPENSSL
1001
    SUBJECT_DIRECTORY_ATTRIBUTES *sda = (SUBJECT_DIRECTORY_ATTRIBUTES *)sda_object_ptr;
1002
    int attr_index, value_index, num_values;
1003
1004
    if(sda == NULL) {
1005
	return NULL;
1006
    }
1007
1008
    /* Search pdaNID in "Subject Directory Attributes", and create an array with a copy of all attribute values (as strings) */
1009
    for (attr_index = 0; attr_index < sk_X509_ATTRIBUTE_num(sda); attr_index++) {
1010
        X509_ATTRIBUTE *attribute = sk_X509_ATTRIBUTE_value(sda, attr_index);
1011
        if(pdaNID == OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attribute))) { 
1012
1013
    	    num_values = X509_ATTRIBUTE_count(attribute);
1014
	    if(num_values > 0) {
1015
                if(array == NULL) {
1016
                    array = apr_array_make(p, num_values, sizeof(char *));
1017
                }
1018
1019
                for (value_index = 0; value_index < num_values; value_index++) {
1020
                    ASN1_TYPE *type = X509_ATTRIBUTE_get0_type(attribute, value_index);
1021
                    if(type->type == V_ASN1_GENERALIZEDTIME) {  // i.e: dateOfBirth
1022
                        ASN1_GENERALIZEDTIME *val = (ASN1_GENERALIZEDTIME *)X509_ATTRIBUTE_get0_data(attribute, value_index, type->type, NULL);
1023
                        char **ptr = apr_array_push(array);
1024
                        *ptr = apr_pstrdup(p, val->data);
1025
                    } else { // ASN1_STRING 
1026
                        ASN1_STRING *val = (ASN1_STRING *)X509_ATTRIBUTE_get0_data(attribute, value_index, type->type, NULL);
1027
                        char **ptr = apr_array_push(array);
1028
                        *ptr = apr_pstrdup(p, val->data);
1029
                    }
1030
                }
1031
            }
1032
1033
        }
1034
    }
1035
1036
    ERR_clear_error();
1037
#endif
1038
1039
    return array;
1040
}
1041
1042
apr_array_header_t *ssl_ext_subject_dir_attr_lookup(apr_pool_t *p, X509 *xs, int pdaNID)
1043
{
1044
    apr_array_header_t *array = NULL;  
1045
    void *sda_object_ptr = NULL;
1046
1047
    /* Check certificate */
1048
    if(xs == NULL) {
1049
        return NULL;
1050
    }
1051
1052
    /* Check "Subject Directory Attributes" */
1053
    sda_object_ptr = ssl_ext_get_subject_dir_attrs_object_ptr(xs);
1054
    if(sda_object_ptr == NULL) {
1055
        return NULL;
1056
    }
1057
1058
    array = ssl_ext_get_subject_dir_attr_values_by_NID(p, sda_object_ptr, pdaNID);
1059
1060
    ssl_ext_free_subject_dir_attrs_object_ptr(sda_object_ptr);
1061
1062
    return array;
1063
}
1064
1065
852
static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl)
1066
static char *ssl_var_lookup_ssl_compress_meth(SSL *ssl)
853
{
1067
{
854
    char *result = "NULL";
1068
    char *result = "NULL";
(-)httpd-trunk/modules/ssl/ssl_engine_kernel.c (+61 lines)
Lines 1133-1138 Link Here
1133
        }
1133
        }
1134
    }
1134
    }
1135
1135
1136
    /*
1137
     * On-demand subject directory attributes
1138
     */
1139
    if (dc->nOptions & SSL_OPT_SUBJECTDIRATTR) {
1140
        apr_array_header_t *array;
1141
        X509 *peercert = SSL_get_peer_certificate(ssl);
1142
        void *sda_object_ptr = ssl_ext_get_subject_dir_attrs_object_ptr(peercert);
1143
1144
        if(sda_object_ptr != NULL) {
1145
1146
            array = ssl_ext_get_subject_dir_attr_values_by_NID(r->pool, sda_object_ptr, NID_id_pda_dateOfBirth);
1147
            if( (array != NULL) && (array->nelts > 0) ) {
1148
                char **elts = (char **) array->elts;
1149
                val = elts[0];
1150
                apr_table_setn(env, "SSL_CLIENT_EXT_SDA_DATEOFBIRTH", val);
1151
                apr_table_setn(env, "SSL_CLIENT_EXT_SDA_AGE", get_age_from_generalizedtime_str(r->pool, val));
1152
            }
1153
1154
            array = ssl_ext_get_subject_dir_attr_values_by_NID(r->pool, sda_object_ptr, NID_id_pda_gender);
1155
            if( (array != NULL) && (array->nelts > 0) ) {
1156
                char **elts = (char **) array->elts;
1157
                val = elts[0];
1158
                apr_table_setn(env, "SSL_CLIENT_EXT_SDA_GENDER", val);
1159
            }
1160
1161
            array = ssl_ext_get_subject_dir_attr_values_by_NID(r->pool, sda_object_ptr, NID_id_pda_placeOfBirth);
1162
            if( (array != NULL) && (array->nelts > 0) ) {
1163
                char **elts = (char **) array->elts;
1164
                val = elts[0];
1165
                apr_table_setn(env, "SSL_CLIENT_EXT_SDA_PLACEOFBIRTH", val);
1166
            }
1167
1168
            array = ssl_ext_get_subject_dir_attr_values_by_NID(r->pool, sda_object_ptr, NID_id_pda_countryOfResidence);
1169
            if( (array != NULL) && (array->nelts > 0) ) {
1170
                for(i = 0; i < array->nelts; i++) {
1171
                    char **elts = (char **) array->elts;
1172
                    val = elts[i];
1173
                    var = apr_psprintf(r->pool, "SSL_CLIENT_EXT_SDA_COUNTRYOFRESIDENCE_%d", i);
1174
                    apr_table_setn(env, var, val);
1175
                }
1176
            }
1177
1178
            array = ssl_ext_get_subject_dir_attr_values_by_NID(r->pool, sda_object_ptr, NID_id_pda_countryOfCitizenship);
1179
            if( (array != NULL) && (array->nelts > 0) ) {
1180
                for(i = 0; i < array->nelts; i++) {
1181
                    char **elts = (char **) array->elts;
1182
                    val = elts[i];
1183
                    var = apr_psprintf(r->pool, "SSL_CLIENT_EXT_SDA_COUNTRYOFCITIZENSHIP_%d", i);
1184
                    apr_table_setn(env, var, val);
1185
                }
1186
            }
1187
1188
            ssl_ext_free_subject_dir_attrs_object_ptr(sda_object_ptr);
1189
        }
1190
1191
        if(peercert != NULL) {
1192
            X509_free(peercert);
1193
        }
1194
1195
    }
1196
1136
    return DECLINED;
1197
    return DECLINED;
1137
}
1198
}
1138
1199

Return to bug 47514