Annotation of src/usr.bin/openssl/s_cb.c, Revision 1.1
1.1 ! jsing 1: /* $OpenBSD: s_cb.c,v 1.22 2014/06/13 04:29:13 miod Exp $ */
! 2: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
! 3: * All rights reserved.
! 4: *
! 5: * This package is an SSL implementation written
! 6: * by Eric Young (eay@cryptsoft.com).
! 7: * The implementation was written so as to conform with Netscapes SSL.
! 8: *
! 9: * This library is free for commercial and non-commercial use as long as
! 10: * the following conditions are aheared to. The following conditions
! 11: * apply to all code found in this distribution, be it the RC4, RSA,
! 12: * lhash, DES, etc., code; not just the SSL code. The SSL documentation
! 13: * included with this distribution is covered by the same copyright terms
! 14: * except that the holder is Tim Hudson (tjh@cryptsoft.com).
! 15: *
! 16: * Copyright remains Eric Young's, and as such any Copyright notices in
! 17: * the code are not to be removed.
! 18: * If this package is used in a product, Eric Young should be given attribution
! 19: * as the author of the parts of the library used.
! 20: * This can be in the form of a textual message at program startup or
! 21: * in documentation (online or textual) provided with the package.
! 22: *
! 23: * Redistribution and use in source and binary forms, with or without
! 24: * modification, are permitted provided that the following conditions
! 25: * are met:
! 26: * 1. Redistributions of source code must retain the copyright
! 27: * notice, this list of conditions and the following disclaimer.
! 28: * 2. Redistributions in binary form must reproduce the above copyright
! 29: * notice, this list of conditions and the following disclaimer in the
! 30: * documentation and/or other materials provided with the distribution.
! 31: * 3. All advertising materials mentioning features or use of this software
! 32: * must display the following acknowledgement:
! 33: * "This product includes cryptographic software written by
! 34: * Eric Young (eay@cryptsoft.com)"
! 35: * The word 'cryptographic' can be left out if the rouines from the library
! 36: * being used are not cryptographic related :-).
! 37: * 4. If you include any Windows specific code (or a derivative thereof) from
! 38: * the apps directory (application code) you must include an acknowledgement:
! 39: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
! 40: *
! 41: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
! 42: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 43: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 44: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 45: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 46: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 47: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 48: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 49: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 50: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 51: * SUCH DAMAGE.
! 52: *
! 53: * The licence and distribution terms for any publically available version or
! 54: * derivative of this code cannot be changed. i.e. this code cannot simply be
! 55: * copied and put under another distribution licence
! 56: * [including the GNU Public Licence.]
! 57: */
! 58: /* ====================================================================
! 59: * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
! 60: *
! 61: * Redistribution and use in source and binary forms, with or without
! 62: * modification, are permitted provided that the following conditions
! 63: * are met:
! 64: *
! 65: * 1. Redistributions of source code must retain the above copyright
! 66: * notice, this list of conditions and the following disclaimer.
! 67: *
! 68: * 2. Redistributions in binary form must reproduce the above copyright
! 69: * notice, this list of conditions and the following disclaimer in
! 70: * the documentation and/or other materials provided with the
! 71: * distribution.
! 72: *
! 73: * 3. All advertising materials mentioning features or use of this
! 74: * software must display the following acknowledgment:
! 75: * "This product includes software developed by the OpenSSL Project
! 76: * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
! 77: *
! 78: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
! 79: * endorse or promote products derived from this software without
! 80: * prior written permission. For written permission, please contact
! 81: * openssl-core@openssl.org.
! 82: *
! 83: * 5. Products derived from this software may not be called "OpenSSL"
! 84: * nor may "OpenSSL" appear in their names without prior written
! 85: * permission of the OpenSSL Project.
! 86: *
! 87: * 6. Redistributions of any form whatsoever must retain the following
! 88: * acknowledgment:
! 89: * "This product includes software developed by the OpenSSL Project
! 90: * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
! 91: *
! 92: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
! 93: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 94: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 95: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
! 96: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! 97: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 98: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
! 99: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 100: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 101: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 102: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
! 103: * OF THE POSSIBILITY OF SUCH DAMAGE.
! 104: * ====================================================================
! 105: *
! 106: * This product includes cryptographic software written by Eric Young
! 107: * (eay@cryptsoft.com). This product includes software written by Tim
! 108: * Hudson (tjh@cryptsoft.com).
! 109: *
! 110: */
! 111:
! 112: #include <sys/socket.h>
! 113:
! 114: #include <netinet/in.h>
! 115:
! 116: #include <netdb.h>
! 117: #include <stdio.h>
! 118: #include <stdlib.h>
! 119: #include <string.h>
! 120:
! 121: #include "apps.h"
! 122:
! 123: #include <openssl/err.h>
! 124: #include <openssl/rand.h>
! 125: #include <openssl/ssl.h>
! 126: #include <openssl/x509.h>
! 127:
! 128: #include "s_apps.h"
! 129:
! 130: #define COOKIE_SECRET_LENGTH 16
! 131:
! 132: int verify_depth = 0;
! 133: int verify_error = X509_V_OK;
! 134: int verify_return_error = 0;
! 135: unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
! 136: int cookie_initialized = 0;
! 137:
! 138: int
! 139: verify_callback(int ok, X509_STORE_CTX * ctx)
! 140: {
! 141: X509 *err_cert;
! 142: int err, depth;
! 143:
! 144: err_cert = X509_STORE_CTX_get_current_cert(ctx);
! 145: err = X509_STORE_CTX_get_error(ctx);
! 146: depth = X509_STORE_CTX_get_error_depth(ctx);
! 147:
! 148: BIO_printf(bio_err, "depth=%d ", depth);
! 149: if (err_cert) {
! 150: X509_NAME_print_ex(bio_err, X509_get_subject_name(err_cert),
! 151: 0, XN_FLAG_ONELINE);
! 152: BIO_puts(bio_err, "\n");
! 153: } else
! 154: BIO_puts(bio_err, "<no cert>\n");
! 155: if (!ok) {
! 156: BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
! 157: X509_verify_cert_error_string(err));
! 158: if (verify_depth >= depth) {
! 159: if (!verify_return_error)
! 160: ok = 1;
! 161: verify_error = X509_V_OK;
! 162: } else {
! 163: ok = 0;
! 164: verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
! 165: }
! 166: }
! 167: switch (err) {
! 168: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
! 169: BIO_puts(bio_err, "issuer= ");
! 170: X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
! 171: 0, XN_FLAG_ONELINE);
! 172: BIO_puts(bio_err, "\n");
! 173: break;
! 174: case X509_V_ERR_CERT_NOT_YET_VALID:
! 175: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
! 176: BIO_printf(bio_err, "notBefore=");
! 177: ASN1_TIME_print(bio_err, X509_get_notBefore(err_cert));
! 178: BIO_printf(bio_err, "\n");
! 179: break;
! 180: case X509_V_ERR_CERT_HAS_EXPIRED:
! 181: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
! 182: BIO_printf(bio_err, "notAfter=");
! 183: ASN1_TIME_print(bio_err, X509_get_notAfter(err_cert));
! 184: BIO_printf(bio_err, "\n");
! 185: break;
! 186: case X509_V_ERR_NO_EXPLICIT_POLICY:
! 187: policies_print(bio_err, ctx);
! 188: break;
! 189: }
! 190: if (err == X509_V_OK && ok == 2)
! 191: policies_print(bio_err, ctx);
! 192:
! 193: BIO_printf(bio_err, "verify return:%d\n", ok);
! 194: return (ok);
! 195: }
! 196:
! 197: int
! 198: set_cert_stuff(SSL_CTX * ctx, char *cert_file, char *key_file)
! 199: {
! 200: if (cert_file != NULL) {
! 201: /*
! 202: SSL *ssl;
! 203: X509 *x509;
! 204: */
! 205:
! 206: if (SSL_CTX_use_certificate_file(ctx, cert_file,
! 207: SSL_FILETYPE_PEM) <= 0) {
! 208: BIO_printf(bio_err,
! 209: "unable to get certificate from '%s'\n", cert_file);
! 210: ERR_print_errors(bio_err);
! 211: return (0);
! 212: }
! 213: if (key_file == NULL)
! 214: key_file = cert_file;
! 215: if (SSL_CTX_use_PrivateKey_file(ctx, key_file,
! 216: SSL_FILETYPE_PEM) <= 0) {
! 217: BIO_printf(bio_err,
! 218: "unable to get private key from '%s'\n", key_file);
! 219: ERR_print_errors(bio_err);
! 220: return (0);
! 221: }
! 222: /*
! 223: In theory this is no longer needed
! 224: ssl=SSL_new(ctx);
! 225: x509=SSL_get_certificate(ssl);
! 226:
! 227: if (x509 != NULL) {
! 228: EVP_PKEY *pktmp;
! 229: pktmp = X509_get_pubkey(x509);
! 230: EVP_PKEY_copy_parameters(pktmp,
! 231: SSL_get_privatekey(ssl));
! 232: EVP_PKEY_free(pktmp);
! 233: }
! 234: SSL_free(ssl);
! 235: */
! 236:
! 237: /*
! 238: * If we are using DSA, we can copy the parameters from the
! 239: * private key
! 240: */
! 241:
! 242:
! 243: /*
! 244: * Now we know that a key and cert have been set against the
! 245: * SSL context
! 246: */
! 247: if (!SSL_CTX_check_private_key(ctx)) {
! 248: BIO_printf(bio_err,
! 249: "Private key does not match the certificate public key\n");
! 250: return (0);
! 251: }
! 252: }
! 253: return (1);
! 254: }
! 255:
! 256: int
! 257: set_cert_key_stuff(SSL_CTX * ctx, X509 * cert, EVP_PKEY * key)
! 258: {
! 259: if (cert == NULL)
! 260: return 1;
! 261: if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
! 262: BIO_printf(bio_err, "error setting certificate\n");
! 263: ERR_print_errors(bio_err);
! 264: return 0;
! 265: }
! 266: if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) {
! 267: BIO_printf(bio_err, "error setting private key\n");
! 268: ERR_print_errors(bio_err);
! 269: return 0;
! 270: }
! 271: /*
! 272: * Now we know that a key and cert have been set against the SSL
! 273: * context
! 274: */
! 275: if (!SSL_CTX_check_private_key(ctx)) {
! 276: BIO_printf(bio_err,
! 277: "Private key does not match the certificate public key\n");
! 278: return 0;
! 279: }
! 280: return 1;
! 281: }
! 282:
! 283: long
! 284: bio_dump_callback(BIO * bio, int cmd, const char *argp,
! 285: int argi, long argl, long ret)
! 286: {
! 287: BIO *out;
! 288:
! 289: out = (BIO *) BIO_get_callback_arg(bio);
! 290: if (out == NULL)
! 291: return (ret);
! 292:
! 293: if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
! 294: BIO_printf(out,
! 295: "read from %p [%p] (%lu bytes => %ld (0x%lX))\n",
! 296: (void *) bio, argp, (unsigned long) argi, ret, ret);
! 297: BIO_dump(out, argp, (int) ret);
! 298: return (ret);
! 299: } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
! 300: BIO_printf(out,
! 301: "write to %p [%p] (%lu bytes => %ld (0x%lX))\n",
! 302: (void *) bio, argp, (unsigned long) argi, ret, ret);
! 303: BIO_dump(out, argp, (int) ret);
! 304: }
! 305: return (ret);
! 306: }
! 307:
! 308: void
! 309: apps_ssl_info_callback(const SSL * s, int where, int ret)
! 310: {
! 311: const char *str;
! 312: int w;
! 313:
! 314: w = where & ~SSL_ST_MASK;
! 315:
! 316: if (w & SSL_ST_CONNECT)
! 317: str = "SSL_connect";
! 318: else if (w & SSL_ST_ACCEPT)
! 319: str = "SSL_accept";
! 320: else
! 321: str = "undefined";
! 322:
! 323: if (where & SSL_CB_LOOP) {
! 324: BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s));
! 325: } else if (where & SSL_CB_ALERT) {
! 326: str = (where & SSL_CB_READ) ? "read" : "write";
! 327: BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n", str,
! 328: SSL_alert_type_string_long(ret),
! 329: SSL_alert_desc_string_long(ret));
! 330: } else if (where & SSL_CB_EXIT) {
! 331: if (ret == 0)
! 332: BIO_printf(bio_err, "%s:failed in %s\n",
! 333: str, SSL_state_string_long(s));
! 334: else if (ret < 0) {
! 335: BIO_printf(bio_err, "%s:error in %s\n",
! 336: str, SSL_state_string_long(s));
! 337: }
! 338: }
! 339: }
! 340:
! 341:
! 342: void
! 343: msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL * ssl, void *arg)
! 344: {
! 345: BIO *bio = arg;
! 346: const char *str_write_p, *str_version, *str_content_type = "",
! 347: *str_details1 = "", *str_details2 = "";
! 348:
! 349: str_write_p = write_p ? ">>>" : "<<<";
! 350:
! 351: switch (version) {
! 352: case SSL2_VERSION:
! 353: str_version = "SSL 2.0";
! 354: break;
! 355: case SSL3_VERSION:
! 356: str_version = "SSL 3.0 ";
! 357: break;
! 358: case TLS1_VERSION:
! 359: str_version = "TLS 1.0 ";
! 360: break;
! 361: case TLS1_1_VERSION:
! 362: str_version = "TLS 1.1 ";
! 363: break;
! 364: case TLS1_2_VERSION:
! 365: str_version = "TLS 1.2 ";
! 366: break;
! 367: case DTLS1_VERSION:
! 368: str_version = "DTLS 1.0 ";
! 369: break;
! 370: case DTLS1_BAD_VER:
! 371: str_version = "DTLS 1.0 (bad) ";
! 372: break;
! 373: default:
! 374: str_version = "???";
! 375: }
! 376:
! 377: if (version == SSL2_VERSION) {
! 378: str_details1 = "???";
! 379:
! 380: if (len > 0) {
! 381: switch (((const unsigned char *) buf)[0]) {
! 382: case 0:
! 383: str_details1 = ", ERROR:";
! 384: str_details2 = " ???";
! 385: if (len >= 3) {
! 386: unsigned err = (((const unsigned char *) buf)[1] << 8) + ((const unsigned char *) buf)[2];
! 387:
! 388: switch (err) {
! 389: case 0x0001:
! 390: str_details2 = " NO-CIPHER-ERROR";
! 391: break;
! 392: case 0x0002:
! 393: str_details2 = " NO-CERTIFICATE-ERROR";
! 394: break;
! 395: case 0x0004:
! 396: str_details2 = " BAD-CERTIFICATE-ERROR";
! 397: break;
! 398: case 0x0006:
! 399: str_details2 = " UNSUPPORTED-CERTIFICATE-TYPE-ERROR";
! 400: break;
! 401: }
! 402: }
! 403: break;
! 404: case 1:
! 405: str_details1 = ", CLIENT-HELLO";
! 406: break;
! 407: case 2:
! 408: str_details1 = ", CLIENT-MASTER-KEY";
! 409: break;
! 410: case 3:
! 411: str_details1 = ", CLIENT-FINISHED";
! 412: break;
! 413: case 4:
! 414: str_details1 = ", SERVER-HELLO";
! 415: break;
! 416: case 5:
! 417: str_details1 = ", SERVER-VERIFY";
! 418: break;
! 419: case 6:
! 420: str_details1 = ", SERVER-FINISHED";
! 421: break;
! 422: case 7:
! 423: str_details1 = ", REQUEST-CERTIFICATE";
! 424: break;
! 425: case 8:
! 426: str_details1 = ", CLIENT-CERTIFICATE";
! 427: break;
! 428: }
! 429: }
! 430: }
! 431: if (version == SSL3_VERSION || version == TLS1_VERSION ||
! 432: version == TLS1_1_VERSION || version == TLS1_2_VERSION ||
! 433: version == DTLS1_VERSION || version == DTLS1_BAD_VER) {
! 434: switch (content_type) {
! 435: case 20:
! 436: str_content_type = "ChangeCipherSpec";
! 437: break;
! 438: case 21:
! 439: str_content_type = "Alert";
! 440: break;
! 441: case 22:
! 442: str_content_type = "Handshake";
! 443: break;
! 444: }
! 445:
! 446: if (content_type == 21) { /* Alert */
! 447: str_details1 = ", ???";
! 448:
! 449: if (len == 2) {
! 450: switch (((const unsigned char *) buf)[0]) {
! 451: case 1:
! 452: str_details1 = ", warning";
! 453: break;
! 454: case 2:
! 455: str_details1 = ", fatal";
! 456: break;
! 457: }
! 458:
! 459: str_details2 = " ???";
! 460: switch (((const unsigned char *) buf)[1]) {
! 461: case 0:
! 462: str_details2 = " close_notify";
! 463: break;
! 464: case 10:
! 465: str_details2 = " unexpected_message";
! 466: break;
! 467: case 20:
! 468: str_details2 = " bad_record_mac";
! 469: break;
! 470: case 21:
! 471: str_details2 = " decryption_failed";
! 472: break;
! 473: case 22:
! 474: str_details2 = " record_overflow";
! 475: break;
! 476: case 30:
! 477: str_details2 = " decompression_failure";
! 478: break;
! 479: case 40:
! 480: str_details2 = " handshake_failure";
! 481: break;
! 482: case 42:
! 483: str_details2 = " bad_certificate";
! 484: break;
! 485: case 43:
! 486: str_details2 = " unsupported_certificate";
! 487: break;
! 488: case 44:
! 489: str_details2 = " certificate_revoked";
! 490: break;
! 491: case 45:
! 492: str_details2 = " certificate_expired";
! 493: break;
! 494: case 46:
! 495: str_details2 = " certificate_unknown";
! 496: break;
! 497: case 47:
! 498: str_details2 = " illegal_parameter";
! 499: break;
! 500: case 48:
! 501: str_details2 = " unknown_ca";
! 502: break;
! 503: case 49:
! 504: str_details2 = " access_denied";
! 505: break;
! 506: case 50:
! 507: str_details2 = " decode_error";
! 508: break;
! 509: case 51:
! 510: str_details2 = " decrypt_error";
! 511: break;
! 512: case 60:
! 513: str_details2 = " export_restriction";
! 514: break;
! 515: case 70:
! 516: str_details2 = " protocol_version";
! 517: break;
! 518: case 71:
! 519: str_details2 = " insufficient_security";
! 520: break;
! 521: case 80:
! 522: str_details2 = " internal_error";
! 523: break;
! 524: case 90:
! 525: str_details2 = " user_canceled";
! 526: break;
! 527: case 100:
! 528: str_details2 = " no_renegotiation";
! 529: break;
! 530: case 110:
! 531: str_details2 = " unsupported_extension";
! 532: break;
! 533: case 111:
! 534: str_details2 = " certificate_unobtainable";
! 535: break;
! 536: case 112:
! 537: str_details2 = " unrecognized_name";
! 538: break;
! 539: case 113:
! 540: str_details2 = " bad_certificate_status_response";
! 541: break;
! 542: case 114:
! 543: str_details2 = " bad_certificate_hash_value";
! 544: break;
! 545: case 115:
! 546: str_details2 = " unknown_psk_identity";
! 547: break;
! 548: }
! 549: }
! 550: }
! 551: if (content_type == 22) { /* Handshake */
! 552: str_details1 = "???";
! 553:
! 554: if (len > 0) {
! 555: switch (((const unsigned char *) buf)[0]) {
! 556: case 0:
! 557: str_details1 = ", HelloRequest";
! 558: break;
! 559: case 1:
! 560: str_details1 = ", ClientHello";
! 561: break;
! 562: case 2:
! 563: str_details1 = ", ServerHello";
! 564: break;
! 565: case 3:
! 566: str_details1 = ", HelloVerifyRequest";
! 567: break;
! 568: case 11:
! 569: str_details1 = ", Certificate";
! 570: break;
! 571: case 12:
! 572: str_details1 = ", ServerKeyExchange";
! 573: break;
! 574: case 13:
! 575: str_details1 = ", CertificateRequest";
! 576: break;
! 577: case 14:
! 578: str_details1 = ", ServerHelloDone";
! 579: break;
! 580: case 15:
! 581: str_details1 = ", CertificateVerify";
! 582: break;
! 583: case 16:
! 584: str_details1 = ", ClientKeyExchange";
! 585: break;
! 586: case 20:
! 587: str_details1 = ", Finished";
! 588: break;
! 589: }
! 590: }
! 591: }
! 592: }
! 593: BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p,
! 594: str_version, str_content_type, (unsigned long) len,
! 595: str_details1, str_details2);
! 596:
! 597: if (len > 0) {
! 598: size_t num, i;
! 599:
! 600: BIO_printf(bio, " ");
! 601: num = len;
! 602: #if 0
! 603: if (num > 16)
! 604: num = 16;
! 605: #endif
! 606: for (i = 0; i < num; i++) {
! 607: if (i % 16 == 0 && i > 0)
! 608: BIO_printf(bio, "\n ");
! 609: BIO_printf(bio, " %02x",
! 610: ((const unsigned char *) buf)[i]);
! 611: }
! 612: if (i < len)
! 613: BIO_printf(bio, " ...");
! 614: BIO_printf(bio, "\n");
! 615: }
! 616: (void) BIO_flush(bio);
! 617: }
! 618:
! 619: void
! 620: tlsext_cb(SSL * s, int client_server, int type, unsigned char *data, int len,
! 621: void *arg)
! 622: {
! 623: BIO *bio = arg;
! 624: char *extname;
! 625:
! 626: switch (type) {
! 627: case TLSEXT_TYPE_server_name:
! 628: extname = "server name";
! 629: break;
! 630:
! 631: case TLSEXT_TYPE_max_fragment_length:
! 632: extname = "max fragment length";
! 633: break;
! 634:
! 635: case TLSEXT_TYPE_client_certificate_url:
! 636: extname = "client certificate URL";
! 637: break;
! 638:
! 639: case TLSEXT_TYPE_trusted_ca_keys:
! 640: extname = "trusted CA keys";
! 641: break;
! 642:
! 643: case TLSEXT_TYPE_truncated_hmac:
! 644: extname = "truncated HMAC";
! 645: break;
! 646:
! 647: case TLSEXT_TYPE_status_request:
! 648: extname = "status request";
! 649: break;
! 650:
! 651: case TLSEXT_TYPE_user_mapping:
! 652: extname = "user mapping";
! 653: break;
! 654:
! 655: case TLSEXT_TYPE_client_authz:
! 656: extname = "client authz";
! 657: break;
! 658:
! 659: case TLSEXT_TYPE_server_authz:
! 660: extname = "server authz";
! 661: break;
! 662:
! 663: case TLSEXT_TYPE_cert_type:
! 664: extname = "cert type";
! 665: break;
! 666:
! 667: case TLSEXT_TYPE_elliptic_curves:
! 668: extname = "elliptic curves";
! 669: break;
! 670:
! 671: case TLSEXT_TYPE_ec_point_formats:
! 672: extname = "EC point formats";
! 673: break;
! 674:
! 675: case TLSEXT_TYPE_srp:
! 676: extname = "SRP";
! 677: break;
! 678:
! 679: case TLSEXT_TYPE_signature_algorithms:
! 680: extname = "signature algorithms";
! 681: break;
! 682:
! 683: case TLSEXT_TYPE_use_srtp:
! 684: extname = "use SRTP";
! 685: break;
! 686:
! 687: case TLSEXT_TYPE_heartbeat:
! 688: extname = "heartbeat";
! 689: break;
! 690:
! 691: case TLSEXT_TYPE_session_ticket:
! 692: extname = "session ticket";
! 693: break;
! 694:
! 695: case TLSEXT_TYPE_renegotiate:
! 696: extname = "renegotiation info";
! 697: break;
! 698:
! 699: #ifdef TLSEXT_TYPE_next_proto_neg
! 700: case TLSEXT_TYPE_next_proto_neg:
! 701: extname = "next protocol";
! 702: break;
! 703: #endif
! 704:
! 705: default:
! 706: extname = "unknown";
! 707: break;
! 708:
! 709: }
! 710:
! 711: BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n",
! 712: client_server ? "server" : "client", extname, type, len);
! 713: BIO_dump(bio, (char *) data, len);
! 714: (void) BIO_flush(bio);
! 715: }
! 716:
! 717: int
! 718: generate_cookie_callback(SSL * ssl, unsigned char *cookie,
! 719: unsigned int *cookie_len)
! 720: {
! 721: unsigned char *buffer, result[EVP_MAX_MD_SIZE];
! 722: unsigned int length, resultlength;
! 723: union {
! 724: struct sockaddr sa;
! 725: struct sockaddr_in s4;
! 726: struct sockaddr_in6 s6;
! 727: } peer;
! 728:
! 729: /* Initialize a random secret */
! 730: if (!cookie_initialized) {
! 731: if (!RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH)) {
! 732: BIO_printf(bio_err,
! 733: "error setting random cookie secret\n");
! 734: return 0;
! 735: }
! 736: cookie_initialized = 1;
! 737: }
! 738: /* Read peer information */
! 739: (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
! 740:
! 741: /* Create buffer with peer's address and port */
! 742: length = 0;
! 743: switch (peer.sa.sa_family) {
! 744: case AF_INET:
! 745: length += sizeof(struct in_addr);
! 746: length += sizeof(peer.s4.sin_port);
! 747: break;
! 748: case AF_INET6:
! 749: length += sizeof(struct in6_addr);
! 750: length += sizeof(peer.s6.sin6_port);
! 751: break;
! 752: default:
! 753: OPENSSL_assert(0);
! 754: break;
! 755: }
! 756: buffer = malloc(length);
! 757:
! 758: if (buffer == NULL) {
! 759: BIO_printf(bio_err, "out of memory\n");
! 760: return 0;
! 761: }
! 762: switch (peer.sa.sa_family) {
! 763: case AF_INET:
! 764: memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port));
! 765: memcpy(buffer + sizeof(peer.s4.sin_port),
! 766: &peer.s4.sin_addr, sizeof(struct in_addr));
! 767: break;
! 768: case AF_INET6:
! 769: memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port));
! 770: memcpy(buffer + sizeof(peer.s6.sin6_port),
! 771: &peer.s6.sin6_addr, sizeof(struct in6_addr));
! 772: break;
! 773: default:
! 774: OPENSSL_assert(0);
! 775: break;
! 776: }
! 777:
! 778: /* Calculate HMAC of buffer using the secret */
! 779: HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH,
! 780: buffer, length, result, &resultlength);
! 781: free(buffer);
! 782:
! 783: memcpy(cookie, result, resultlength);
! 784: *cookie_len = resultlength;
! 785:
! 786: return 1;
! 787: }
! 788:
! 789: int
! 790: verify_cookie_callback(SSL * ssl, unsigned char *cookie, unsigned int cookie_len)
! 791: {
! 792: unsigned char *buffer, result[EVP_MAX_MD_SIZE];
! 793: unsigned int length, resultlength;
! 794: union {
! 795: struct sockaddr sa;
! 796: struct sockaddr_in s4;
! 797: struct sockaddr_in6 s6;
! 798: } peer;
! 799:
! 800: /* If secret isn't initialized yet, the cookie can't be valid */
! 801: if (!cookie_initialized)
! 802: return 0;
! 803:
! 804: /* Read peer information */
! 805: (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
! 806:
! 807: /* Create buffer with peer's address and port */
! 808: length = 0;
! 809: switch (peer.sa.sa_family) {
! 810: case AF_INET:
! 811: length += sizeof(struct in_addr);
! 812: length += sizeof(peer.s4.sin_port);
! 813: break;
! 814: case AF_INET6:
! 815: length += sizeof(struct in6_addr);
! 816: length += sizeof(peer.s6.sin6_port);
! 817: break;
! 818: default:
! 819: OPENSSL_assert(0);
! 820: break;
! 821: }
! 822: buffer = malloc(length);
! 823:
! 824: if (buffer == NULL) {
! 825: BIO_printf(bio_err, "out of memory\n");
! 826: return 0;
! 827: }
! 828: switch (peer.sa.sa_family) {
! 829: case AF_INET:
! 830: memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port));
! 831: memcpy(buffer + sizeof(peer.s4.sin_port),
! 832: &peer.s4.sin_addr, sizeof(struct in_addr));
! 833: break;
! 834: case AF_INET6:
! 835: memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port));
! 836: memcpy(buffer + sizeof(peer.s6.sin6_port),
! 837: &peer.s6.sin6_addr, sizeof(struct in6_addr));
! 838: break;
! 839: default:
! 840: OPENSSL_assert(0);
! 841: break;
! 842: }
! 843:
! 844: /* Calculate HMAC of buffer using the secret */
! 845: HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH,
! 846: buffer, length, result, &resultlength);
! 847: free(buffer);
! 848:
! 849: if (cookie_len == resultlength &&
! 850: memcmp(result, cookie, resultlength) == 0)
! 851: return 1;
! 852:
! 853: return 0;
! 854: }