📄 tls_gnutls.c
字号:
/* TODO: gnutls_certificate_set_verify_flags(xcred, flags); * to force peer validation(?) */ if (params->ca_cert) { conn->verify_peer = 1; ret = gnutls_certificate_set_x509_trust_file( conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " "in PEM format: %s", params->ca_cert, gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_trust_file( conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert " "'%s' in DER format: %s", params->ca_cert, gnutls_strerror(ret)); } } } if (params->client_cert && params->private_key) { /* TODO: private_key_passwd? */ ret = gnutls_certificate_set_x509_key_file( conn->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client cert/key " "in PEM format: %s", gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_key_file( conn->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client " "cert/key in DER format: %s", gnutls_strerror(ret)); return ret; } } } ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred); if (ret < 0) { wpa_printf(MSG_INFO, "Failed to configure credentials: %s", gnutls_strerror(ret)); } return ret;}int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert){ /* TODO */ return -1;}int tls_global_set_verify(void *ssl_ctx, int check_crl){ /* TODO */ return -1;}int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, int verify_peer){ if (conn == NULL) return -1; /* TODO */ return 1;}int tls_global_client_cert(void *_ssl_ctx, const char *client_cert){ /* TODO */ return -1;}int tls_global_private_key(void *_ssl_ctx, const char *private_key, const char *private_key_passwd){ /* TODO */ return -1;}int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, struct tls_keys *keys){ security_parameters_st *sec; if (conn == NULL || conn->session == NULL || keys == NULL) return -1; memset(keys, 0, sizeof(*keys)); sec = &conn->session->security_parameters; keys->master_key = sec->master_secret; keys->master_key_len = TLS_MASTER_SIZE; keys->client_random = sec->client_random; keys->client_random_len = TLS_RANDOM_SIZE; keys->server_random = sec->server_random; keys->server_random_len = TLS_RANDOM_SIZE; return 0;}static int tls_connection_verify_peer(struct tls_connection *conn){ unsigned int status, num_certs, i; time_t now; const gnutls_datum_t *certs; gnutls_x509_crt_t cert; if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) { wpa_printf(MSG_INFO, "TLS: Failed to verify peer " "certificate chain"); return -1; } if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); return -1; } if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " "known issuer"); return -1; } if (status & GNUTLS_CERT_REVOKED) { wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); return -1; } now = time(NULL); certs = gnutls_certificate_get_peers(conn->session, &num_certs); if (certs == NULL) { wpa_printf(MSG_INFO, "TLS: No peer certificate chain " "received"); return -1; } for (i = 0; i < num_certs; i++) { char *buf; size_t len; if (gnutls_x509_crt_init(&cert) < 0) { wpa_printf(MSG_INFO, "TLS: Certificate initialization " "failed"); return -1; } if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) { wpa_printf(MSG_INFO, "TLS: Could not parse peer " "certificate %d/%d", i + 1, num_certs); gnutls_x509_crt_deinit(cert); return -1; } gnutls_x509_crt_get_dn(cert, NULL, &len); len++; buf = malloc(len + 1); if (buf) { buf[0] = buf[len] = '\0'; gnutls_x509_crt_get_dn(cert, buf, &len); } wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", i + 1, num_certs, buf); if (i == 0) { /* TODO: validate subject_match and altsubject_match */ } free(buf); if (gnutls_x509_crt_get_expiration_time(cert) < now || gnutls_x509_crt_get_activation_time(cert) > now) { wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " "not valid at this time", i + 1, num_certs); gnutls_x509_crt_deinit(cert); return -1; } gnutls_x509_crt_deinit(cert); } return 0;}u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, size_t *out_len){ u8 *out_data; int ret; if (in_data && in_len) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in " "pull_buf", __func__, conn->pull_buf_len); free(conn->pull_buf); } conn->pull_buf = malloc(in_len); if (conn->pull_buf == NULL) return NULL; memcpy(conn->pull_buf, in_data, in_len); conn->pull_buf_offset = conn->pull_buf; conn->pull_buf_len = in_len; } ret = gnutls_handshake(conn->session); if (ret < 0) { switch (ret) { case GNUTLS_E_AGAIN: break; case GNUTLS_E_FATAL_ALERT_RECEIVED: wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", __func__, gnutls_alert_get_name( gnutls_alert_get(conn->session))); conn->read_alerts++; /* continue */ default: wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " "-> %s", __func__, gnutls_strerror(ret)); conn->failed++; } } else { wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully"); if (conn->verify_peer && tls_connection_verify_peer(conn)) { wpa_printf(MSG_INFO, "TLS: Peer certificate chain " "failed validation"); conn->failed++; return NULL; } conn->established = 1; if (conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = malloc(1); } } out_data = conn->push_buf; *out_len = conn->push_buf_len; conn->push_buf = NULL; conn->push_buf_len = 0; return out_data;}u8 * tls_connection_server_handshake(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, size_t *out_len){ /* TODO */ return NULL;}int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len){ ssize_t res; res = gnutls_record_send(conn->session, in_data, in_len); if (conn->push_buf == NULL) return -1; if (conn->push_buf_len < out_len) out_len = conn->push_buf_len; memcpy(out_data, conn->push_buf, out_len); free(conn->push_buf); conn->push_buf = NULL; conn->push_buf_len = 0; return out_len;}int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len){ ssize_t res; if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in " "pull_buf", __func__, conn->pull_buf_len); free(conn->pull_buf); } conn->pull_buf = malloc(in_len); if (conn->pull_buf == NULL) return -1; memcpy(conn->pull_buf, in_data, in_len); conn->pull_buf_offset = conn->pull_buf; conn->pull_buf_len = in_len; res = gnutls_record_recv(conn->session, out_data, out_len); if (res < 0) { wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " "(%s)", __func__, res, gnutls_strerror(res)); } return res;}int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn){ if (conn == NULL) return 0; return gnutls_session_is_resumed(conn->session);}#ifdef EAP_FASTint tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn, const u8 *key, size_t key_len){ /* TODO */ return -1;}#endif /* EAP_FAST */int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn){ /* TODO: set ADH-AES128-SHA cipher */ return -1;}int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen){ /* TODO */ buf[0] = '\0'; return 0;}int tls_connection_enable_workaround(void *ssl_ctx, struct tls_connection *conn){ /* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */ return 0;}#ifdef EAP_FASTint tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len){ /* TODO */ return -1;}#endif /* EAP_FAST */int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn){ if (conn == NULL) return -1; return conn->failed;}int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn){ if (conn == NULL) return -1; return conn->read_alerts;}int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn){ if (conn == NULL) return -1; return conn->write_alerts;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -