int /* returns -1 if error, 0 if verfy fail, and 1 if verify OK */ smime_verify_cert(const char* ca_cert_pem, const char* cert_pem) { X509* ca_cert = NULL; X509* cert = NULL; int ret = -1; if (!ca_cert_pem || !cert_pem) GOTO_ERR("NULL arg(s)"); if (!(ca_cert = extract_certificate(ca_cert_pem))) goto err; if (!(cert = extract_certificate(cert_pem))) goto err; ret = verify_cert(ca_cert, cert); err: if (ca_cert) X509_free(ca_cert); if (cert) X509_free(cert); return ret; }
int verify_callback (int preverify_ok, X509_STORE_CTX * ctx) { int ret = 0; struct tls_session *session; SSL *ssl; struct gc_arena gc = gc_new(); /* get the tls_session pointer */ ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); ASSERT (ssl); session = (struct tls_session *) SSL_get_ex_data (ssl, mydata_index); ASSERT (session); cert_hash_remember (session, ctx->error_depth, x509_get_sha1_hash(ctx->current_cert, &gc)); /* did peer present cert which was signed by our root cert? */ if (!preverify_ok) { /* get the X509 name */ char *subject = x509_get_subject(ctx->current_cert, &gc); if (subject) { /* Remote site specified a certificate, but it's not correct */ msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s", ctx->error_depth, X509_verify_cert_error_string (ctx->error), subject); } ERR_clear_error(); session->verified = false; goto cleanup; } if (SUCCESS != verify_cert(session, ctx->current_cert, ctx->error_depth)) goto cleanup; ret = 1; cleanup: gc_free(&gc); return ret; }
int verify_callback (void *session_obj, x509_crt *cert, int cert_depth, int *flags) { struct tls_session *session = (struct tls_session *) session_obj; struct gc_arena gc = gc_new(); ASSERT (cert); ASSERT (session); session->verified = false; /* Remember certificate hash */ cert_hash_remember (session, cert_depth, x509_get_sha1_hash(cert, &gc)); /* did peer present cert which was signed by our root cert? */ if (*flags != 0) { char *subject = x509_get_subject(cert, &gc); if (subject) msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, flags=%x, %s", cert_depth, *flags, subject); else msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, flags=%x, could not extract X509 " "subject string from certificate", *flags, cert_depth); /* Leave flags set to non-zero to indicate that the cert is not ok */ } else if (SUCCESS != verify_cert(session, cert, cert_depth)) { *flags |= BADCERT_OTHER; } gc_free(&gc); /* * PolarSSL-1.2.0+ expects 0 on anything except fatal errors. */ return 0; }
static int exchange_certificates(struct openssl_session_auth_context* ctx, char** client_certificate, u32* client_certificate_length, char** server_certificate, u32* server_certificate_length, struct in_addr* remote_addr) { int ret, server_cert_verification_result_code, client_cert_verification_result_code; char* common_name = NULL; u32 common_name_length; /* Load server certificate */ if( load_cert(module_context->path_to_publickey, server_certificate, server_certificate_length) || *server_certificate_length <= 0 ) { printf("Failed to load public key: %s\n", module_context->path_to_publickey); goto failed; } /* Just check if we are able to verify certificate against our own CA */ if ( verify_cert(*server_certificate, *server_certificate_length, &common_name, &common_name_length) ) { printf("Failed to verify own certificate against the CA. Cert file: %s\n", module_context->path_to_publickey); goto failed; } /* Send server certificate length */ if ( write_u32(ctx, *server_certificate_length) != 4) { printf("Failed to send server certificate length\n"); goto failed; } /* Send server certificate */ if ( openssl_local_write(ctx, *server_certificate, *server_certificate_length) != *server_certificate_length ) { printf("Failed to send server certificate\n"); goto failed; } /* Reads verification result of server certificate validation by the client */ server_cert_verification_result_code = read_u32(ctx); if ( server_cert_verification_result_code == READ_ERROR ) { printf("Failed to read client response on server certificate validation\n"); goto failed; } else if ( server_cert_verification_result_code == 0 ) { printf("Client failed to validate server certificate\n"); goto failed; } /* Reads client certificate length */ *client_certificate_length = read_u32(ctx); if ( *client_certificate_length == READ_ERROR ) { printf("Failed to read client certificate length\n"); goto failed; } /* Reads client certificate */ *client_certificate = malloc(*client_certificate_length); if ( *client_certificate == NULL ) goto failed; if ( openssl_local_read(ctx, *client_certificate_length, *client_certificate, client_certificate_length) < *client_certificate_length ) { printf( "Failed to read client certificate\n"); goto failed; } /* Verifies client certificate against CA */ ret = verify_cert(*client_certificate, *client_certificate_length, &common_name, &common_name_length); if ( ret ) { client_cert_verification_result_code = 0; printf("Failed to validate client certificate against CA\n"); } else { /* Certificate is signed by the trusted CA, now we have to check whether the remote node ip matches certificate ip */ char remote_ip[100]; inet_ntop(AF_INET, remote_addr, remote_ip, 100); //printf("Remote addr: %s\n",remote_ip); if ( strcmp(remote_ip, common_name) != 0 ) { client_cert_verification_result_code = 0; printf("Client certificate is signed by CA, but is issued for a different client. Current client is %s, but the certificate is for %s\n", remote_ip, common_name); } else { client_cert_verification_result_code = 1; } } if ( client_cert_verification_result_code == 1) { ret = 0; } else { ret = -1; } /* Send client certificate verification result */ if ( write_u32(ctx, client_cert_verification_result_code) != 4 ) { printf("Failed to send server certificate length\n"); goto failed; } goto done; failed: ret = -1; done: free(common_name); return ret; };
int main (int argc, char **argv) { int retval; PRFileDesc *in_file; FILE *out_file; /* not PRFileDesc until SECU accepts it */ int crequest, dresponse; int prequest, presponse; int ccert, vcert; const char *db_dir, *date_str, *cert_usage_str, *name; const char *responder_name, *responder_url, *signer_name; PRBool add_acceptable_responses, add_service_locator; SECItem *data = NULL; PLOptState *optstate; SECStatus rv; CERTCertDBHandle *handle = NULL; SECCertUsage cert_usage; PRTime verify_time; CERTCertificate *cert = NULL; PRBool ascii = PR_FALSE; retval = -1; /* what we return/exit with on error */ program_name = PL_strrchr(argv[0], '/'); program_name = program_name ? (program_name + 1) : argv[0]; in_file = PR_STDIN; out_file = stdout; crequest = 0; dresponse = 0; prequest = 0; presponse = 0; ccert = 0; vcert = 0; db_dir = NULL; date_str = NULL; cert_usage_str = NULL; name = NULL; responder_name = NULL; responder_url = NULL; signer_name = NULL; add_acceptable_responses = PR_FALSE; add_service_locator = PR_FALSE; optstate = PL_CreateOptState (argc, argv, "AHLPR:S:V:d:l:pr:s:t:u:w:"); if (optstate == NULL) { SECU_PrintError (program_name, "PL_CreateOptState failed"); return retval; } while (PL_GetNextOpt (optstate) == PL_OPT_OK) { switch (optstate->option) { case '?': short_usage (program_name); return retval; case 'A': add_acceptable_responses = PR_TRUE; break; case 'H': long_usage (program_name); return retval; case 'L': add_service_locator = PR_TRUE; break; case 'P': presponse = 1; break; case 'R': dresponse = 1; name = optstate->value; break; case 'S': ccert = 1; name = optstate->value; break; case 'V': vcert = 1; name = optstate->value; break; case 'a': ascii = PR_TRUE; break; case 'd': db_dir = optstate->value; break; case 'l': responder_url = optstate->value; break; case 'p': prequest = 1; break; case 'r': crequest = 1; name = optstate->value; break; case 's': signer_name = optstate->value; break; case 't': responder_name = optstate->value; break; case 'u': cert_usage_str = optstate->value; break; case 'w': date_str = optstate->value; break; } } PL_DestroyOptState(optstate); if ((crequest + dresponse + prequest + presponse + ccert + vcert) != 1) { PR_fprintf (PR_STDERR, "%s: must specify exactly one command\n\n", program_name); short_usage (program_name); return retval; } if (vcert) { if (cert_usage_str == NULL) { PR_fprintf (PR_STDERR, "%s: verification requires cert usage\n\n", program_name); short_usage (program_name); return retval; } rv = cert_usage_from_char (cert_usage_str, &cert_usage); if (rv != SECSuccess) { PR_fprintf (PR_STDERR, "%s: invalid cert usage (\"%s\")\n\n", program_name, cert_usage_str); long_usage (program_name); return retval; } } if (ccert + vcert) { if (responder_url != NULL || responder_name != NULL) { /* * To do a full status check, both the URL and the cert name * of the responder must be specified if either one is. */ if (responder_url == NULL || responder_name == NULL) { if (responder_url == NULL) PR_fprintf (PR_STDERR, "%s: must also specify responder location\n\n", program_name); else PR_fprintf (PR_STDERR, "%s: must also specify responder name\n\n", program_name); short_usage (program_name); return retval; } } if (date_str != NULL) { rv = DER_AsciiToTime (&verify_time, (char *) date_str); if (rv != SECSuccess) { SECU_PrintError (program_name, "error converting time string"); PR_fprintf (PR_STDERR, "\n"); long_usage (program_name); return retval; } } else { verify_time = PR_Now(); } } retval = -2; /* errors change from usage to runtime */ /* * Initialize the NSPR and Security libraries. */ PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); db_dir = SECU_ConfigDirectory (db_dir); rv = NSS_Init (db_dir); if (rv != SECSuccess) { SECU_PrintError (program_name, "NSS_Init failed"); goto prdone; } SECU_RegisterDynamicOids(); if (prequest + presponse) { MAKE_FILE_BINARY(stdin); data = read_file_into_item (in_file, siBuffer); if (data == NULL) { SECU_PrintError (program_name, "problem reading input"); goto nssdone; } } if (crequest + dresponse + presponse + ccert + vcert) { handle = CERT_GetDefaultCertDB(); if (handle == NULL) { SECU_PrintError (program_name, "problem getting certdb handle"); goto nssdone; } /* * It would be fine to do the enable for all of these commands, * but this way we check that everything but an overall verify * can be done without it. That is, that the individual pieces * work on their own. */ if (vcert) { rv = CERT_EnableOCSPChecking (handle); if (rv != SECSuccess) { SECU_PrintError (program_name, "error enabling OCSP checking"); goto nssdone; } } if ((ccert + vcert) && (responder_name != NULL)) { rv = CERT_SetOCSPDefaultResponder (handle, responder_url, responder_name); if (rv != SECSuccess) { SECU_PrintError (program_name, "error setting default responder"); goto nssdone; } rv = CERT_EnableOCSPDefaultResponder (handle); if (rv != SECSuccess) { SECU_PrintError (program_name, "error enabling default responder"); goto nssdone; } } } #define NOTYET(opt) \ { \ PR_fprintf (PR_STDERR, "%s not yet working\n", opt); \ exit (-1); \ } if (name) { cert = find_certificate(handle, name, ascii); } if (crequest) { if (signer_name != NULL) { NOTYET("-s"); } rv = create_request (out_file, handle, cert, add_service_locator, add_acceptable_responses); } else if (dresponse) { if (signer_name != NULL) { NOTYET("-s"); } rv = dump_response (out_file, handle, cert, responder_url); } else if (prequest) { rv = print_request (out_file, data); } else if (presponse) { rv = print_response (out_file, data, handle); } else if (ccert) { if (signer_name != NULL) { NOTYET("-s"); } rv = get_cert_status (out_file, handle, cert, name, verify_time); } else if (vcert) { if (signer_name != NULL) { NOTYET("-s"); } rv = verify_cert (out_file, handle, cert, name, cert_usage, verify_time); } if (rv != SECSuccess) SECU_PrintError (program_name, "error performing requested operation"); else retval = 0; nssdone: if (cert) { CERT_DestroyCertificate(cert); } if (data != NULL) { SECITEM_FreeItem (data, PR_TRUE); } if (handle != NULL) { CERT_DisableOCSPDefaultResponder(handle); CERT_DisableOCSPChecking (handle); } if (NSS_Shutdown () != SECSuccess) { retval = 1; } prdone: PR_Cleanup (); return retval; }