#include #include #include #include #include #include #include #include "os.h" #include #include #include #include #include #include #include #include #include //asd #define ALLOW_INVALID_PURPOSE 0x00000001 #define ALLOW_SELF_SIGNED_CERT_IN_CHAIN 0x00000002 #define VERIFY_SHOW_CERTS 0x80000000 #define SHUT_RD 0 /* == Win32 SD_RECEIVE */ #define SHUT_WR 1 /* == Win32 SD_SEND */ #define SHUT_RDWR 2 /* == Win32 SD_BOTH */ unsigned long verify_control_flags = 0; int dump_cert_names = 0; int ignore_all_verify_errors = 0; char * rootcert = "-----BEGIN CERTIFICATE-----\n" "MIIDbDCCAtWgAwIBAgIBKTANBgkqhkiG9w0BAQQFADCBkTELMAkGA1UEBhMCVVMx\n" "CzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTYW4gRGllZ28xEzARBgNVBAoTClZlcmlt\n" "YXRyaXgxDTALBgNVBAsTBFZDQVMxGzAZBgNVBAMTElZlcmltYXRyaXggUk9PVCBD\n" "QTEgMB4GCSqGSIb3DQEJARYRQ0FAVmVyaW1hdHJpeC5jb20wHhcNMDUwMzIzMjA0\n" "NzEwWhcNMTUwMzIxMjA0NzEwWjCBhzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB\n" "MRMwEQYDVQQKEwpWZXJpbWF0cml4MQ0wCwYDVQQLEwRWQ0FTMRQwEgYDVQQDEwtN\n" "aWtlIEJlYXR0eTExMC8GCSqGSIb3DQEJARYiU1VCQ0EuMTExMTYxMDgyOTg0M0BW\n" "ZXJpbWF0cml4LmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy0us/E8u\n" "2vH1x6AcwDHllaMz3SdJ1plknmOPn2IgPHoOdg+PR2ciAR4wOzXUyOkasUhn8FyS\n" "p+lPQiv/vfMxu6zG4NtwRF5NIWqCG06pXUIYR3JH4HSbfhf+9IIHsn2HwPolBBRq\n" "zDJRkKKVLWSlYLjneqhWkYCFLkTshSyw2vcCAwEAAaOB2zCB2DAdBgNVHQ4EFgQU\n" "CfPXPsVfPryHZq9o7/soM3JAtZUwgagGA1UdIwSBoDCBnaGBl6SBlDCBkTELMAkG\n" "A1UEBhMCVVMxCzAJBgNVBAgTAkNBMRIwEAYDVQQHEwlTYW4gRGllZ28xEzARBgNV\n" "BAoTClZlcmltYXRyaXgxDTALBgNVBAsTBFZDQVMxGzAZBgNVBAMTElZlcmltYXRy\n" "aXggUk9PVCBDQTEgMB4GCSqGSIb3DQEJARYRQ0FAVmVyaW1hdHJpeC5jb22CAQAw\n" "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBr9fD+FC5Of2LJb1pw+hUO\n" "WKFmgulTkVGO5tFo2EddK5k/RywxJ76QmM+ej0Zz9AsvWDJO6HQmpwm8WQbxyG6F\n" "jq5xKAUJMSmQv3UYY7uwcmcZbtnU6OYfm5zIz1p7F9oJsCWBX3nPQ3SE7DP7xBBK\n" "KsHR1fLvK1pdTPsSpJsQvw==\n" "-----END CERTIFICATE-----\n"; int ip_connect( char * host, int port ) { struct sockaddr_in sa; int s = -1; /* Set-up the sockaddr_in structure */ memset((char *)&sa,0,sizeof(sa)); sa.sin_family=AF_INET; sa.sin_port=(unsigned short)port; sa.sin_addr.s_addr = inet_addr(host); SM_printf("connect port = %x\r\n", sa.sin_port); /* Create the socket */ s = socket( AF_INET, SOCK_STREAM, 0 ); if (s == -1) { SM_printf("failed to create the socket\r\n"); return -1; } /* Connect */ if ( connect( s, (struct sockaddr*)&sa, sizeof(sa) ) == -1 ) { SM_printf("failed to connect\r\n"); close(s); return -1; } return s; #if 0 unsigned long addr; // struct sockaddr_in them; sockaddr them; //struct hostent * pHostEnt; //char ** pHostAddr = NULL; int s = -1; /* resolve IP address */ addr = inet_addr(host); if ( -1 == addr ) { SM_printf("Host address must be an IPv4 IP Address\n"); //SM_printf("Failed to connect, err = %d (%s)\r\n", e, strerror(e)); return -1; } /* Set-up the sockaddr_in structure */ memset((char *)&them,0,sizeof(them)); them.sin_family=AF_INET; //them.sin_port=htons((unsigned short)port); them.sin_port=(unsigned short)port; them.sin_addr.s_addr = inet_addr(host); //memcpy( (void *)&them.sin_addr, (void *)&addr, sizeof(addr) ); /* create the socket */ //s = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); s = socket(AF_INET, SOCK_STREAM, 0); if (-1 == s) { SM_printf("Failed to create socket %d\n",errno); return -1; } if (connect(s, &them, sizeof(them)) == -1) { // if (connect(s, &them, sizeof(them) ) == -1 ) { int e = errno; SM_printf("Failed to connect, err = %d (%s)\n", e, strerror(e) ); close( s ); return -1; } SM_printf("Socket (%d) connect OK to %s:%d\n", s, host, port); return s; #endif } void print_cert( X509 * cert ) { X509_PURPOSE *ptmp; int j, id, i, idret; char *pname; BIO *STDout=NULL; // Create BIO object for stdout STDout=BIO_new_fp(stdout,BIO_NOCLOSE); // Print the certificate text X509_print_ex( STDout, cert, 0, 0 ); // Print the Certificate Purposes // This code is from openssl/apps/x509.c BIO_printf(STDout, " Certificate purposes:\n"); for (j = 0; j < X509_PURPOSE_get_count(); j++) { ptmp = X509_PURPOSE_get0(j); id = X509_PURPOSE_get_id(ptmp); pname = X509_PURPOSE_get0_name(ptmp); for (i = 0; i < 2; i++) { idret = X509_check_purpose(cert, id, i); BIO_printf(STDout, " %s%s : ", pname, i ? " CA" : ""); if (idret == 1) BIO_printf(STDout, "Yes\n"); else if (idret == 0) BIO_printf(STDout, "No\n"); else BIO_printf(STDout, "Yes (WARNING code=%d)\n", idret); } } // Free our BIO object BIO_free_all(STDout); } X509 * get_issuer( X509_STORE_CTX *ctx ) { X509 *issuer, *tmp_issuer = NULL, *err_cert; int res; // Ensure we have an X509 Store Context if ( !ctx ) { SM_printf( "no CTX\n" ); return NULL; } err_cert = X509_STORE_CTX_get_current_cert(ctx); if ( NULL == err_cert ) { SM_printf("No cert to get issuer of\n"); return NULL; } // Obtain the issuer cert issuer = ctx->current_issuer; // If the issuer has not been set, try to get it from the trusted // certs in the store. If this works, the cert will have to be freed // later. if ( !issuer ) { // It is not set yet, try getting it from the store res = X509_STORE_CTX_get1_issuer( &tmp_issuer, ctx, err_cert ); issuer = tmp_issuer; if ( issuer ) { //SM_printf( "Got issuer from trusted certs\n" ); } } if ( !issuer) { // If we did not get the issuer from the trusted certs, // try getting it from the stack of untrusted certs. // If this works we just get a pointer to the stack // entry and must NOT free it. int i; X509 *potential_issuer; for (i = 0; i < sk_X509_num(ctx->untrusted); i++) { potential_issuer = sk_X509_value(ctx->untrusted, i); if (ctx->check_issued(ctx, err_cert, potential_issuer)) issuer = potential_issuer; } if ( issuer ) { //SM_printf("Got issuer from untrusted certs\n"); } } if ( !issuer ) { SM_printf( "Could not find issuer cert\n"); } //else //{ // SM_printf( "Have issuer cert\n" ); //} // This should be freed to avoid memory leaks, // but this is just a test app, so let it leak! //if (tmp_issuer) // X509_free(tmp_issuer); return issuer; } void log_ssl_verify_errors( int verify_result ) { switch( verify_result ) { default: SM_printf("UNKNOWN SSL Verify error %ld\n", verify_result); break; case X509_V_OK: SM_printf("SSL Verify OK\n"); break; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: SM_printf("SSL Verify UNABLE_TO_GET_ISSUER_CERT\n"); break; case X509_V_ERR_CERT_NOT_YET_VALID: SM_printf("SSL Verify CERT_NOT_YET_VALID\n"); break; case X509_V_ERR_CERT_HAS_EXPIRED: SM_printf("SSL Verify CERT_HAS_EXPIRED\n"); break; case X509_V_ERR_INVALID_PURPOSE: SM_printf("SSL Verify INVALID_PURPOSE\n"); break; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: SM_printf("SSL Verify UNABLE_TO_GET_ISSUER_CERT_LOCALLY\n"); break; case X509_V_ERR_PATH_LENGTH_EXCEEDED: SM_printf("SSL Verify PATH_LENGTH_EXCEEDED\n"); break; case X509_V_ERR_CERT_UNTRUSTED: SM_printf("SSL Verify CERT_UNTRUSTED\n"); break; case X509_V_ERR_CERT_REJECTED: SM_printf("SSL Verify CERT_REJECTED\n"); break; case X509_V_ERR_UNABLE_TO_GET_CRL: SM_printf("SSL Verify UNABLE_TO_GET_CRL\n"); break; case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: SM_printf("SSL Verify UNABLE_TO_DECRYPT_CERT_SIGNATURE\n"); break; case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: SM_printf("SSL Verify UNABLE_TO_DECRYPT_CRL_SIGNATURE\n"); break; case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: SM_printf("SSL Verify UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY\n"); break; case X509_V_ERR_CERT_SIGNATURE_FAILURE: SM_printf("SSL Verify CERT_SIGNATURE_FAILURE\n"); break; case X509_V_ERR_CRL_SIGNATURE_FAILURE: SM_printf("SSL Verify CRL_SIGNATURE_FAILURE\n"); break; case X509_V_ERR_CRL_NOT_YET_VALID: SM_printf("SSL Verify ERR_CRL_NOT_YET_VALID\n"); break; case X509_V_ERR_CRL_HAS_EXPIRED: SM_printf("SSL Verify CRL_HAS_EXPIRED\n"); break; case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: SM_printf("SSL Verify ERROR_IN_CERT_NOT_BEFORE_FIELD\n"); break; case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: SM_printf("SSL Verify ERROR_IN_CERT_NOT_AFTER_FIELD\n"); break; case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: SM_printf("SSL Verify ERROR_IN_CRL_LAST_UPDATE_FIELD\n"); break; case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: SM_printf("SSL Verify ERROR_IN_CRL_NEXT_UPDATE_FIELD\n"); break; case X509_V_ERR_OUT_OF_MEM: SM_printf("SSL Verify OUT_OF_MEM\n"); break; case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: SM_printf("SSL Verify DEPTH_ZERO_SELF_SIGNED_CERT\n"); break; case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: SM_printf("SSL Verify SELF_SIGNED_CERT_IN_CHAIN\n"); break; case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: SM_printf("SSL Verify UNABLE_TO_VERIFY_LEAF_SIGNATURE\n"); break; case X509_V_ERR_CERT_CHAIN_TOO_LONG: SM_printf("SSL Verify CERT_CHAIN_TOO_LONG\n"); break; case X509_V_ERR_CERT_REVOKED: SM_printf("SSL Verify CERT_REVOKED\n"); break; case X509_V_ERR_INVALID_CA: SM_printf("SSL Verify INVALID_CA\n"); break; case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: SM_printf("SSL Verify SUBJECT_ISSUER_MISMATCH\n"); break; case X509_V_ERR_AKID_SKID_MISMATCH: SM_printf("SSL Verify AKID_SKID_MISMATCH\n"); break; case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: SM_printf("SSL Verify AKID_ISSUER_SERIAL_MISMATCH\n"); break; case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: SM_printf("SSL Verify UNABLE_TO_GET_CRL_ISSUER\n"); break; /* case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: case X509_V_ERR_INVALID_NON_CA: case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: case X509_V_ERR_INVALID_EXTENSION: case X509_V_ERR_INVALID_POLICY_EXTENSION: case X509_V_ERR_NO_EXPLICIT_POLICY: case X509_V_ERR_UNNESTED_RESOURCE: case X509_V_ERR_APPLICATION_VERIFICATION: */ } } #if 0 void log_ssl_errors( ) { unsigned long err; char * sErrStr; SM_printf("log_ssl_errors -- \n"); err = ERR_get_error(); SM_printf("ERR_get_error Error code %d\n",err); while( err != 0 ) { SM_printf("Use NULL for error buffer so OpenSSL internal buffer is used.\n"); // This internal buffer is not thread safe! sErrStr = (char *)ERR_error_string( err, NULL ); if ( sErrStr != NULL ) SM_printf("%lu - %s\n", err, sErrStr ); } } #endif X509 * pem_to_x509( char * pem ) { X509 * pX509 = NULL; BIO * pBio = NULL; /* Allocate BIO object*/ pBio = BIO_new( BIO_s_mem() ); if ( pBio == NULL ) return NULL; /* Put the raw certificate (char format) into the BIO object */ BIO_write( pBio, pem, strlen(pem) ); /* Parse the certificate */ pX509 = (struct x509_st *)PEM_ASN1_read_bio( (char *(*)())d2i_X509 /* DER to Internal conversion fn */ , PEM_STRING_X509 /* PEM Marker string from pem.h */ , pBio /* BIO containing cert PEM data */ , NULL , NULL , NULL ); /* Free the BIO structure */ BIO_free(pBio); /* Return the Cert */ return pX509; } #define MAX_DEPTH 3 int my_verify_callback(int ok, X509_STORE_CTX *ctx) { X509 *err_cert, *issuer; int err; int depth; char buf[256]; SM_printf("my_verify_callback \n"); err_cert = X509_STORE_CTX_get_current_cert(ctx); err = X509_STORE_CTX_get_error(ctx); depth = X509_STORE_CTX_get_error_depth(ctx); SM_printf("------------ Begin Verify Callback --------------\n"); X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof buf); if ( dump_cert_names ) { SM_printf("verifying certificate: %s\n", buf); print_cert( err_cert ); SM_printf("\n"); } X509_NAME_oneline(X509_get_issuer_name(err_cert),buf,sizeof buf); if ( dump_cert_names ) { SM_printf("issued by : %s\n", buf); issuer = get_issuer( ctx ); if ( issuer ) print_cert( issuer ); else SM_printf("No issuer yet\n"); SM_printf("\n"); } if ( !ok ) { if ( depth >= MAX_DEPTH ) { SM_printf("Verify callback: depth( %d ) exceeds %d\n", depth, MAX_DEPTH ); X509_STORE_CTX_set_error(ctx,X509_V_ERR_CERT_CHAIN_TOO_LONG); ok = 0; } switch( ctx->error ) { case X509_V_OK: SM_printf( "!ok but X509_V_OK?, just say OK\n"); ok = 1; break; case X509_V_ERR_INVALID_PURPOSE: if ( verify_control_flags & ALLOW_INVALID_PURPOSE ) { SM_printf("ignoring INVALID_PURPOSE error\n"); X509_STORE_CTX_set_error(ctx,X509_V_OK); ok = 1; } break; case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: if ( verify_control_flags & ALLOW_SELF_SIGNED_CERT_IN_CHAIN ) { SM_printf("ignoring SELF_SIGNED_CERT_IN_CHAIN error\n"); X509_STORE_CTX_set_error(ctx,X509_V_OK); ok = 1; } break; default: if ( ignore_all_verify_errors ) { SM_printf("ignoring verify error (%d)", ctx->error); log_ssl_verify_errors( ctx->error ); X509_STORE_CTX_set_error(ctx,X509_V_OK); ok = 1; } else { SM_printf("verify callback failing on "); log_ssl_verify_errors( ctx->error ); } break; } } SM_printf("------------ End Verify Callback --------------\n"); return(ok); } void usage() { SM_printf("ssltest [options]\n"); SM_printf(" -s server_addr\n"); SM_printf(" -p server_port\n"); SM_printf(" -v : disable client validation of server\n"); SM_printf(" -f flags : 1 to allow invalid purpose\n"); SM_printf(" : 2 to allow self signed cert in chain\n"); SM_printf(" : 32 to show certs being verified\n"); SM_printf(" -o : omit setting local trusted rootcert\n"); SM_printf(" -i : ignore all verify errors\n"); } int ssltest(char *server, int port_num) { // char * server; int port; SSL_CTX * sslctx = NULL; /* SSL Context */ SSL * sslcon = NULL; /* SSL Connection handle */ int s = -1; /* socket */ int err; int e; BIO * sbio = NULL; //int c; int verify_peer = 1; //int tmp; X509 * root_x509 = NULL; int omit_rootcert = 0; SM_printf("ssltest: test function --- \n"); /* if ( argc < 3 ) { usage(); return 0; } */ /* while ((c = getopt(argc, argv, "inovf:s:p:")) != -1) switch (c) { case 'v': verify_peer = 0; break; case 's': server = optarg; break; case 'p': port = atoi(optarg); break; case 'f': tmp = atoi(optarg); if ( tmp > 0 ) verify_control_flags |= (1 << (tmp-1)); break; case 'o': omit_rootcert = 1; break; case 'i': ignore_all_verify_errors = 1; verify_control_flags = 0xFFFFFFFF; break; case 'n': dump_cert_names = 1; case '?': case 'h': usage(argv[0]); return 0; } */ // server = "192.168.1.12"; port = port_num; // port = 8090; // port = 12697; ignore_all_verify_errors = 1; verify_control_flags = 0xFFFFFFFF; verify_peer = 0; /* Check that port is valid */ if ( port <= 0 ) { SM_printf("invalid port %d\n", port ); return 0; } /* Dump the Validation Flags */ if ( verify_peer ) { if ( ignore_all_verify_errors ) { SM_printf("Verify Peer ignoring all validation errors\n"); } else if ( verify_control_flags ) { SM_printf("Verify Peer: (%x)\n",verify_control_flags); if ( verify_control_flags & ALLOW_INVALID_PURPOSE ) SM_printf(" :Allow Invalid Purpose\n"); if ( verify_control_flags & ALLOW_SELF_SIGNED_CERT_IN_CHAIN ) SM_printf(" :Allow Self Signed Cert In Chain\n"); if ( verify_control_flags & VERIFY_SHOW_CERTS ) { dump_cert_names = 1; SM_printf(" :Show names of certs being verified\n"); } } else { SM_printf("Verify Peer with no error exceptions\n"); } } else { SM_printf("Peer Verification disabled\n"); } do { /* Initialize OpenSSL */ OpenSSL_add_all_algorithms(); OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); OpenSSL_add_ssl_algorithms(); SSL_library_init(); SSL_load_error_strings(); /* Create an SSL Context */ sslctx = SSL_CTX_new(TLSv1_client_method()); if ( NULL == sslctx ) { SM_printf("Failed to create SSL Context\n"); break; } SM_printf("SSL_CTX_new log ssl errors\n"); log_ssl_errors(); /* Initialize the context */ SSL_CTX_set_quiet_shutdown(sslctx,1); SSL_CTX_set_options(sslctx, 0); SSL_CTX_sess_set_cache_size(sslctx,128); /* Setup for Peer Validation */ if ( verify_peer ) { if ( !omit_rootcert ) { SM_printf("setting local trusted rootcert\n"); root_x509 = pem_to_x509( rootcert ); if ( root_x509 ) X509_STORE_add_cert( sslctx->cert_store, root_x509 ); else { log_ssl_errors(); SM_printf("Failed to convert rootcert to X509 structure in verify setup\n"); } } else { SM_printf("omitted setting local trusted rootcert\n"); } SM_printf("enabbling client validation of server SSL certificate\n"); SSL_CTX_set_verify( sslctx , SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT , my_verify_callback ); SSL_CTX_set_verify_depth( sslctx, 3 ); } /* Create SSL Connection context */ sslcon = SSL_new(sslctx); if ( sslcon == NULL ) { SM_printf("SSL_new failed\n"); break; } SM_printf("SSL_new log ssl errors\n"); log_ssl_errors(); /* Establish connection to the server */ s = ip_connect( server, port ); if ( -1 == s ) { SM_printf("IP connection to %s on port %d Failed\n", server, port); break; } /* Wrap the connected socket in a BIO object so OpenSSL can use it */ sbio = BIO_new_socket( s, BIO_NOCLOSE ); if ( sbio == NULL ) { SM_printf("Failed to create socket BIO\n"); break; } SM_printf("BIO_new_socket log ssl errors\n"); log_ssl_errors(); SM_printf("sslcon->type %d\n",sslcon->type); SM_printf("sslcon->version %d\n",sslcon->version); //Protocol Version SM_printf("sslcon->rwstate %d\n",sslcon->rwstate); SM_printf("sslcon->in_handshake %d\n",sslcon->in_handshake); SM_printf("sslcon->handshake_func %d\n",sslcon->handshake_func); SM_printf("sslcon->state %d\n",sslcon->state); SM_printf("sslcon->rstate %d\n",sslcon->rstate); SM_printf("sslcon->init_num %d\n",sslcon->init_num); //amount read/written SM_printf("sslcon->error %d\n",sslcon->error); SM_printf("sslcon->error_code %d\n",sslcon->error_code); // Actual Error Code SM_printf("sslcon->client_version %d\n",sslcon->client_version); /* Give the connected socket to OpenSSL */ SM_printf("Give the connected socket to OpenSSL\n"); SSL_set_bio( sslcon, sbio, sbio ); SSL_set_connect_state( sslcon ); /* Perform the SSL handshake to complete the SSL connection */ while( 1 ) { /* do the SSL connection */ SM_printf("do the SSL connection\n"); err = SSL_connect( sslcon ); SM_printf("SSL_connect status %d\n", err); /* Check for success */ if ( err > 0 ) { log_ssl_errors(); log_ssl_verify_errors( sslcon->verify_result ); SM_printf("SSL_connect succeeded\n"); break; } /* Error was returned */ e = SSL_get_error( sslcon, err ); if ( (SSL_ERROR_WANT_READ != e) && (SSL_ERROR_WANT_WRITE != e) ) { SM_printf("SSL_connect Error %d\n", e); log_ssl_errors(); int e = errno; SM_printf("sockerrno to connect, err = %d (%s)\n", e, strerror(e) ); log_ssl_verify_errors( sslcon->verify_result ); SM_printf("SSL_connect Failed\n"); SM_printf("sslcon->type %d\n",sslcon->type); SM_printf("sslcon->version %d\n",sslcon->version); //Protocol Version SM_printf("sslcon->rwstate %d\n",sslcon->rwstate); SM_printf("sslcon->in_handshake %d\n",sslcon->in_handshake); SM_printf("sslcon->handshake_func %d\n",sslcon->handshake_func); SM_printf("sslcon->state %d\n",sslcon->state); SM_printf("sslcon->rstate %d\n",sslcon->rstate); SM_printf("sslcon->init_num %d\n",sslcon->init_num); //amount read/written SM_printf("sslcon->error %d\n",sslcon->error); SM_printf("sslcon->error_code %d\n",sslcon->error_code); // Actual Error Code SM_printf("sslcon->client_version %d\n",sslcon->client_version); break; } /* OpenSSL wants to retry */ SM_printf("Retry SSL_connect\n"); } /* Connection has either been established, or it has failed */ } while ( 0 ); /* Free allocated resources */ SM_printf("freeing resources\n"); if ( sslcon ) { SSL_shutdown( sslcon ); shutdown( SSL_get_fd(sslcon), SHUT_RDWR ); SSL_free( sslcon ); } if ( s != -1 ) { shutdown( s, SHUT_RDWR ); close( s ); } if ( sslctx ) SSL_CTX_free( sslctx ); if ( root_x509 ) X509_free( root_x509 ); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0); ERR_free_strings(); return 0; }