/* paul2.c.txt */ // This code is provided "as is" with NO WARRANTY expressed or // implied. You may use it freely at your own risk. #include #include #include extern void die(char *s); extern char *formRequest(); extern char *getHost(char *hostname, int *portNum, char *arg); extern int SSLsocket(SSL *ssl, char *host, int port); extern int writeToSSLSocket(SSL *ssl, char *request); extern void printSSLServerResponse(SSL *ssl); /****************************************** This is just a place-holder function. If you've stored a hash of the server cert name in order to be REALLY sure you're talking to the right guy, return it here. *******************************************/ unsigned long getHash() { return 1L; } int my_verify_callback(int ok, X509_STORE_CTX *ctx) { X509 *cert; int err; char c; /* the variable ok will be 0 here because the callback */ /* doesn't get called unless the chain is !ok */ cert = X509_STORE_CTX_get_current_cert(ctx); err = X509_STORE_CTX_get_error(ctx); printf("Error verifying: %s\n", X509_NAME_oneline(X509_get_subject_name(cert), 0, 0)); printf("Error: number %d: %s\n", err, X509_verify_cert_error_string(err)); printf("Accept it anyway? (y/n) "); c = getchar(); if (c == 'y') ok = 1; return ok; } /******************************************** ******************* MAIN ******************** *********************************************/ int main(int argc, char *argv[]) { char hostName[128]; int, i; int port; int result; char *request; SSL *ssl = NULL; SSL_CTX *ssl_ctx = NULL; X509 *server_cert, *next_cert; STACK_OF(X509) *chain; if (argc < 2) { die("Usage: paul2 hostname:port"); } strcpy(hostName, argv[1]); request = formRequest(); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); getHost(hostName, &port, argv[1]); ssl_ctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_load_verify_locations(ssl_ctx, "nRSA.pem", 0); SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, &my_verify_callback); ssl = SSL_new(ssl_ctx); result = SSLsocket(ssl, hostName, port); server_cert = SSL_get_peer_certificate(ssl); chain = SSL_get_peer_cert_chain(ssl); result = ssl_verify_cert_chain(ssl, chain); printf("Verify: %d\n", result); if (!result) die("Invalid cert chain!"); printf("%d certs in chain\n", chain->stack.num); for (i = 0; i < chain->stack.num; i++) { next_cert = (X509 *)chain->stack.data[0]; if (next_cert) { printf("\t%d: %s\n", i, X509_NAME_oneline( X509_get_subject_name(next_cert), 0, 0)); printf("\t%d: %s\n", i, X509_NAME_oneline( X509_get_issuer_name(next_cert), 0, 0)); } } result = writeToSSLSocket(ssl, request); printSSLServerResponse(ssl); SSL_shutdown(ssl); free(ssl); if (ssl_ctx != NULL) SSL_CTX_free(ssl_ctx); free(request); return 0; }