1 #include <stdio.h> 2 #include <netdb.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 #include <err.h> 6 #include <sys/socket.h> 7 8 #include <openssl/ssl.h> 9 #include <openssl/ocsp.h> 10 11 static int 12 tcp_connect(char *host, char *port) 13 { 14 int error, sd = -1; 15 struct addrinfo hints, *res, *r; 16 17 memset(&hints, 0, sizeof(struct addrinfo)); 18 hints.ai_family = AF_INET; 19 hints.ai_socktype = SOCK_STREAM; 20 21 error = getaddrinfo(host, port, &hints, &res); 22 if (error != 0) { 23 perror("getaddrinfo()"); 24 exit(-1); 25 } 26 27 for (r = res; r != NULL; r = r->ai_next) { 28 sd = socket(r->ai_family, r->ai_socktype, r->ai_protocol); 29 if (sd == -1) 30 continue; 31 32 if (connect(sd, r->ai_addr, r->ai_addrlen) == 0) 33 break; 34 35 close(sd); 36 } 37 38 freeaddrinfo(res); 39 40 return sd; 41 } 42 43 int 44 main(int argc, char *argv[]) 45 { 46 int sd, ocsp_status; 47 const unsigned char *p; 48 long len; 49 OCSP_RESPONSE *rsp = NULL; 50 OCSP_BASICRESP *br = NULL; 51 X509_STORE *st = NULL; 52 STACK_OF(X509) *ch = NULL; 53 char *host, *port; 54 #ifdef _PATH_SSL_CA_FILE 55 char *cafile = _PATH_SSL_CA_FILE; 56 #else 57 char *cafile = "/etc/ssl/cert.pem"; 58 #endif 59 60 SSL *ssl; 61 SSL_CTX *ctx; 62 63 SSL_library_init(); 64 SSL_load_error_strings(); 65 66 ctx = SSL_CTX_new(SSLv23_client_method()); 67 68 if (!SSL_CTX_load_verify_locations(ctx, cafile, NULL)) { 69 printf("failed to load %s\n", cafile); 70 exit(-1); 71 } 72 73 if (argc != 3) 74 errx(-1, "need a host and port to connect to"); 75 else { 76 host = argv[1]; 77 port = argv[2]; 78 } 79 80 sd = tcp_connect(host, port); 81 82 ssl = SSL_new(ctx); 83 84 SSL_set_fd(ssl, (int) sd); 85 SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp); 86 87 if (SSL_connect(ssl) <= 0) { 88 printf("SSL connect error\n"); 89 exit(-1); 90 } 91 92 if (SSL_get_verify_result(ssl) != X509_V_OK) { 93 printf("Certificate doesn't verify from host %s port %s\n", host, port); 94 exit(-1); 95 } 96 97 /* ==== VERIFY OCSP RESPONSE ==== */ 98 99 100 len = SSL_get_tlsext_status_ocsp_resp(ssl, &p); 101 102 if (!p) { 103 printf("No OCSP response received for %s port %s\n", host, port); 104 exit(-1); 105 } 106 107 rsp = d2i_OCSP_RESPONSE(NULL, &p, len); 108 if (!rsp) { 109 puts("Invalid OCSP response"); 110 exit(-1); 111 } 112 113 ocsp_status = OCSP_response_status(rsp); 114 if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 115 printf("Invalid OCSP response status: %s (%d)", 116 OCSP_response_status_str(ocsp_status), ocsp_status); 117 exit(-1); 118 } 119 120 br = OCSP_response_get1_basic(rsp); 121 if (!br) { 122 puts("Invalid OCSP response"); 123 exit(-1); 124 } 125 126 ch = SSL_get_peer_cert_chain(ssl); 127 st = SSL_CTX_get_cert_store(ctx); 128 129 if (OCSP_basic_verify(br, ch, st, 0) <= 0) { 130 puts("OCSP response verification failed"); 131 exit(-1); 132 } 133 134 printf("OCSP validated from %s %s\n", host, port); 135 136 return 0; 137 } 138