xref: /freebsd-src/contrib/wpa/src/utils/ext_password_file.c (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
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