-/*
- * Verify a certificate.
- * Most of the work (signatures and issuer attributes checking)
- * is done by ssl; we check the CN in the peer certificate
- * against the peer name.
- */
-int ssl_verify_callback(int ok, X509_STORE_CTX * ctx)
-{
- char subject[256];
- char cn_str[256];
- X509 *peer_cert;
- int err, depth;
- SSL *ssl;
- struct eaptls_session *ets;
- char *ptr1 = NULL, *ptr2 = NULL;
-
- peer_cert = X509_STORE_CTX_get_current_cert(ctx);
- err = X509_STORE_CTX_get_error(ctx);
- depth = X509_STORE_CTX_get_error_depth(ctx);
-
- dbglog("certificate verify depth: %d", depth);
-
- if (auth_required && !ok) {
- X509_NAME_oneline(X509_get_subject_name(peer_cert),
- subject, 256);
-
- X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
- NID_commonName, cn_str, 256);
-
- dbglog("Certificate verification error:\n depth: %d CN: %s"
- "\n err: %d (%s)\n", depth, cn_str, err,
- X509_verify_cert_error_string(err));
-
- return 0;
- }
-
- ssl = X509_STORE_CTX_get_ex_data(ctx,
- SSL_get_ex_data_X509_STORE_CTX_idx());
-
- ets = (struct eaptls_session *)SSL_get_ex_data(ssl, 0);
-
- if (ets == NULL) {
- error("Error: SSL_get_ex_data returned NULL");
- return 0;
- }
-
- log_ssl_errors();
-
- if (!depth)
- {
- /* Verify certificate based on certificate type and extended key usage */
- if (tls_verify_key_usage) {
- int purpose = ets->client ? X509_PURPOSE_SSL_SERVER : X509_PURPOSE_SSL_CLIENT ;
- if (X509_check_purpose(peer_cert, purpose, 0) == 0) {
- error("Certificate verification error: nsCertType mismatch");
- return 0;
- }
-
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
- int flags = ets->client ? XKU_SSL_SERVER : XKU_SSL_CLIENT;
- if (!(X509_get_extended_key_usage(peer_cert) & flags)) {
- error("Certificate verification error: invalid extended key usage");
- return 0;
- }
-#endif
- info("Certificate key usage: OK");
- }
-
- /*
- * If acting as client and the name of the server wasn't specified
- * explicitely, we can't verify the server authenticity
- */
- if (!tls_verify_method)
- tls_verify_method = TLS_VERIFY_NONE;
-
- if (!ets->peer[0] || !strcmp(TLS_VERIFY_NONE, tls_verify_method)) {
- warn("Certificate verication disabled or no peer name was specified");
- return ok;
- }
-
- /* This is the peer certificate */
- X509_NAME_oneline(X509_get_subject_name(peer_cert),
- subject, 256);
-
- X509_NAME_get_text_by_NID(X509_get_subject_name(peer_cert),
- NID_commonName, cn_str, 256);
-
- /* Verify based on subject name */
- ptr1 = ets->peer;
- if (!strcmp(TLS_VERIFY_SUBJECT, tls_verify_method)) {
- ptr2 = subject;
- }
-
- /* Verify based on common name (default) */
- if (strlen(tls_verify_method) == 0 ||
- !strcmp(TLS_VERIFY_NAME, tls_verify_method)) {
- ptr2 = cn_str;
- }
-
- /* Match the suffix of common name */
- if (!strcmp(TLS_VERIFY_SUFFIX, tls_verify_method)) {
- int len = strlen(ptr1);
- int off = strlen(cn_str) - len;
- ptr2 = cn_str;
- if (off > 0) {
- ptr2 = cn_str + off;
- }
- }
-
- if (strcmp(ptr1, ptr2)) {
- error("Certificate verification error: CN (%s) != %s", ptr1, ptr2);
- return 0;
- }
-
- info("Certificate CN: %s, peer name %s", cn_str, ets->peer);
-
- /*
- * If a peer certificate file was specified, here we check it
- */
- if (ets->peercertfile[0]) {
- if (ssl_cmp_certs(&ets->peercertfile[0], peer_cert)
- != 0) {
- error
- ("Peer certificate doesn't match stored certificate");
- return 0;
- }
- }
- }
-
- return ok;
-}
-
-/*
- * Compare a certificate with the one stored in a file
- */
-int ssl_cmp_certs(char *filename, X509 * a)
-{
- X509 *b;
- int ret;
-
- if (!(b = get_X509_from_file(filename)))
- return 1;
-
- ret = X509_cmp(a, b);
- X509_free(b);
-
- return ret;
-
-}
-
-X509 *get_X509_from_file(char *filename)
-{
- FILE *fp;
- X509 *ret;
-
- if (!(fp = fopen(filename, "r")))
- return NULL;
-
- ret = PEM_read_X509(fp, NULL, NULL, NULL);
-
- fclose(fp);
-
- return ret;
-}
-