diff --git a/src/utils/ext_password.c b/src/utils/ext_password.c index 5615bd72a..cbf92de8c 100644 --- a/src/utils/ext_password.c +++ b/src/utils/ext_password.c @@ -20,6 +20,9 @@ static const struct ext_password_backend *backends[] = { #ifdef CONFIG_EXT_PASSWORD_TEST &ext_password_test, #endif /* CONFIG_EXT_PASSWORD_TEST */ +#ifdef CONFIG_EXT_PASSWORD_FILE + &ext_password_file, +#endif /* CONFIG_EXT_PASSWORD_FILE */ NULL }; diff --git a/src/utils/ext_password_file.c b/src/utils/ext_password_file.c new file mode 100644 index 000000000..4bb0095f3 --- /dev/null +++ b/src/utils/ext_password_file.c @@ -0,0 +1,136 @@ +/* + * External backend for file-backed passwords + * Copyright (c) 2021, Patrick Steinhardt + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "utils/common.h" +#include "utils/config.h" +#include "ext_password_i.h" + + +/** + * Data structure for the file-backed password backend. + */ +struct ext_password_file_data { + char *path; /* path of the password file */ +}; + + +/** + * ext_password_file_init - Initialize file-backed password backend + * @params: Parameters passed by the user. + * Returns: Pointer to the initialized backend. + * + * This function initializes a new file-backed password backend. The user is + * expected to initialize this backend with the parameters being the path of + * the file that contains the passwords. + */ +static void * ext_password_file_init(const char *params) +{ + struct ext_password_file_data *data; + + if (!params) { + wpa_printf(MSG_ERROR, "EXT PW FILE: no path given"); + return NULL; + } + + data = os_zalloc(sizeof(*data)); + if (!data) + return NULL; + + data->path = os_strdup(params); + if (!data->path) { + os_free(data); + return NULL; + } + + return data; +} + + +/** + * ext_password_file_deinit - Deinitialize file-backed password backend + * @ctx: The file-backed password backend + * + * This function frees all data associated with the file-backed password + * backend. + */ +static void ext_password_file_deinit(void *ctx) +{ + struct ext_password_file_data *data = ctx; + + str_clear_free(data->path); + os_free(data); +} + +/** + * ext_password_file_get - Retrieve password from the file-backed password backend + * @ctx: The file-backed password backend + * @name: Name of the password to retrieve + * Returns: Buffer containing the password if one was found or %NULL. + * + * This function tries to find a password identified by name in the password + * file. The password is expected to be stored in `NAME=PASSWORD` format. + * Comments and empty lines in the file are ignored. Invalid lines will cause + * an error message, but will not cause the function to fail. + */ +static struct wpabuf * ext_password_file_get(void *ctx, const char *name) +{ + struct ext_password_file_data *data = ctx; + struct wpabuf *password = NULL; + char buf[512], *pos; + int line = 0; + FILE *f; + + f = fopen(data->path, "r"); + if (!f) { + wpa_printf(MSG_ERROR, + "EXT PW FILE: could not open file '%s': %s", + data->path, strerror(errno)); + return NULL; + } + + wpa_printf(MSG_DEBUG, "EXT PW FILE: get(%s)", name); + + while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { + char *sep = os_strchr(pos, '='); + + if (!sep) { + wpa_printf(MSG_ERROR, "Invalid password line %d.", + line); + continue; + } + + if (!sep[1]) { + wpa_printf(MSG_ERROR, "No password for line %d.", line); + continue; + + } + + if (os_strncmp(name, pos, sep - pos) != 0) + continue; + + password = wpabuf_alloc_copy(sep + 1, os_strlen(sep + 1)); + goto done; + } + + wpa_printf(MSG_ERROR, "Password for '%s' was not found.", name); + +done: + forced_memzero(buf, sizeof(buf)); + fclose(f); + return password; +} + + +const struct ext_password_backend ext_password_file = { + .name = "file", + .init = ext_password_file_init, + .deinit = ext_password_file_deinit, + .get = ext_password_file_get, +}; diff --git a/src/utils/ext_password_i.h b/src/utils/ext_password_i.h index 948eaf542..872ccd195 100644 --- a/src/utils/ext_password_i.h +++ b/src/utils/ext_password_i.h @@ -26,4 +26,8 @@ struct wpabuf * ext_password_alloc(size_t len); extern const struct ext_password_backend ext_password_test; #endif /* CONFIG_EXT_PASSWORD_TEST */ +#ifdef CONFIG_EXT_PASSWORD_FILE +extern const struct ext_password_backend ext_password_file; +#endif /* CONFIG_EXT_PASSWORD_FILE */ + #endif /* EXT_PASSWORD_I_H */ diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index 5b551d4df..fd74c1640 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -1617,6 +1617,12 @@ L_CFLAGS += -DCONFIG_EXT_PASSWORD_TEST NEED_EXT_PASSWORD=y endif +ifdef CONFIG_EXT_PASSWORD_FILE +OBJS += src/utils/ext_password_file.c +L_CFLAGS += -DCONFIG_EXT_PASSWORD_FILE +NEED_EXT_PASSWORD=y +endif + ifdef NEED_EXT_PASSWORD OBJS += src/utils/ext_password.c L_CFLAGS += -DCONFIG_EXT_PASSWORD diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 5e9a696f6..bc3aa1d1c 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1751,6 +1751,12 @@ CFLAGS += -DCONFIG_EXT_PASSWORD_TEST NEED_EXT_PASSWORD=y endif +ifdef CONFIG_EXT_PASSWORD_FILE +OBJS += ../src/utils/ext_password_file.o +CFLAGS += -DCONFIG_EXT_PASSWORD_FILE +NEED_EXT_PASSWORD=y +endif + ifdef NEED_EXT_PASSWORD OBJS += ../src/utils/ext_password.o CFLAGS += -DCONFIG_EXT_PASSWORD diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index aaf64280f..708a82385 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -530,6 +530,8 @@ CONFIG_WIFI_DISPLAY=y # # External password backend for testing purposes (developer use) #CONFIG_EXT_PASSWORD_TEST=y +# File-based backend to read passwords from an external file. +#CONFIG_EXT_PASSWORD_FILE=y # Enable Fast Session Transfer (FST) #CONFIG_FST=y diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 9d5de8591..77f363e00 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -366,7 +366,14 @@ fast_reauth=1 # Password (and passphrase, etc.) backend for external storage # format: [:] +# Test backend which stores passwords in memory. Should only be used for +# development purposes. #ext_password_backend=test:pw1=password|pw2=testing +# File-based backend which reads passwords from a file. The parameter +# identifies the file to read passwords from. The password file follows the +# format of wpa_supplicant.conf and accepts simple `key=passphrase` formatted +# passwords. +#ext_password_backend=file:/path/to/passwords.conf # Disable P2P functionality