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 "ext_password_i.h" 13 14 15 /** 16 * Data structure for the file-backed password backend. 17 */ 18 struct ext_password_file_data { 19 char *path; /* path of the password file */ 20 }; 21 22 23 /** 24 * ext_password_file_init - Initialize file-backed password backend 25 * @params: Parameters passed by the user. 26 * Returns: Pointer to the initialized backend. 27 * 28 * This function initializes a new file-backed password backend. The user is 29 * expected to initialize this backend with the parameters being the path of 30 * the file that contains the passwords. 31 */ ext_password_file_init(const char * params)32 static void * ext_password_file_init(const char *params) 33 { 34 struct ext_password_file_data *data; 35 36 if (!params) { 37 wpa_printf(MSG_ERROR, "EXT PW FILE: no path given"); 38 return NULL; 39 } 40 41 data = os_zalloc(sizeof(*data)); 42 if (!data) 43 return NULL; 44 45 data->path = os_strdup(params); 46 if (!data->path) { 47 os_free(data); 48 return NULL; 49 } 50 51 return data; 52 } 53 54 55 /** 56 * ext_password_file_deinit - Deinitialize file-backed password backend 57 * @ctx: The file-backed password backend 58 * 59 * This function frees all data associated with the file-backed password 60 * backend. 61 */ ext_password_file_deinit(void * ctx)62 static void ext_password_file_deinit(void *ctx) 63 { 64 struct ext_password_file_data *data = ctx; 65 66 str_clear_free(data->path); 67 os_free(data); 68 } 69 70 /** 71 * ext_password_file_get - Retrieve password from the file-backed password backend 72 * @ctx: The file-backed password backend 73 * @name: Name of the password to retrieve 74 * Returns: Buffer containing the password if one was found or %NULL. 75 * 76 * This function tries to find a password identified by name in the password 77 * file. The password is expected to be stored in `NAME=PASSWORD` format. 78 * Comments and empty lines in the file are ignored. Invalid lines will cause 79 * an error message, but will not cause the function to fail. 80 */ ext_password_file_get(void * ctx,const char * name)81 static struct wpabuf * ext_password_file_get(void *ctx, const char *name) 82 { 83 struct ext_password_file_data *data = ctx; 84 struct wpabuf *password = NULL; 85 char buf[512], *pos; 86 size_t name_len; 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 name_len = os_strlen(name); 99 100 wpa_printf(MSG_DEBUG, "EXT PW FILE: get(%s)", name); 101 102 while ((pos = fgets(buf, sizeof(buf), f))) { 103 char *sep; 104 105 line++; 106 107 /* Strip newline characters */ 108 pos[strcspn(pos, "\r\n")] = 0; 109 110 /* Skip comments and empty lines */ 111 if (*pos == '#' || *pos == '\0') 112 continue; 113 114 sep = os_strchr(pos, '='); 115 if (!sep) { 116 wpa_printf(MSG_ERROR, "Invalid password line %d.", 117 line); 118 continue; 119 } 120 121 if (!sep[1]) { 122 wpa_printf(MSG_ERROR, "No password for line %d.", line); 123 continue; 124 125 } 126 127 if (name_len != (size_t) (sep - pos) || 128 os_strncmp(name, pos, sep - pos) != 0) 129 continue; 130 131 password = wpabuf_alloc_copy(sep + 1, os_strlen(sep + 1)); 132 goto done; 133 } 134 135 wpa_printf(MSG_ERROR, "Password for '%s' was not found.", name); 136 137 done: 138 forced_memzero(buf, sizeof(buf)); 139 fclose(f); 140 return password; 141 } 142 143 144 const struct ext_password_backend ext_password_file = { 145 .name = "file", 146 .init = ext_password_file_init, 147 .deinit = ext_password_file_deinit, 148 .get = ext_password_file_get, 149 }; 150