📄 tls_openssl.c
字号:
free(conn->subject_match); free(conn->altsubject_match); free(conn);}int tls_connection_established(void *ssl_ctx, struct tls_connection *conn){ return conn ? SSL_is_init_finished(conn->ssl) : 0;}int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn){ if (conn == NULL) return -1; /* Shutdown previous TLS connection without notifying the peer * because the connection was already terminated in practice * and "close notify" shutdown alert would confuse AS. */ SSL_set_quiet_shutdown(conn->ssl, 1); SSL_shutdown(conn->ssl); return 0;}static int tls_match_altsubject(X509 *cert, const char *match){ GENERAL_NAME *gen; char *field, *tmp; void *ext; int i, found = 0; size_t len; ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { gen = sk_GENERAL_NAME_value(ext, i); switch (gen->type) { case GEN_EMAIL: field = "EMAIL"; break; case GEN_DNS: field = "DNS"; break; case GEN_URI: field = "URI"; break; default: field = NULL; wpa_printf(MSG_DEBUG, "TLS: altSubjectName: " "unsupported type=%d", gen->type); break; } if (!field) continue; wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s", field, gen->d.ia5->data); len = strlen(field) + 1 + strlen(gen->d.ia5->data) + 1; tmp = malloc(len); if (tmp == NULL) continue; snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data); if (strstr(tmp, match)) found++; free(tmp); } return found;}static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx){ char buf[256]; X509 *err_cert; int err, depth; SSL *ssl; struct tls_connection *conn; char *match, *altmatch; err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); err = X509_STORE_CTX_get_error(x509_ctx); depth = X509_STORE_CTX_get_error_depth(x509_ctx); ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); conn = SSL_get_app_data(ssl); match = conn ? conn->subject_match : NULL; altmatch = conn ? conn->altsubject_match : NULL; if (!preverify_ok) { wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," " error %d (%s) depth %d for '%s'", err, X509_verify_cert_error_string(err), depth, buf); } else { wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - " "preverify_ok=%d err=%d (%s) depth=%d buf='%s'", preverify_ok, err, X509_verify_cert_error_string(err), depth, buf); if (depth == 0 && match && strstr(buf, match) == NULL) { wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " "match with '%s'", buf, match); preverify_ok = 0; } else if (depth == 0 && altmatch && !tls_match_altsubject(err_cert, altmatch)) { wpa_printf(MSG_WARNING, "TLS: altSubjectName match " "'%s' not found", altmatch); preverify_ok = 0; } } return preverify_ok;}int tls_connection_ca_cert(void *ssl_ctx, struct tls_connection *conn, const char *ca_cert){ if (conn == NULL) return -1; if (ca_cert) { if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1) { wpa_printf(MSG_WARNING, "TLS: Failed to load root " "certificates: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } else { wpa_printf(MSG_DEBUG, "TLS: Trusted root " "certificate(s) loaded"); tls_get_errors(ssl_ctx); } SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); } else { /* No ca_cert configured - do not try to verify server * certificate */ SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); } return 0;}int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert){ SSL_CTX *ssl_ctx = _ssl_ctx; if (ca_cert) { if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1) { wpa_printf(MSG_WARNING, "TLS: Failed to load root " "certificates: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } else { wpa_printf(MSG_DEBUG, "TLS: Trusted root " "certificate(s) loaded"); } } return 0;}int tls_global_set_verify(void *ssl_ctx, int check_crl){ int flags; if (check_crl) { X509_STORE *cs = SSL_CTX_get_cert_store(ssl_ctx); if (cs == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to get certificate " "store when enabling check_crl: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } flags = X509_V_FLAG_CRL_CHECK; if (check_crl == 2) flags |= X509_V_FLAG_CRL_CHECK_ALL; X509_STORE_set_flags(cs, flags); } return 0;}int tls_connection_set_subject_match(void *ssl_ctx, struct tls_connection *conn, const char *subject_match, const char *altsubject_match){ if (conn == NULL) return -1; free(conn->subject_match); conn->subject_match = NULL; if (subject_match) { conn->subject_match = strdup(subject_match); if (conn->subject_match == NULL) return -1; } free(conn->altsubject_match); conn->altsubject_match = NULL; if (altsubject_match) { conn->altsubject_match = strdup(altsubject_match); if (conn->altsubject_match == NULL) return -1; } return 0;}int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, int verify_peer){ if (conn == NULL) return -1; if (verify_peer) { SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); } else { SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); } SSL_set_accept_state(conn->ssl); return 0;}int tls_connection_client_cert(void *ssl_ctx, struct tls_connection *conn, const char *client_cert){ if (client_cert == NULL) return 0; if (conn == NULL) return -1; if (SSL_use_certificate_file(conn->ssl, client_cert, SSL_FILETYPE_ASN1) != 1 && SSL_use_certificate_file(conn->ssl, client_cert, SSL_FILETYPE_PEM) != 1) { wpa_printf(MSG_INFO, "TLS: Failed to load client " "certificate: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } return 0;}int tls_global_client_cert(void *_ssl_ctx, const char *client_cert){ SSL_CTX *ssl_ctx = _ssl_ctx; if (client_cert == NULL) return 0; if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert, SSL_FILETYPE_ASN1) != 1 && SSL_CTX_use_certificate_file(ssl_ctx, client_cert, SSL_FILETYPE_PEM) != 1) { wpa_printf(MSG_INFO, "TLS: Failed to load client " "certificate: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } return 0;}static int tls_passwd_cb(char *buf, int size, int rwflag, void *password){ if (password == NULL) { return 0; } strncpy(buf, (char *) password, size); buf[size - 1] = '\0'; return strlen(buf);}static int tls_read_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, const char *private_key, const char *passwd){#ifdef PKCS12_FUNCS FILE *f; PKCS12 *p12; EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *certs; int res = 0; char buf[256]; f = fopen(private_key, "r"); if (f == NULL) return -1; p12 = d2i_PKCS12_fp(f, NULL); if (p12 == NULL) { wpa_printf(MSG_DEBUG, "TLS: Failed to read PKCS12 file '%s'", private_key); fclose(f); return -1; } fclose(f); pkey = NULL; cert = NULL; certs = NULL; if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) { wpa_printf(MSG_DEBUG, "TLS: Failed to parse PKCS12 file '%s': " "%s", private_key, ERR_error_string(ERR_get_error(), NULL)); return -1; } wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 file '%s'", private_key); if (cert) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: " "subject='%s'", buf); if (ssl) { if (SSL_use_certificate(ssl, cert) != 1) res = -1; } else { if (SSL_CTX_use_certificate(ssl_ctx, cert) != 1) res = -1; } X509_free(cert); } if (pkey) { wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12"); if (ssl) { if (SSL_use_PrivateKey(ssl, pkey) != 1) res = -1; } else { if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) res = -1; } EVP_PKEY_free(pkey); } if (certs) { while ((cert = sk_X509_pop(certs)) != NULL) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "TLS: additional certificate" " from PKCS12: subject='%s'", buf); /* * There is no SSL equivalent for the chain cert - so * always add it to the context... */ if (SSL_CTX_add_extra_chain_cert(ssl_ctx, cert) != 1) { res = -1; break; } } sk_X509_free(certs); } PKCS12_free(p12); if (res < 0) tls_get_errors(ssl_ctx); return res;#else /* PKCS12_FUNCS */ wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read " "p12/pfx files"); return -1;#endif /* PKCS12_FUNCS */}int tls_connection_engine_private_key(void *_ssl_ctx, struct tls_connection *conn){#ifndef OPENSSL_NO_ENGINE if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) { char *error = ERR_error_string(ERR_get_error(), NULL); wpa_printf(MSG_ERROR, "ENGINE: can't use private key for TLS " "[%s]", error); return -1; } if (!SSL_check_private_key(conn->ssl)) { wpa_printf(MSG_INFO, "SSL: Private key failed verification: " "%s", ERR_error_string(ERR_get_error(), NULL)); return -1; } return 0;#else /* OPENSSL_NO_ENGINE */ wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but " "engine support was not compiled in"); return -1;#endif /* OPENSSL_NO_ENGINE */}int tls_connection_private_key(void *_ssl_ctx, struct tls_connection *conn, const char *private_key, const char *private_key_passwd){ SSL_CTX *ssl_ctx = _ssl_ctx; char *passwd; if (private_key == NULL) return 0; if (conn == NULL) return -1; if (private_key_passwd) { passwd = strdup(private_key_passwd); if (passwd == NULL) return -1; } else passwd = NULL; SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd); if (SSL_use_PrivateKey_file(conn->ssl, private_key, SSL_FILETYPE_ASN1) != 1 && SSL_use_PrivateKey_file(conn->ssl, private_key, SSL_FILETYPE_PEM) != 1 && tls_read_pkcs12(ssl_ctx, conn->ssl, private_key, passwd)) { wpa_printf(MSG_INFO, "SSL: Failed to load private key: %s", ERR_error_string(ERR_get_error(), NULL)); free(passwd); ERR_clear_error(); return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -