/src/mosquitto/plugins/password-file/password_parse.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Copyright (c) 2011-2021 Roger Light <roger@atchoo.org> |
3 | | |
4 | | All rights reserved. This program and the accompanying materials |
5 | | are made available under the terms of the Eclipse Public License 2.0 |
6 | | and Eclipse Distribution License v1.0 which accompany this distribution. |
7 | | |
8 | | The Eclipse Public License is available at |
9 | | https://www.eclipse.org/legal/epl-2.0/ |
10 | | and the Eclipse Distribution License is available at |
11 | | http://www.eclipse.org/org/documents/edl-v10.php. |
12 | | |
13 | | SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
14 | | |
15 | | Contributors: |
16 | | Roger Light - initial implementation and documentation. |
17 | | */ |
18 | | |
19 | | #include "config.h" |
20 | | |
21 | | #include <ctype.h> |
22 | | #include <stdio.h> |
23 | | #include <string.h> |
24 | | |
25 | | #include "mosquitto.h" |
26 | | #include "password_file.h" |
27 | | |
28 | | int password_file__parse(struct password_file_data *data) |
29 | 890 | { |
30 | 890 | FILE *pwfile; |
31 | 890 | struct mosquitto__unpwd *unpwd; |
32 | 890 | char *username, *password; |
33 | 890 | char *saveptr = NULL; |
34 | 890 | char *buf; |
35 | 890 | int buflen = 256; |
36 | | |
37 | 890 | buf = mosquitto_malloc((size_t)buflen); |
38 | 890 | if(buf == NULL){ |
39 | 0 | mosquitto_log_printf(MOSQ_LOG_ERR, "Error: Out of memory."); |
40 | 0 | return MOSQ_ERR_NOMEM; |
41 | 0 | } |
42 | | |
43 | 890 | pwfile = mosquitto_fopen(data->password_file, "rt", true); |
44 | 890 | if(!pwfile){ |
45 | 0 | mosquitto_log_printf(MOSQ_LOG_ERR, "password-file: Error: Unable to open pwfile \"%s\".", data->password_file); |
46 | 0 | mosquitto_FREE(buf); |
47 | 0 | return MOSQ_ERR_UNKNOWN; |
48 | 0 | } |
49 | | |
50 | 8.27k | while(!feof(pwfile)){ |
51 | 8.02k | if(mosquitto_fgets(&buf, &buflen, pwfile)){ |
52 | 7.20k | if(buf[0] == '#') continue; |
53 | 7.00k | if(!strchr(buf, ':')) continue; |
54 | | |
55 | 5.45k | username = strtok_r(buf, ":", &saveptr); |
56 | 5.45k | if(username){ |
57 | 5.45k | username = mosquitto_trimblanks(username); |
58 | 5.45k | if(strlen(username) > 65535){ |
59 | 4 | mosquitto_log_printf(MOSQ_LOG_ERR, "password-file: Error: Invalid line in password file '%s', username too long.", data->password_file); |
60 | 4 | fclose(pwfile); |
61 | 4 | mosquitto_FREE(buf); |
62 | 4 | return MOSQ_ERR_INVAL; |
63 | 4 | } |
64 | 5.45k | if(strlen(username) <= 0){ |
65 | 10 | mosquitto_log_printf(MOSQ_LOG_ERR, "password-file: Error: Empty username in password file '%s'.", data->password_file); |
66 | 10 | fclose(pwfile); |
67 | 10 | mosquitto_FREE(buf); |
68 | 10 | return MOSQ_ERR_INVAL; |
69 | 10 | } |
70 | | |
71 | 5.44k | HASH_FIND(hh, data->unpwd, username, strlen(username), unpwd); |
72 | 5.44k | if(unpwd){ |
73 | 14 | mosquitto_log_printf(MOSQ_LOG_ERR, "password-file: Error: Duplicate user '%s' in password file '%s'.", username, data->password_file); |
74 | 14 | fclose(pwfile); |
75 | 14 | mosquitto_FREE(buf); |
76 | 14 | return MOSQ_ERR_INVAL; |
77 | 14 | } |
78 | | |
79 | 5.42k | unpwd = mosquitto_calloc(1, sizeof(struct mosquitto__unpwd)); |
80 | 5.42k | if(!unpwd){ |
81 | 0 | fclose(pwfile); |
82 | 0 | mosquitto_FREE(buf); |
83 | 0 | return MOSQ_ERR_NOMEM; |
84 | 0 | } |
85 | | |
86 | 5.42k | unpwd->username = mosquitto_strdup(username); |
87 | 5.42k | if(!unpwd->username){ |
88 | 0 | mosquitto_FREE(unpwd); |
89 | 0 | mosquitto_FREE(buf); |
90 | 0 | fclose(pwfile); |
91 | 0 | return MOSQ_ERR_NOMEM; |
92 | 0 | } |
93 | 5.42k | password = strtok_r(NULL, ":", &saveptr); |
94 | 5.42k | if(password){ |
95 | 5.31k | password = mosquitto_trimblanks(password); |
96 | | |
97 | 5.31k | if(strlen(password) > 65535){ |
98 | 8 | mosquitto_log_printf(MOSQ_LOG_ERR, "password-file: Error: Invalid line in password file '%s', password too long.", data->password_file); |
99 | 8 | mosquitto_FREE(unpwd->username); |
100 | 8 | mosquitto_FREE(unpwd); |
101 | 8 | mosquitto_FREE(buf); |
102 | 8 | fclose(pwfile); |
103 | 8 | return MOSQ_ERR_INVAL; |
104 | 8 | } |
105 | | |
106 | 5.31k | if(mosquitto_pw_new(&unpwd->pw, MOSQ_PW_DEFAULT) |
107 | 5.31k | || mosquitto_pw_decode(unpwd->pw, password)){ |
108 | | |
109 | 498 | mosquitto_log_printf(MOSQ_LOG_ERR, "password-file: Error: Unable to decode line in password file '%s'.", data->password_file); |
110 | 498 | mosquitto_pw_cleanup(unpwd->pw); |
111 | 498 | mosquitto_FREE(unpwd->username); |
112 | 498 | mosquitto_FREE(unpwd); |
113 | 498 | mosquitto_FREE(buf); |
114 | 498 | fclose(pwfile); |
115 | 498 | return MOSQ_ERR_INVAL; |
116 | 498 | } |
117 | | |
118 | 4.81k | HASH_ADD_KEYPTR(hh, data->unpwd, unpwd->username, strlen(unpwd->username), unpwd); |
119 | 4.81k | }else{ |
120 | 110 | mosquitto_log_printf(MOSQ_LOG_ERR, "password-file: Error: Invalid line in password file '%s': %s", data->password_file, buf); |
121 | 110 | mosquitto_pw_cleanup(unpwd->pw); |
122 | 110 | mosquitto_FREE(unpwd->username); |
123 | 110 | mosquitto_FREE(unpwd); |
124 | 110 | mosquitto_FREE(buf); |
125 | 110 | fclose(pwfile); |
126 | 110 | return MOSQ_ERR_INVAL; |
127 | 110 | } |
128 | 5.42k | } |
129 | 5.45k | } |
130 | 8.02k | } |
131 | 246 | fclose(pwfile); |
132 | 246 | mosquitto_FREE(buf); |
133 | | |
134 | 246 | return MOSQ_ERR_SUCCESS; |
135 | 890 | } |
136 | | |
137 | | |
138 | | void password_file__cleanup(struct password_file_data *data) |
139 | 2.94k | { |
140 | 2.94k | struct mosquitto__unpwd *u, *tmp = NULL; |
141 | | |
142 | 2.94k | if(!data) return; |
143 | | |
144 | 4.81k | HASH_ITER(hh, data->unpwd, u, tmp){ |
145 | 4.81k | HASH_DEL(data->unpwd, u); |
146 | 4.81k | mosquitto_pw_cleanup(u->pw); |
147 | 4.81k | mosquitto_FREE(u->username); |
148 | 4.81k | mosquitto_FREE(u); |
149 | 4.81k | } |
150 | 2.94k | } |
151 | | |
152 | | |
153 | | int password_file__reload(int event, void *event_data, void *userdata) |
154 | 0 | { |
155 | 0 | struct password_file_data *data = userdata; |
156 | |
|
157 | 0 | UNUSED(event); |
158 | 0 | UNUSED(event_data); |
159 | |
|
160 | 0 | password_file__cleanup(data); |
161 | 0 | return password_file__parse(data); |
162 | 0 | } |