1 /* 2 * External backend for file-backed passwords 3 * Copyright (c) 2021, Patrick Steinhardt <ps@pks.im> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "utils/common.h" 12 #include "utils/config.h" 13 #include "ext_password_i.h" 14 15 16 /** 17 * Data structure for the file-backed password backend. 18 */ 19 struct ext_password_file_data { 20 char *path; /* path of the password file */ 21 }; 22 23 24 /** 25 * ext_password_file_init - Initialize file-backed password backend 26 * @params: Parameters passed by the user. 27 * Returns: Pointer to the initialized backend. 28 * 29 * This function initializes a new file-backed password backend. The user is 30 * expected to initialize this backend with the parameters being the path of 31 * the file that contains the passwords. 32 */ 33 static void * ext_password_file_init(const char *params) 34 { 35 struct ext_password_file_data *data; 36 37 if (!params) { 38 wpa_printf(MSG_ERROR, "EXT PW FILE: no path given"); 39 return NULL; 40 } 41 42 data = os_zalloc(sizeof(*data)); 43 if (!data) 44 return NULL; 45 46 data->path = os_strdup(params); 47 if (!data->path) { 48 os_free(data); 49 return NULL; 50 } 51 52 return data; 53 } 54 55 56 /** 57 * ext_password_file_deinit - Deinitialize file-backed password backend 58 * @ctx: The file-backed password backend 59 * 60 * This function frees all data associated with the file-backed password 61 * backend. 62 */ 63 static void ext_password_file_deinit(void *ctx) 64 { 65 struct ext_password_file_data *data = ctx; 66 67 str_clear_free(data->path); 68 os_free(data); 69 } 70 71 /** 72 * ext_password_file_get - Retrieve password from the file-backed password backend 73 * @ctx: The file-backed password backend 74 * @name: Name of the password to retrieve 75 * Returns: Buffer containing the password if one was found or %NULL. 76 * 77 * This function tries to find a password identified by name in the password 78 * file. The password is expected to be stored in `NAME=PASSWORD` format. 79 * Comments and empty lines in the file are ignored. Invalid lines will cause 80 * an error message, but will not cause the function to fail. 81 */ 82 static struct wpabuf * ext_password_file_get(void *ctx, const char *name) 83 { 84 struct ext_password_file_data *data = ctx; 85 struct wpabuf *password = NULL; 86 char buf[512], *pos; 87 int line = 0; 88 FILE *f; 89 90 f = fopen(data->path, "r"); 91 if (!f) { 92 wpa_printf(MSG_ERROR, 93 "EXT PW FILE: could not open file '%s': %s", 94 data->path, strerror(errno)); 95 return NULL; 96 } 97 98 wpa_printf(MSG_DEBUG, "EXT PW FILE: get(%s)", name); 99 100 while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { 101 char *sep = os_strchr(pos, '='); 102 103 if (!sep) { 104 wpa_printf(MSG_ERROR, "Invalid password line %d.", 105 line); 106 continue; 107 } 108 109 if (!sep[1]) { 110 wpa_printf(MSG_ERROR, "No password for line %d.", line); 111 continue; 112 113 } 114 115 if (os_strncmp(name, pos, sep - pos) != 0) 116 continue; 117 118 password = wpabuf_alloc_copy(sep + 1, os_strlen(sep + 1)); 119 goto done; 120 } 121 122 wpa_printf(MSG_ERROR, "Password for '%s' was not found.", name); 123 124 done: 125 forced_memzero(buf, sizeof(buf)); 126 fclose(f); 127 return password; 128 } 129 130 131 const struct ext_password_backend ext_password_file = { 132 .name = "file", 133 .init = ext_password_file_init, 134 .deinit = ext_password_file_deinit, 135 .get = ext_password_file_get, 136 }; 137