| OLD | NEW |
| (Empty) |
| 1 /* Licensed to the Apache Software Foundation (ASF) under one or more | |
| 2 * contributor license agreements. See the NOTICE file distributed with | |
| 3 * this work for additional information regarding copyright ownership. | |
| 4 * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| 5 * (the "License"); you may not use this file except in compliance with | |
| 6 * the License. You may obtain a copy of the License at | |
| 7 * | |
| 8 * http://www.apache.org/licenses/LICENSE-2.0 | |
| 9 * | |
| 10 * Unless required by applicable law or agreed to in writing, software | |
| 11 * distributed under the License is distributed on an "AS IS" BASIS, | |
| 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 13 * See the License for the specific language governing permissions and | |
| 14 * limitations under the License. | |
| 15 */ | |
| 16 | |
| 17 /** SSL info wrapper | |
| 18 * | |
| 19 * @author Mladen Turk | |
| 20 * @version $Id: sslinfo.c 1658603 2015-02-09 23:26:44Z kkolinko $ | |
| 21 */ | |
| 22 | |
| 23 #include "tcn.h" | |
| 24 #include "apr_file_io.h" | |
| 25 #include "apr_thread_mutex.h" | |
| 26 #include "apr_poll.h" | |
| 27 | |
| 28 #ifdef HAVE_OPENSSL | |
| 29 #include "ssl_private.h" | |
| 30 | |
| 31 static const char *hex_basis = "0123456789ABCDEF"; | |
| 32 | |
| 33 static char *convert_to_hex(const void *buf, size_t len) | |
| 34 { | |
| 35 const unsigned char *p = ( const unsigned char *)buf; | |
| 36 char *str, *s; | |
| 37 size_t i; | |
| 38 | |
| 39 if ((len < 1) || ((str = malloc(len * 2 + 1)) == NULL)) | |
| 40 return NULL; | |
| 41 for (i = 0, s = str; i < len; i++) { | |
| 42 unsigned char c = *p++; | |
| 43 *s++ = hex_basis[c >> 4]; | |
| 44 *s++ = hex_basis[c & 0x0F]; | |
| 45 } | |
| 46 *s = '\0'; | |
| 47 return str; | |
| 48 } | |
| 49 | |
| 50 #define DIGIT2NUM(x) (((x)[0] - '0') * 10 + (x)[1] - '0') | |
| 51 | |
| 52 static int get_days_remaining(ASN1_UTCTIME *tm) | |
| 53 { | |
| 54 apr_time_t then, now = apr_time_now(); | |
| 55 apr_time_exp_t exp = {0}; | |
| 56 int diff; | |
| 57 | |
| 58 /* Fail if the time isn't a valid ASN.1 UTCTIME; RFC3280 mandates | |
| 59 * that the seconds digits are present even though ASN.1 | |
| 60 * doesn't. */ | |
| 61 if (tm->length < 11 || !ASN1_UTCTIME_check(tm)) | |
| 62 return 0; | |
| 63 | |
| 64 exp.tm_year = DIGIT2NUM(tm->data); | |
| 65 exp.tm_mon = DIGIT2NUM(tm->data + 2) - 1; | |
| 66 exp.tm_mday = DIGIT2NUM(tm->data + 4) + 1; | |
| 67 exp.tm_hour = DIGIT2NUM(tm->data + 6); | |
| 68 exp.tm_min = DIGIT2NUM(tm->data + 8); | |
| 69 exp.tm_sec = DIGIT2NUM(tm->data + 10); | |
| 70 | |
| 71 if (exp.tm_year <= 50) | |
| 72 exp.tm_year += 100; | |
| 73 if (apr_time_exp_gmt_get(&then, &exp) != APR_SUCCESS) | |
| 74 return 0; | |
| 75 | |
| 76 diff = (int)((apr_time_sec(then) - apr_time_sec(now)) / (60*60*24)); | |
| 77 return diff > 0 ? diff : 0; | |
| 78 } | |
| 79 | |
| 80 static char *get_cert_valid(ASN1_UTCTIME *tm) | |
| 81 { | |
| 82 char *result; | |
| 83 BIO* bio; | |
| 84 int n; | |
| 85 | |
| 86 if ((bio = BIO_new(BIO_s_mem())) == NULL) | |
| 87 return NULL; | |
| 88 ASN1_UTCTIME_print(bio, tm); | |
| 89 n = BIO_pending(bio); | |
| 90 result = malloc(n+1); | |
| 91 n = BIO_read(bio, result, n); | |
| 92 result[n] = '\0'; | |
| 93 BIO_free(bio); | |
| 94 return result; | |
| 95 } | |
| 96 | |
| 97 static char *get_cert_PEM(X509 *xs) | |
| 98 { | |
| 99 char *result = NULL; | |
| 100 BIO *bio; | |
| 101 | |
| 102 if ((bio = BIO_new(BIO_s_mem())) == NULL) | |
| 103 return NULL; | |
| 104 if (PEM_write_bio_X509(bio, xs)) { | |
| 105 int n = BIO_pending(bio); | |
| 106 result = malloc(n+1); | |
| 107 n = BIO_read(bio, result, n); | |
| 108 result[n] = '\0'; | |
| 109 } | |
| 110 BIO_free(bio); | |
| 111 return result; | |
| 112 } | |
| 113 | |
| 114 static unsigned char *get_cert_ASN1(X509 *xs, int *len) | |
| 115 { | |
| 116 unsigned char *result = NULL; | |
| 117 BIO *bio; | |
| 118 | |
| 119 *len = 0; | |
| 120 if ((bio = BIO_new(BIO_s_mem())) == NULL) | |
| 121 return NULL; | |
| 122 if (i2d_X509_bio(bio, xs)) { | |
| 123 int n = BIO_pending(bio); | |
| 124 result = malloc(n); | |
| 125 n = BIO_read(bio, result, n); | |
| 126 *len = n; | |
| 127 } | |
| 128 BIO_free(bio); | |
| 129 return result; | |
| 130 } | |
| 131 | |
| 132 | |
| 133 static char *get_cert_serial(X509 *xs) | |
| 134 { | |
| 135 char *result; | |
| 136 BIO *bio; | |
| 137 int n; | |
| 138 | |
| 139 if ((bio = BIO_new(BIO_s_mem())) == NULL) | |
| 140 return NULL; | |
| 141 i2a_ASN1_INTEGER(bio, X509_get_serialNumber(xs)); | |
| 142 n = BIO_pending(bio); | |
| 143 result = malloc(n+1); | |
| 144 n = BIO_read(bio, result, n); | |
| 145 result[n] = '\0'; | |
| 146 BIO_free(bio); | |
| 147 return result; | |
| 148 } | |
| 149 | |
| 150 static const struct { | |
| 151 int fid; | |
| 152 int nid; | |
| 153 } info_cert_dn_rec[] = { | |
| 154 { SSL_INFO_DN_COUNTRYNAME, NID_countryName }, | |
| 155 { SSL_INFO_DN_STATEORPROVINCENAME, NID_stateOrProvinceName }, | |
| 156 { SSL_INFO_DN_LOCALITYNAME, NID_localityName }, | |
| 157 { SSL_INFO_DN_ORGANIZATIONNAME, NID_organizationName }, | |
| 158 { SSL_INFO_DN_ORGANIZATIONALUNITNAME, NID_organizationalUnitName }, | |
| 159 { SSL_INFO_DN_COMMONNAME, NID_commonName }, | |
| 160 { SSL_INFO_DN_TITLE, NID_title }, | |
| 161 { SSL_INFO_DN_INITIALS, NID_initials }, | |
| 162 { SSL_INFO_DN_GIVENNAME, NID_givenName }, | |
| 163 { SSL_INFO_DN_SURNAME, NID_surname }, | |
| 164 { SSL_INFO_DN_DESCRIPTION, NID_description }, | |
| 165 { SSL_INFO_DN_UNIQUEIDENTIFIER, NID_x500UniqueIdentifier }, | |
| 166 { SSL_INFO_DN_EMAILADDRESS, NID_pkcs9_emailAddress }, | |
| 167 { 0, 0 } | |
| 168 }; | |
| 169 | |
| 170 static char *lookup_ssl_cert_dn(X509_NAME *xsname, int dnidx) | |
| 171 { | |
| 172 char *result; | |
| 173 X509_NAME_ENTRY *xsne; | |
| 174 int i, j, n, idx = 0; | |
| 175 | |
| 176 result = NULL; | |
| 177 | |
| 178 for (i = 0; info_cert_dn_rec[i].fid != 0; i++) { | |
| 179 if (info_cert_dn_rec[i].fid == dnidx) { | |
| 180 for (j = 0; j < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *) | |
| 181 (xsname->entries)); j++) { | |
| 182 xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *) | |
| 183 (xsname->entries), j); | |
| 184 | |
| 185 n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); | |
| 186 if (n == info_cert_dn_rec[i].nid && idx-- == 0) { | |
| 187 result = malloc(xsne->value->length + 1); | |
| 188 memcpy(result, xsne->value->data, | |
| 189 xsne->value->length); | |
| 190 result[xsne->value->length] = '\0'; | |
| 191 | |
| 192 #if APR_CHARSET_EBCDIC | |
| 193 ap_xlate_proto_from_ascii(result, xsne->value->length); | |
| 194 #endif /* APR_CHARSET_EBCDIC */ | |
| 195 break; | |
| 196 } | |
| 197 } | |
| 198 break; | |
| 199 } | |
| 200 } | |
| 201 return result; | |
| 202 } | |
| 203 | |
| 204 TCN_IMPLEMENT_CALL(jobject, SSLSocket, getInfoB)(TCN_STDARGS, jlong sock, | |
| 205 jint what) | |
| 206 { | |
| 207 tcn_socket_t *a = J2P(sock, tcn_socket_t *); | |
| 208 tcn_ssl_conn_t *s; | |
| 209 jbyteArray array = NULL; | |
| 210 apr_status_t rv = APR_SUCCESS; | |
| 211 | |
| 212 UNREFERENCED(o); | |
| 213 TCN_ASSERT(sock != 0); | |
| 214 | |
| 215 s = (tcn_ssl_conn_t *)(a->opaque); | |
| 216 switch (what) { | |
| 217 case SSL_INFO_SESSION_ID: | |
| 218 { | |
| 219 SSL_SESSION *session = SSL_get_session(s->ssl); | |
| 220 if (session) { | |
| 221 unsigned int len; | |
| 222 const unsigned char *id = SSL_SESSION_get_id(session, &len); | |
| 223 array = tcn_new_arrayb(e, id, len); | |
| 224 } | |
| 225 } | |
| 226 break; | |
| 227 default: | |
| 228 rv = APR_EINVAL; | |
| 229 break; | |
| 230 } | |
| 231 if (what & SSL_INFO_CLIENT_MASK) { | |
| 232 X509 *xs; | |
| 233 unsigned char *result; | |
| 234 int len; | |
| 235 if ((xs = SSL_get_peer_certificate(s->ssl)) != NULL) { | |
| 236 switch (what) { | |
| 237 case SSL_INFO_CLIENT_CERT: | |
| 238 if ((result = get_cert_ASN1(xs, &len))) { | |
| 239 array = tcn_new_arrayb(e, result, len); | |
| 240 free(result); | |
| 241 } | |
| 242 break; | |
| 243 } | |
| 244 X509_free(xs); | |
| 245 } | |
| 246 rv = APR_SUCCESS; | |
| 247 } | |
| 248 else if (what & SSL_INFO_SERVER_MASK) { | |
| 249 X509 *xs; | |
| 250 unsigned char *result; | |
| 251 int len; | |
| 252 if ((xs = SSL_get_certificate(s->ssl)) != NULL) { | |
| 253 switch (what) { | |
| 254 case SSL_INFO_SERVER_CERT: | |
| 255 if ((result = get_cert_ASN1(xs, &len))) { | |
| 256 array = tcn_new_arrayb(e, result, len); | |
| 257 free(result); | |
| 258 } | |
| 259 break; | |
| 260 } | |
| 261 /* XXX: No need to call the X509_free(xs); */ | |
| 262 } | |
| 263 rv = APR_SUCCESS; | |
| 264 } | |
| 265 else if (what & SSL_INFO_CLIENT_CERT_CHAIN) { | |
| 266 X509 *xs; | |
| 267 unsigned char *result; | |
| 268 STACK_OF(X509) *sk = SSL_get_peer_cert_chain(s->ssl); | |
| 269 int len, n = what & 0x0F; | |
| 270 if (n < sk_X509_num(sk)) { | |
| 271 xs = sk_X509_value(sk, n); | |
| 272 if ((result = get_cert_ASN1(xs, &len))) { | |
| 273 array = tcn_new_arrayb(e, result, len); | |
| 274 free(result); | |
| 275 } | |
| 276 } | |
| 277 rv = APR_SUCCESS; | |
| 278 } | |
| 279 if (rv != APR_SUCCESS) | |
| 280 tcn_ThrowAPRException(e, rv); | |
| 281 | |
| 282 return array; | |
| 283 } | |
| 284 | |
| 285 TCN_IMPLEMENT_CALL(jstring, SSLSocket, getInfoS)(TCN_STDARGS, jlong sock, | |
| 286 jint what) | |
| 287 { | |
| 288 tcn_socket_t *a = J2P(sock, tcn_socket_t *); | |
| 289 tcn_ssl_conn_t *s; | |
| 290 jstring value = NULL; | |
| 291 apr_status_t rv = APR_SUCCESS; | |
| 292 | |
| 293 UNREFERENCED(o); | |
| 294 TCN_ASSERT(sock != 0); | |
| 295 | |
| 296 s = (tcn_ssl_conn_t *)(a->opaque); | |
| 297 switch (what) { | |
| 298 case SSL_INFO_SESSION_ID: | |
| 299 { | |
| 300 SSL_SESSION *session = SSL_get_session(s->ssl); | |
| 301 if (session) { | |
| 302 unsigned int len; | |
| 303 const unsigned char *id = SSL_SESSION_get_id(session, &len); | |
| 304 char *hs = convert_to_hex(id, len); | |
| 305 if (hs) { | |
| 306 value = tcn_new_string(e, hs); | |
| 307 free(hs); | |
| 308 } | |
| 309 } | |
| 310 } | |
| 311 break; | |
| 312 case SSL_INFO_PROTOCOL: | |
| 313 value = tcn_new_string(e, SSL_get_version(s->ssl)); | |
| 314 break; | |
| 315 case SSL_INFO_CIPHER: | |
| 316 value = tcn_new_string(e, SSL_get_cipher_name(s->ssl)); | |
| 317 break; | |
| 318 case SSL_INFO_CIPHER_VERSION: | |
| 319 value = tcn_new_string(e, SSL_get_cipher_version(s->ssl)); | |
| 320 break; | |
| 321 case SSL_INFO_CIPHER_DESCRIPTION: | |
| 322 { | |
| 323 SSL_CIPHER *cipher = (SSL_CIPHER *)SSL_get_current_cipher(s->ssl
); | |
| 324 if (cipher) { | |
| 325 char buf[256]; | |
| 326 const char *desc = SSL_CIPHER_description(cipher, buf, 256); | |
| 327 value = tcn_new_string(e, desc); | |
| 328 } | |
| 329 } | |
| 330 break; | |
| 331 default: | |
| 332 rv = APR_EINVAL; | |
| 333 break; | |
| 334 } | |
| 335 if (what & (SSL_INFO_CLIENT_S_DN | SSL_INFO_CLIENT_I_DN)) { | |
| 336 X509 *xs; | |
| 337 X509_NAME *xsname; | |
| 338 if ((xs = SSL_get_peer_certificate(s->ssl)) != NULL) { | |
| 339 char *result; | |
| 340 int idx = what & 0x0F; | |
| 341 if (what & SSL_INFO_CLIENT_S_DN) | |
| 342 xsname = X509_get_subject_name(xs); | |
| 343 else | |
| 344 xsname = X509_get_issuer_name(xs); | |
| 345 if (idx) { | |
| 346 result = lookup_ssl_cert_dn(xsname, idx); | |
| 347 if (result) { | |
| 348 value = tcn_new_string(e, result); | |
| 349 free(result); | |
| 350 } | |
| 351 } | |
| 352 else | |
| 353 value = tcn_new_string(e, X509_NAME_oneline(xsname, NULL, 0)); | |
| 354 X509_free(xs); | |
| 355 } | |
| 356 rv = APR_SUCCESS; | |
| 357 } | |
| 358 else if (what & (SSL_INFO_SERVER_S_DN | SSL_INFO_SERVER_I_DN)) { | |
| 359 X509 *xs; | |
| 360 X509_NAME *xsname; | |
| 361 if ((xs = SSL_get_certificate(s->ssl)) != NULL) { | |
| 362 char *result; | |
| 363 int idx = what & 0x0F; | |
| 364 if (what & SSL_INFO_SERVER_S_DN) | |
| 365 xsname = X509_get_subject_name(xs); | |
| 366 else | |
| 367 xsname = X509_get_issuer_name(xs); | |
| 368 if (idx) { | |
| 369 result = lookup_ssl_cert_dn(xsname, what & 0x0F); | |
| 370 if (result) { | |
| 371 value = tcn_new_string(e, result); | |
| 372 free(result); | |
| 373 } | |
| 374 } | |
| 375 else | |
| 376 value = tcn_new_string(e, X509_NAME_oneline(xsname, NULL, 0)); | |
| 377 /* XXX: No need to call the X509_free(xs); */ | |
| 378 } | |
| 379 rv = APR_SUCCESS; | |
| 380 } | |
| 381 else if (what & SSL_INFO_CLIENT_MASK) { | |
| 382 X509 *xs; | |
| 383 char *result; | |
| 384 int nid; | |
| 385 if ((xs = SSL_get_peer_certificate(s->ssl)) != NULL) { | |
| 386 switch (what) { | |
| 387 case SSL_INFO_CLIENT_V_START: | |
| 388 if ((result = get_cert_valid(X509_get_notBefore(xs)))) { | |
| 389 value = tcn_new_string(e, result); | |
| 390 free(result); | |
| 391 } | |
| 392 break; | |
| 393 case SSL_INFO_CLIENT_V_END: | |
| 394 if ((result = get_cert_valid(X509_get_notAfter(xs)))) { | |
| 395 value = tcn_new_string(e, result); | |
| 396 free(result); | |
| 397 } | |
| 398 break; | |
| 399 case SSL_INFO_CLIENT_A_SIG: | |
| 400 nid = OBJ_obj2nid((ASN1_OBJECT *)xs->cert_info->signature->a
lgorithm); | |
| 401 if (nid == NID_undef) | |
| 402 value = tcn_new_string(e, "UNKNOWN"); | |
| 403 else | |
| 404 value = tcn_new_string(e, OBJ_nid2ln(nid)); | |
| 405 break; | |
| 406 case SSL_INFO_CLIENT_A_KEY: | |
| 407 nid = OBJ_obj2nid((ASN1_OBJECT *)xs->cert_info->key->algor->
algorithm); | |
| 408 if (nid == NID_undef) | |
| 409 value = tcn_new_string(e, "UNKNOWN"); | |
| 410 else | |
| 411 value = tcn_new_string(e, OBJ_nid2ln(nid)); | |
| 412 break; | |
| 413 case SSL_INFO_CLIENT_CERT: | |
| 414 if ((result = get_cert_PEM(xs))) { | |
| 415 value = tcn_new_string(e, result); | |
| 416 free(result); | |
| 417 } | |
| 418 break; | |
| 419 case SSL_INFO_CLIENT_M_SERIAL: | |
| 420 if ((result = get_cert_serial(xs))) { | |
| 421 value = tcn_new_string(e, result); | |
| 422 free(result); | |
| 423 } | |
| 424 break; | |
| 425 } | |
| 426 X509_free(xs); | |
| 427 } | |
| 428 rv = APR_SUCCESS; | |
| 429 } | |
| 430 else if (what & SSL_INFO_SERVER_MASK) { | |
| 431 X509 *xs; | |
| 432 char *result; | |
| 433 int nid; | |
| 434 if ((xs = SSL_get_certificate(s->ssl)) != NULL) { | |
| 435 switch (what) { | |
| 436 case SSL_INFO_SERVER_V_START: | |
| 437 if ((result = get_cert_valid(X509_get_notBefore(xs)))) { | |
| 438 value = tcn_new_string(e, result); | |
| 439 free(result); | |
| 440 } | |
| 441 break; | |
| 442 case SSL_INFO_SERVER_V_END: | |
| 443 if ((result = get_cert_valid(X509_get_notAfter(xs)))) { | |
| 444 value = tcn_new_string(e, result); | |
| 445 free(result); | |
| 446 } | |
| 447 break; | |
| 448 case SSL_INFO_SERVER_A_SIG: | |
| 449 nid = OBJ_obj2nid((ASN1_OBJECT *)xs->cert_info->signature->a
lgorithm); | |
| 450 if (nid == NID_undef) | |
| 451 value = tcn_new_string(e, "UNKNOWN"); | |
| 452 else | |
| 453 value = tcn_new_string(e, OBJ_nid2ln(nid)); | |
| 454 break; | |
| 455 case SSL_INFO_SERVER_A_KEY: | |
| 456 nid = OBJ_obj2nid((ASN1_OBJECT *)xs->cert_info->key->algor->
algorithm); | |
| 457 if (nid == NID_undef) | |
| 458 value = tcn_new_string(e, "UNKNOWN"); | |
| 459 else | |
| 460 value = tcn_new_string(e, OBJ_nid2ln(nid)); | |
| 461 break; | |
| 462 case SSL_INFO_SERVER_CERT: | |
| 463 if ((result = get_cert_PEM(xs))) { | |
| 464 value = tcn_new_string(e, result); | |
| 465 free(result); | |
| 466 } | |
| 467 break; | |
| 468 case SSL_INFO_SERVER_M_SERIAL: | |
| 469 if ((result = get_cert_serial(xs))) { | |
| 470 value = tcn_new_string(e, result); | |
| 471 free(result); | |
| 472 } | |
| 473 break; | |
| 474 } | |
| 475 /* XXX: No need to call the X509_free(xs); */ | |
| 476 } | |
| 477 rv = APR_SUCCESS; | |
| 478 } | |
| 479 else if (what & SSL_INFO_CLIENT_CERT_CHAIN) { | |
| 480 X509 *xs; | |
| 481 char *result; | |
| 482 STACK_OF(X509) *sk = SSL_get_peer_cert_chain(s->ssl); | |
| 483 int n = what & 0x0F; | |
| 484 if (n < sk_X509_num(sk)) { | |
| 485 xs = sk_X509_value(sk, n); | |
| 486 if ((result = get_cert_PEM(xs))) { | |
| 487 value = tcn_new_string(e, result); | |
| 488 free(result); | |
| 489 } | |
| 490 } | |
| 491 rv = APR_SUCCESS; | |
| 492 } | |
| 493 if (rv != APR_SUCCESS) | |
| 494 tcn_ThrowAPRException(e, rv); | |
| 495 | |
| 496 return value; | |
| 497 } | |
| 498 | |
| 499 TCN_IMPLEMENT_CALL(jint, SSLSocket, getInfoI)(TCN_STDARGS, jlong sock, | |
| 500 jint what) | |
| 501 { | |
| 502 tcn_socket_t *a = J2P(sock, tcn_socket_t *); | |
| 503 tcn_ssl_conn_t *s; | |
| 504 apr_status_t rv = APR_SUCCESS; | |
| 505 jint value = -1; | |
| 506 | |
| 507 UNREFERENCED(o); | |
| 508 TCN_ASSERT(sock != 0); | |
| 509 | |
| 510 s = (tcn_ssl_conn_t *)(a->opaque); | |
| 511 | |
| 512 switch (what) { | |
| 513 case SSL_INFO_CIPHER_USEKEYSIZE: | |
| 514 case SSL_INFO_CIPHER_ALGKEYSIZE: | |
| 515 { | |
| 516 int usekeysize = 0; | |
| 517 int algkeysize = 0; | |
| 518 const SSL_CIPHER *cipher = SSL_get_current_cipher(s->ssl); | |
| 519 if (cipher) { | |
| 520 usekeysize = SSL_CIPHER_get_bits(cipher, &algkeysize); | |
| 521 if (what == SSL_INFO_CIPHER_USEKEYSIZE) | |
| 522 value = usekeysize; | |
| 523 else | |
| 524 value = algkeysize; | |
| 525 } | |
| 526 } | |
| 527 break; | |
| 528 case SSL_INFO_CLIENT_CERT_CHAIN: | |
| 529 { | |
| 530 STACK_OF(X509) *sk = SSL_get_peer_cert_chain(s->ssl); | |
| 531 value = sk_X509_num(sk); | |
| 532 } | |
| 533 break; | |
| 534 default: | |
| 535 rv = APR_EINVAL; | |
| 536 break; | |
| 537 } | |
| 538 if (what & SSL_INFO_CLIENT_MASK) { | |
| 539 X509 *xs; | |
| 540 if ((xs = SSL_get_peer_certificate(s->ssl)) != NULL) { | |
| 541 switch (what) { | |
| 542 case SSL_INFO_CLIENT_V_REMAIN: | |
| 543 value = get_days_remaining(X509_get_notAfter(xs)); | |
| 544 rv = APR_SUCCESS; | |
| 545 break; | |
| 546 default: | |
| 547 rv = APR_EINVAL; | |
| 548 break; | |
| 549 } | |
| 550 X509_free(xs); | |
| 551 } | |
| 552 } | |
| 553 | |
| 554 if (rv != APR_SUCCESS) | |
| 555 tcn_ThrowAPRException(e, rv); | |
| 556 return value; | |
| 557 } | |
| 558 | |
| 559 #else | |
| 560 /* OpenSSL is not supported. | |
| 561 * Create empty stubs. | |
| 562 */ | |
| 563 | |
| 564 TCN_IMPLEMENT_CALL(jobject, SSLSocket, getInfoB)(TCN_STDARGS, jlong sock, | |
| 565 jint what) | |
| 566 { | |
| 567 UNREFERENCED_STDARGS; | |
| 568 UNREFERENCED(sock); | |
| 569 UNREFERENCED(what); | |
| 570 return NULL; | |
| 571 } | |
| 572 | |
| 573 TCN_IMPLEMENT_CALL(jstring, SSLSocket, getInfoS)(TCN_STDARGS, jlong sock, | |
| 574 jint what) | |
| 575 { | |
| 576 UNREFERENCED_STDARGS; | |
| 577 UNREFERENCED(sock); | |
| 578 UNREFERENCED(what); | |
| 579 return NULL; | |
| 580 } | |
| 581 | |
| 582 TCN_IMPLEMENT_CALL(jint, SSLSocket, getInfoI)(TCN_STDARGS, jlong sock, | |
| 583 jint what) | |
| 584 { | |
| 585 UNREFERENCED_STDARGS; | |
| 586 UNREFERENCED(sock); | |
| 587 UNREFERENCED(what); | |
| 588 return 0; | |
| 589 } | |
| 590 | |
| 591 #endif | |
| OLD | NEW |