Changeset 9d9b093 in mod_gnutls for src/gnutls_hooks.c
- Timestamp:
- Jan 11, 2013, 12:56:51 AM (8 years ago)
- Branches:
- debian/master, debian/stretch-backports, jessie-backports, upstream
- Children:
- 2dd044f, 8ce897a
- Parents:
- 8df5b25
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/gnutls_hooks.c
r8df5b25 r9d9b093 37 37 static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); 38 38 /* use side==0 for server and side==1 for client */ 39 static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, 39 static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, 40 int side, 41 int export_certificates_enabled); 42 static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, 40 43 int side, 41 44 int export_certificates_enabled); … … 69 72 #endif 70 73 74 if (gnutls_check_version(LIBGNUTLS_VERSION)==NULL) { 75 fprintf(stderr, "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", 76 LIBGNUTLS_VERSION, gnutls_check_version(NULL)); 77 return -3; 78 } 79 71 80 ret = gnutls_global_init(); 72 if (ret < 0) /* FIXME: can we print here? */ 73 exit(ret); 81 if (ret < 0) { 82 fprintf(stderr, "gnutls_global_init: %s\n", gnutls_strerror(ret)); 83 return -3; 84 } 85 86 ret = gnutls_global_init_extra(); 87 if (ret < 0) { 88 fprintf(stderr, "gnutls_global_init_extra: %s\n", gnutls_strerror(ret)); 89 return -3; 90 } 74 91 75 92 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, … … 83 100 gnutls_global_set_log_level(9); 84 101 gnutls_global_set_log_function(gnutls_debug_log_all); 102 apr_file_printf(debug_log_fp, "gnutls: %s\n", gnutls_check_version(NULL)); 85 103 #endif 86 104 87 105 return OK; 88 106 } 89 90 /* We don't support openpgp certificates, yet */91 const static int cert_type_prio[2] = { GNUTLS_CRT_X509, 0 };92 107 93 108 static int mgs_select_virtual_server_cb(gnutls_session_t session) … … 96 111 mgs_srvconf_rec *tsc; 97 112 int ret; 113 int cprio[2]; 98 114 99 115 ctxt = gnutls_transport_get_ptr(session); … … 129 145 */ 130 146 ret = gnutls_priority_set(session, ctxt->sc->priorities); 131 gnutls_certificate_type_set_priority(session, cert_type_prio);132 133 134 147 /* actually it shouldn't fail since we have checked at startup */ 135 148 if (ret < 0) 136 149 return ret; 137 150 151 /* If both certificate types are not present disallow them from 152 * being negotiated. 153 */ 154 if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { 155 cprio[0] = GNUTLS_CRT_X509; 156 cprio[1] = 0; 157 gnutls_certificate_type_set_priority( session, cprio); 158 } else if (ctxt->sc->cert_pgp != NULL && ctxt->sc->certs_x509[0]==NULL) { 159 cprio[0] = GNUTLS_CRT_OPENPGP; 160 cprio[1] = 0; 161 gnutls_certificate_type_set_priority( session, cprio); 162 } 138 163 139 164 return 0; … … 146 171 ctxt = gnutls_transport_get_ptr(session); 147 172 148 ret->type = GNUTLS_CRT_X509; 149 ret->ncerts = ctxt->sc->certs_x509_num; 150 ret->deinit_all = 0; 151 152 ret->cert.x509 = ctxt->sc->certs_x509; 153 ret->key.x509 = ctxt->sc->privkey_x509; 154 return 0; 155 } 156 173 if (gnutls_certificate_type_get( session) == GNUTLS_CRT_X509) { 174 ret->type = GNUTLS_CRT_X509; 175 ret->ncerts = ctxt->sc->certs_x509_num; 176 ret->deinit_all = 0; 177 178 ret->cert.x509 = ctxt->sc->certs_x509; 179 ret->key.x509 = ctxt->sc->privkey_x509; 180 181 return 0; 182 } else if (gnutls_certificate_type_get( session) == GNUTLS_CRT_OPENPGP) { 183 ret->type = GNUTLS_CRT_OPENPGP; 184 ret->ncerts = 1; 185 ret->deinit_all = 0; 186 187 ret->cert.pgp = ctxt->sc->cert_pgp; 188 ret->key.pgp = ctxt->sc->privkey_pgp; 189 190 return 0; 191 192 } 193 194 return GNUTLS_E_INTERNAL_ERROR; 195 } 196 197 /* 2048-bit group parameters from SRP specification */ 157 198 const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n" 158 199 "MIIBBwKCAQCsa9tBMkqam/Fm3l4TiVgvr3K2ZRmH7gf8MZKUPbVgUKNzKcu0oJnt\n" … … 170 211 */ 171 212 static int read_crt_cn(server_rec * s, apr_pool_t * p, 172 gnutls_x509_crt cert, char **cert_cn)213 gnutls_x509_crt_t cert, char **cert_cn) 173 214 { 174 215 int rv = 0, i; … … 178 219 *cert_cn = NULL; 179 220 221 data_len = 0; 180 222 rv = gnutls_x509_crt_get_dn_by_oid(cert, 181 223 GNUTLS_OID_X520_COMMON_NAME, … … 188 230 0, *cert_cn, &data_len); 189 231 } else { /* No CN return subject alternative name */ 190 ap_log_error(APLOG_MARK, APLOG_ INFO, 0, s,191 "No common name found in certificate for '%s:%d'. Looking for subject alternative name. ",232 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, 233 "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", 192 234 s->server_hostname, s->port); 193 235 rv = 0; … … 217 259 218 260 return rv; 219 220 } 261 } 262 263 static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, 264 gnutls_openpgp_crt_t cert, char **cert_cn) 265 { 266 int rv = 0; 267 size_t data_len; 268 269 270 *cert_cn = NULL; 271 272 data_len = 0; 273 rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); 274 275 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 276 *cert_cn = apr_palloc(p, data_len); 277 rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, &data_len); 278 } else { /* No CN return subject alternative name */ 279 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 280 "No name found in PGP certificate for '%s:%d'.", 281 s->server_hostname, s->port); 282 } 283 284 return rv; 285 } 286 221 287 222 288 int … … 355 421 if (sc->enabled == GNUTLS_ENABLED_TRUE) { 356 422 rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn); 423 if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ 424 rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn); 425 357 426 if (rv < 0) { 358 427 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, … … 483 552 ctxt = gnutls_transport_get_ptr(session); 484 553 485 sni_type = gnutls_certificate_type_get(session);486 if (sni_type != GNUTLS_CRT_X509) {487 /* In theory, we could support OpenPGP Certificates. Theory != code. */488 ap_log_error(APLOG_MARK, APLOG_CRIT, 0,489 ctxt->c->base_server,490 "GnuTLS: Only x509 Certificates are currently supported.");491 return NULL;492 }493 494 554 rv = gnutls_server_name_get(ctxt->session, sni_name, 495 555 &data_len, &sni_type, 0); … … 691 751 apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); 692 752 693 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, 753 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) 754 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, 755 ctxt->sc->export_certificates_enabled); 756 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) 757 mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, 694 758 ctxt->sc->export_certificates_enabled); 695 759 … … 753 817 #define MGS_SIDE ((side==0)?"SSL_SERVER":"SSL_CLIENT") 754 818 static void 755 mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt cert, int side,819 mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, 756 820 int export_certificates_enabled) 757 821 { … … 859 923 } 860 924 } 861 862 863 } 864 865 925 } 926 927 static void 928 mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, 929 int export_certificates_enabled) 930 { 931 unsigned char sbuf[64]; /* buffer to hold serials */ 932 char buf[AP_IOBUFSIZE]; 933 const char *tmp; 934 size_t len; 935 int ret; 936 937 apr_table_t *env = r->subprocess_env; 938 939 if (export_certificates_enabled != 0) { 940 char cert_buf[10 * 1024]; 941 len = sizeof(cert_buf); 942 943 if (gnutls_openpgp_crt_export 944 (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) 945 apr_table_setn(env, 946 apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), 947 apr_pstrmemdup(r->pool, cert_buf, len)); 948 949 } 950 951 len = sizeof(buf); 952 gnutls_openpgp_crt_get_name(cert, 0, buf, &len); 953 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), 954 apr_pstrmemdup(r->pool, buf, len)); 955 956 len = sizeof(sbuf); 957 gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); 958 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 959 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL), 960 apr_pstrdup(r->pool, tmp)); 961 962 ret = gnutls_openpgp_crt_get_version(cert); 963 if (ret > 0) 964 apr_table_setn(env, 965 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), 966 apr_psprintf(r->pool, "%u", ret)); 967 968 apr_table_setn(env, 969 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP"); 970 971 tmp = 972 mgs_time2sz(gnutls_openpgp_crt_get_expiration_time 973 (cert), buf, sizeof(buf)); 974 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), 975 apr_pstrdup(r->pool, tmp)); 976 977 tmp = 978 mgs_time2sz(gnutls_openpgp_crt_get_creation_time 979 (cert), buf, sizeof(buf)); 980 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), 981 apr_pstrdup(r->pool, tmp)); 982 983 ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); 984 if (ret >= 0) { 985 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), 986 gnutls_pk_algorithm_get_name(ret)); 987 } 988 989 } 990 991 /* TODO: Allow client sending a X.509 certificate chain */ 866 992 static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) 867 993 { … … 869 995 unsigned int cert_list_size, status, expired; 870 996 int rv, ret; 871 gnutls_x509_crt_t cert; 997 union { 998 gnutls_x509_crt_t x509; 999 gnutls_openpgp_crt_t pgp; 1000 } cert; 872 1001 apr_time_t activation_time, expiration_time, cur_time; 873 1002 … … 895 1024 } 896 1025 897 gnutls_x509_crt_init(&cert); 898 rv = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER); 1026 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { 1027 gnutls_x509_crt_init(&cert.x509); 1028 rv = gnutls_x509_crt_import(cert.x509, &cert_list[0], GNUTLS_X509_FMT_DER); 1029 } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) { 1030 gnutls_openpgp_crt_init(&cert.pgp); 1031 rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); 1032 } else return HTTP_FORBIDDEN; 1033 899 1034 if (rv < 0) { 900 1035 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 901 1036 "GnuTLS: Failed to Verify Peer: " 902 1037 "Failed to import peer certificates."); 903 ret = HTTP_FORBIDDEN; 904 goto exit; 905 } 906 907 apr_time_ansi_put(&expiration_time, 908 gnutls_x509_crt_get_expiration_time(cert)); 909 apr_time_ansi_put(&activation_time, 910 gnutls_x509_crt_get_activation_time(cert)); 911 912 rv = gnutls_x509_crt_verify(cert, ctxt->sc->ca_list, 1038 ret = HTTP_FORBIDDEN; 1039 goto exit; 1040 } 1041 1042 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { 1043 apr_time_ansi_put(&expiration_time, 1044 gnutls_x509_crt_get_expiration_time(cert.x509)); 1045 apr_time_ansi_put(&activation_time, 1046 gnutls_x509_crt_get_activation_time(cert.x509)); 1047 1048 rv = gnutls_x509_crt_verify(cert.x509, ctxt->sc->ca_list, 913 1049 ctxt->sc->ca_list_size, 0, &status); 1050 } else { 1051 apr_time_ansi_put(&expiration_time, 1052 gnutls_openpgp_crt_get_expiration_time(cert.pgp)); 1053 apr_time_ansi_put(&activation_time, 1054 gnutls_openpgp_crt_get_creation_time(cert.pgp)); 1055 1056 rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list, 1057 0, &status); 1058 } 914 1059 915 1060 if (rv < 0) { … … 917 1062 "GnuTLS: Failed to Verify Peer certificate: (%d) %s", 918 1063 rv, gnutls_strerror(rv)); 1064 if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) 1065 ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, 1066 "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); 919 1067 ret = HTTP_FORBIDDEN; 920 1068 goto exit; 921 1069 } 1070 1071 /* TODO: X509 CRL Verification. */ 1072 /* May add later if anyone needs it. 1073 */ 1074 /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ 922 1075 923 1076 expired = 0; … … 955 1108 } 956 1109 957 /* TODO: Further Verification. */ 958 /* Revocation is X.509 non workable paradigm, I really doubt implementation 959 * is worth doing --nmav 960 */ 961 /// ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); 962 963 // mgs_hook_fixups(r); 964 // rv = mgs_authz_lua(r); 965 966 mgs_add_common_cert_vars(r, cert, 1, 1110 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) 1111 mgs_add_common_cert_vars(r, cert.x509, 1, 1112 ctxt->sc->export_certificates_enabled); 1113 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) 1114 mgs_add_common_pgpcert_vars(r, cert.pgp, 1, 967 1115 ctxt->sc->export_certificates_enabled); 968 1116 … … 988 1136 989 1137 exit: 990 gnutls_x509_crt_deinit(cert); 1138 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) 1139 gnutls_x509_crt_deinit(cert.x509); 1140 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) 1141 gnutls_openpgp_crt_deinit(cert.pgp); 991 1142 return ret; 992 1143
Note: See TracChangeset
for help on using the changeset viewer.