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