eapol_test: Add option for writing server certificate chain to a file
eapol_test command line argument -o<file> can now be used to request the received server certificate chain to be written to the specified file. The certificates will be written in PEM format. [Bug 391]
This commit is contained in:
parent
8a55f56453
commit
1b414f59fc
7 changed files with 60 additions and 9 deletions
|
@ -72,6 +72,7 @@ struct tls_config {
|
||||||
const char *pkcs11_engine_path;
|
const char *pkcs11_engine_path;
|
||||||
const char *pkcs11_module_path;
|
const char *pkcs11_module_path;
|
||||||
int fips_mode;
|
int fips_mode;
|
||||||
|
int cert_in_cb;
|
||||||
|
|
||||||
void (*event_cb)(void *ctx, enum tls_event ev,
|
void (*event_cb)(void *ctx, enum tls_event ev,
|
||||||
union tls_event_data *data);
|
union tls_event_data *data);
|
||||||
|
|
|
@ -59,6 +59,7 @@ struct tls_global {
|
||||||
void (*event_cb)(void *ctx, enum tls_event ev,
|
void (*event_cb)(void *ctx, enum tls_event ev,
|
||||||
union tls_event_data *data);
|
union tls_event_data *data);
|
||||||
void *cb_ctx;
|
void *cb_ctx;
|
||||||
|
int cert_in_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tls_global *tls_global = NULL;
|
static struct tls_global *tls_global = NULL;
|
||||||
|
@ -694,6 +695,7 @@ void * tls_init(const struct tls_config *conf)
|
||||||
if (conf) {
|
if (conf) {
|
||||||
tls_global->event_cb = conf->event_cb;
|
tls_global->event_cb = conf->event_cb;
|
||||||
tls_global->cb_ctx = conf->cb_ctx;
|
tls_global->cb_ctx = conf->cb_ctx;
|
||||||
|
tls_global->cert_in_cb = conf->cert_in_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_FIPS
|
#ifdef CONFIG_FIPS
|
||||||
|
@ -1144,7 +1146,7 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
os_memset(&ev, 0, sizeof(ev));
|
os_memset(&ev, 0, sizeof(ev));
|
||||||
if (conn->cert_probe) {
|
if (conn->cert_probe || tls_global->cert_in_cb) {
|
||||||
cert = get_x509_cert(err_cert);
|
cert = get_x509_cert(err_cert);
|
||||||
ev.peer_cert.cert = cert;
|
ev.peer_cert.cert = cert;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1242,6 +1242,7 @@ struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
|
||||||
#endif /* CONFIG_FIPS */
|
#endif /* CONFIG_FIPS */
|
||||||
tlsconf.event_cb = eap_peer_sm_tls_event;
|
tlsconf.event_cb = eap_peer_sm_tls_event;
|
||||||
tlsconf.cb_ctx = sm;
|
tlsconf.cb_ctx = sm;
|
||||||
|
tlsconf.cert_in_cb = conf->cert_in_cb;
|
||||||
sm->ssl_ctx = tls_init(&tlsconf);
|
sm->ssl_ctx = tls_init(&tlsconf);
|
||||||
if (sm->ssl_ctx == NULL) {
|
if (sm->ssl_ctx == NULL) {
|
||||||
wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
|
wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
|
||||||
|
|
|
@ -262,6 +262,11 @@ struct eap_config {
|
||||||
* This is only used by EAP-WSC and can be left %NULL if not available.
|
* This is only used by EAP-WSC and can be left %NULL if not available.
|
||||||
*/
|
*/
|
||||||
struct wps_context *wps;
|
struct wps_context *wps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cert_in_cb - Include server certificates in callback
|
||||||
|
*/
|
||||||
|
int cert_in_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
|
struct eap_sm * eap_peer_sm_init(void *eapol_ctx,
|
||||||
|
|
|
@ -1883,6 +1883,7 @@ struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
|
||||||
conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
|
conf.pkcs11_engine_path = ctx->pkcs11_engine_path;
|
||||||
conf.pkcs11_module_path = ctx->pkcs11_module_path;
|
conf.pkcs11_module_path = ctx->pkcs11_module_path;
|
||||||
conf.wps = ctx->wps;
|
conf.wps = ctx->wps;
|
||||||
|
conf.cert_in_cb = ctx->cert_in_cb;
|
||||||
|
|
||||||
sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
|
sm->eap = eap_peer_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx, &conf);
|
||||||
if (sm->eap == NULL) {
|
if (sm->eap == NULL) {
|
||||||
|
|
|
@ -231,6 +231,11 @@ struct eapol_ctx {
|
||||||
*/
|
*/
|
||||||
void (*cert_cb)(void *ctx, int depth, const char *subject,
|
void (*cert_cb)(void *ctx, int depth, const char *subject,
|
||||||
const char *cert_hash, const struct wpabuf *cert);
|
const char *cert_hash, const struct wpabuf *cert);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cert_in_cb - Include server certificates in callback
|
||||||
|
*/
|
||||||
|
int cert_in_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "eap_peer/eap.h"
|
#include "eap_peer/eap.h"
|
||||||
#include "eap_server/eap_methods.h"
|
#include "eap_server/eap_methods.h"
|
||||||
#include "eloop.h"
|
#include "eloop.h"
|
||||||
|
#include "utils/base64.h"
|
||||||
#include "rsn_supp/wpa.h"
|
#include "rsn_supp/wpa.h"
|
||||||
#include "eap_peer/eap_i.h"
|
#include "eap_peer/eap_i.h"
|
||||||
#include "wpa_supplicant_i.h"
|
#include "wpa_supplicant_i.h"
|
||||||
|
@ -76,6 +77,8 @@ struct eapol_test_data {
|
||||||
char *connect_info;
|
char *connect_info;
|
||||||
u8 own_addr[ETH_ALEN];
|
u8 own_addr[ETH_ALEN];
|
||||||
struct extra_radius_attr *extra_attrs;
|
struct extra_radius_attr *extra_attrs;
|
||||||
|
|
||||||
|
FILE *server_cert_file;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct eapol_test_data eapol_test;
|
static struct eapol_test_data eapol_test;
|
||||||
|
@ -292,7 +295,6 @@ static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e,
|
||||||
static int eapol_test_eapol_send(void *ctx, int type, const u8 *buf,
|
static int eapol_test_eapol_send(void *ctx, int type, const u8 *buf,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
/* struct wpa_supplicant *wpa_s = ctx; */
|
|
||||||
printf("WPA: eapol_test_eapol_send(type=%d len=%lu)\n",
|
printf("WPA: eapol_test_eapol_send(type=%d len=%lu)\n",
|
||||||
type, (unsigned long) len);
|
type, (unsigned long) len);
|
||||||
if (type == IEEE802_1X_TYPE_EAP_PACKET) {
|
if (type == IEEE802_1X_TYPE_EAP_PACKET) {
|
||||||
|
@ -306,16 +308,16 @@ static int eapol_test_eapol_send(void *ctx, int type, const u8 *buf,
|
||||||
static void eapol_test_set_config_blob(void *ctx,
|
static void eapol_test_set_config_blob(void *ctx,
|
||||||
struct wpa_config_blob *blob)
|
struct wpa_config_blob *blob)
|
||||||
{
|
{
|
||||||
struct wpa_supplicant *wpa_s = ctx;
|
struct eapol_test_data *e = ctx;
|
||||||
wpa_config_set_blob(wpa_s->conf, blob);
|
wpa_config_set_blob(e->wpa_s->conf, blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct wpa_config_blob *
|
static const struct wpa_config_blob *
|
||||||
eapol_test_get_config_blob(void *ctx, const char *name)
|
eapol_test_get_config_blob(void *ctx, const char *name)
|
||||||
{
|
{
|
||||||
struct wpa_supplicant *wpa_s = ctx;
|
struct eapol_test_data *e = ctx;
|
||||||
return wpa_config_get_blob(wpa_s->conf, name);
|
return wpa_config_get_blob(e->wpa_s->conf, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -384,6 +386,20 @@ static void eapol_sm_cb(struct eapol_sm *eapol, int success, void *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void eapol_test_write_cert(FILE *f, const char *subject,
|
||||||
|
const struct wpabuf *cert)
|
||||||
|
{
|
||||||
|
unsigned char *encoded;
|
||||||
|
|
||||||
|
encoded = base64_encode(wpabuf_head(cert), wpabuf_len(cert), NULL);
|
||||||
|
if (encoded == NULL)
|
||||||
|
return;
|
||||||
|
fprintf(f, "%s\n-----BEGIN CERTIFICATE-----\n%s"
|
||||||
|
"-----END CERTIFICATE-----\n\n", subject, encoded);
|
||||||
|
os_free(encoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void eapol_test_cert_cb(void *ctx, int depth, const char *subject,
|
static void eapol_test_cert_cb(void *ctx, int depth, const char *subject,
|
||||||
const char *cert_hash,
|
const char *cert_hash,
|
||||||
const struct wpabuf *cert)
|
const struct wpabuf *cert)
|
||||||
|
@ -409,6 +425,10 @@ static void eapol_test_cert_cb(void *ctx, int depth, const char *subject,
|
||||||
depth, subject, cert_hex);
|
depth, subject, cert_hex);
|
||||||
os_free(cert_hex);
|
os_free(cert_hex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e->server_cert_file)
|
||||||
|
eapol_test_write_cert(e->server_cert_file,
|
||||||
|
subject, cert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +444,7 @@ static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
|
||||||
printf("Failed to allocate EAPOL context.\n");
|
printf("Failed to allocate EAPOL context.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ctx->ctx = wpa_s;
|
ctx->ctx = e;
|
||||||
ctx->msg_ctx = wpa_s;
|
ctx->msg_ctx = wpa_s;
|
||||||
ctx->scard_ctx = wpa_s->scard;
|
ctx->scard_ctx = wpa_s->scard;
|
||||||
ctx->cb = eapol_sm_cb;
|
ctx->cb = eapol_sm_cb;
|
||||||
|
@ -439,6 +459,7 @@ static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
|
||||||
ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
|
ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
|
||||||
ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
|
ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
|
||||||
ctx->cert_cb = eapol_test_cert_cb;
|
ctx->cert_cb = eapol_test_cert_cb;
|
||||||
|
ctx->cert_in_cb = 1;
|
||||||
|
|
||||||
wpa_s->eapol = eapol_sm_init(ctx);
|
wpa_s->eapol = eapol_sm_init(ctx);
|
||||||
if (wpa_s->eapol == NULL) {
|
if (wpa_s->eapol == NULL) {
|
||||||
|
@ -995,7 +1016,7 @@ static void usage(void)
|
||||||
"eapol_test [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] "
|
"eapol_test [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] "
|
||||||
"[-s<AS secret>]\\\n"
|
"[-s<AS secret>]\\\n"
|
||||||
" [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
|
" [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
|
||||||
" [-M<client MAC address>] \\\n"
|
" [-M<client MAC address>] [-o<server cert file] \\\n"
|
||||||
" [-N<attr spec>] \\\n"
|
" [-N<attr spec>] \\\n"
|
||||||
" [-A<client IP>]\n"
|
" [-A<client IP>]\n"
|
||||||
"eapol_test scard\n"
|
"eapol_test scard\n"
|
||||||
|
@ -1021,6 +1042,8 @@ static void usage(void)
|
||||||
" -M<client MAC address> = Set own MAC address "
|
" -M<client MAC address> = Set own MAC address "
|
||||||
"(Calling-Station-Id,\n"
|
"(Calling-Station-Id,\n"
|
||||||
" default: 02:00:00:00:00:01)\n"
|
" default: 02:00:00:00:00:01)\n"
|
||||||
|
" -o<server cert file> = Write received server certificate\n"
|
||||||
|
" chain to the specified file\n"
|
||||||
" -N<attr spec> = send arbitrary attribute specified by:\n"
|
" -N<attr spec> = send arbitrary attribute specified by:\n"
|
||||||
" attr_id:syntax:value or attr_id\n"
|
" attr_id:syntax:value or attr_id\n"
|
||||||
" attr_id - number id of the attribute\n"
|
" attr_id - number id of the attribute\n"
|
||||||
|
@ -1062,7 +1085,7 @@ int main(int argc, char *argv[])
|
||||||
wpa_debug_show_keys = 1;
|
wpa_debug_show_keys = 1;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
c = getopt(argc, argv, "a:A:c:C:M:nN:p:r:s:St:W");
|
c = getopt(argc, argv, "a:A:c:C:M:nN:o:p:r:s:St:W");
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
break;
|
break;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
@ -1087,6 +1110,16 @@ int main(int argc, char *argv[])
|
||||||
case 'n':
|
case 'n':
|
||||||
eapol_test.no_mppe_keys++;
|
eapol_test.no_mppe_keys++;
|
||||||
break;
|
break;
|
||||||
|
case 'o':
|
||||||
|
if (eapol_test.server_cert_file)
|
||||||
|
fclose(eapol_test.server_cert_file);
|
||||||
|
eapol_test.server_cert_file = fopen(optarg, "w");
|
||||||
|
if (eapol_test.server_cert_file == NULL) {
|
||||||
|
printf("Could not open '%s' for writing\n",
|
||||||
|
optarg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
as_port = atoi(optarg);
|
as_port = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -1229,6 +1262,9 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
eloop_destroy();
|
eloop_destroy();
|
||||||
|
|
||||||
|
if (eapol_test.server_cert_file)
|
||||||
|
fclose(eapol_test.server_cert_file);
|
||||||
|
|
||||||
printf("MPPE keys OK: %d mismatch: %d\n",
|
printf("MPPE keys OK: %d mismatch: %d\n",
|
||||||
eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch);
|
eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch);
|
||||||
if (eapol_test.num_mppe_mismatch)
|
if (eapol_test.num_mppe_mismatch)
|
||||||
|
|
Loading…
Reference in a new issue