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