1 /*
2 Copyright (c) 2011-2020 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_broker_internal.h"
26 #include "memory_mosq.h"
27 #include "mqtt_protocol.h"
28 #include "send_mosq.h"
29 #include "misc_mosq.h"
30 #include "util_mosq.h"
31 
32 static int aclfile__parse(struct mosquitto__security_options *security_opts);
33 static int unpwd__file_parse(struct mosquitto__unpwd **unpwd, const char *password_file);
34 static int acl__cleanup(bool reload);
35 static int unpwd__cleanup(struct mosquitto__unpwd **unpwd, bool reload);
36 static int psk__file_parse(struct mosquitto__unpwd **psk_id, const char *psk_file);
37 #ifdef WITH_TLS
38 static int pw__digest(const char *password, const unsigned char *salt, unsigned int salt_len, unsigned char *hash, unsigned int *hash_len, enum mosquitto_pwhash_type hashtype, int iterations);
39 #endif
40 static int mosquitto_unpwd_check_default(int event, void *event_data, void *userdata);
41 static int mosquitto_acl_check_default(int event, void *event_data, void *userdata);
42 
43 
44 
mosquitto_security_init_default(bool reload)45 int mosquitto_security_init_default(bool reload)
46 {
47 	int rc;
48 	int i;
49 	char *pwf;
50 	char *pskf = NULL;
51 
52 	UNUSED(reload);
53 
54 	/* Configure plugin identifier */
55 	if(db.config->per_listener_settings){
56 		for(i=0; i<db.config->listener_count; i++){
57 			db.config->listeners[i].security_options.pid = mosquitto__calloc(1, sizeof(mosquitto_plugin_id_t));
58 			if(db.config->listeners[i].security_options.pid == NULL){
59 				log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
60 				return MOSQ_ERR_NOMEM;
61 			}
62 			db.config->listeners[i].security_options.pid->listener = &db.config->listeners[i];
63 		}
64 	}else{
65 		db.config->security_options.pid = mosquitto__calloc(1, sizeof(mosquitto_plugin_id_t));
66 		if(db.config->security_options.pid == NULL){
67 			log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
68 			return MOSQ_ERR_NOMEM;
69 		}
70 	}
71 
72 	/* Load username/password data if required. */
73 	if(db.config->per_listener_settings){
74 		for(i=0; i<db.config->listener_count; i++){
75 			pwf = db.config->listeners[i].security_options.password_file;
76 			if(pwf){
77 				rc = unpwd__file_parse(&db.config->listeners[i].security_options.unpwd, pwf);
78 				if(rc){
79 					log__printf(NULL, MOSQ_LOG_ERR, "Error opening password file \"%s\".", pwf);
80 					return rc;
81 				}
82 				mosquitto_callback_register(db.config->listeners[i].security_options.pid,
83 						MOSQ_EVT_BASIC_AUTH, mosquitto_unpwd_check_default, NULL, NULL);
84 			}
85 		}
86 	}else{
87 		if(db.config->security_options.password_file){
88 			pwf = db.config->security_options.password_file;
89 			if(pwf){
90 				rc = unpwd__file_parse(&db.config->security_options.unpwd, pwf);
91 				if(rc){
92 					log__printf(NULL, MOSQ_LOG_ERR, "Error opening password file \"%s\".", pwf);
93 					return rc;
94 				}
95 			}
96 			mosquitto_callback_register(db.config->security_options.pid,
97 					MOSQ_EVT_BASIC_AUTH, mosquitto_unpwd_check_default, NULL, NULL);
98 		}
99 	}
100 
101 	/* Load acl data if required. */
102 	if(db.config->per_listener_settings){
103 		for(i=0; i<db.config->listener_count; i++){
104 			if(db.config->listeners[i].security_options.acl_file){
105 				rc = aclfile__parse(&db.config->listeners[i].security_options);
106 				if(rc){
107 					log__printf(NULL, MOSQ_LOG_ERR, "Error opening acl file \"%s\".", db.config->listeners[i].security_options.acl_file);
108 					return rc;
109 				}
110 				mosquitto_callback_register(db.config->listeners[i].security_options.pid,
111 						MOSQ_EVT_ACL_CHECK, mosquitto_acl_check_default, NULL, NULL);
112 			}
113 		}
114 	}else{
115 		if(db.config->security_options.acl_file){
116 			rc = aclfile__parse(&db.config->security_options);
117 			if(rc){
118 				log__printf(NULL, MOSQ_LOG_ERR, "Error opening acl file \"%s\".", db.config->security_options.acl_file);
119 				return rc;
120 			}
121 			mosquitto_callback_register(db.config->security_options.pid,
122 					MOSQ_EVT_ACL_CHECK, mosquitto_acl_check_default, NULL, NULL);
123 		}
124 	}
125 
126 	/* Load psk data if required. */
127 	if(db.config->per_listener_settings){
128 		for(i=0; i<db.config->listener_count; i++){
129 			pskf = db.config->listeners[i].security_options.psk_file;
130 			if(pskf){
131 				rc = psk__file_parse(&db.config->listeners[i].security_options.psk_id, pskf);
132 				if(rc){
133 					log__printf(NULL, MOSQ_LOG_ERR, "Error opening psk file \"%s\".", pskf);
134 					return rc;
135 				}
136 			}
137 		}
138 	}else{
139 		pskf = db.config->security_options.psk_file;
140 		if(pskf){
141 			rc = psk__file_parse(&db.config->security_options.psk_id, pskf);
142 			if(rc){
143 				log__printf(NULL, MOSQ_LOG_ERR, "Error opening psk file \"%s\".", pskf);
144 				return rc;
145 			}
146 		}
147 	}
148 
149 	return MOSQ_ERR_SUCCESS;
150 }
151 
mosquitto_security_cleanup_default(bool reload)152 int mosquitto_security_cleanup_default(bool reload)
153 {
154 	int rc;
155 	int i;
156 
157 	rc = acl__cleanup(reload);
158 	if(rc != MOSQ_ERR_SUCCESS) return rc;
159 
160 	rc = unpwd__cleanup(&db.config->security_options.unpwd, reload);
161 	if(rc != MOSQ_ERR_SUCCESS) return rc;
162 
163 	for(i=0; i<db.config->listener_count; i++){
164 		if(db.config->listeners[i].security_options.unpwd){
165 			rc = unpwd__cleanup(&db.config->listeners[i].security_options.unpwd, reload);
166 			if(rc != MOSQ_ERR_SUCCESS) return rc;
167 		}
168 	}
169 
170 	rc = unpwd__cleanup(&db.config->security_options.psk_id, reload);
171 	if(rc != MOSQ_ERR_SUCCESS) return rc;
172 
173 	for(i=0; i<db.config->listener_count; i++){
174 		if(db.config->listeners[i].security_options.psk_id){
175 			rc = unpwd__cleanup(&db.config->listeners[i].security_options.psk_id, reload);
176 			if(rc != MOSQ_ERR_SUCCESS) return rc;
177 		}
178 	}
179 
180 	if(db.config->per_listener_settings){
181 		for(i=0; i<db.config->listener_count; i++){
182 			if(db.config->listeners[i].security_options.pid){
183 				mosquitto_callback_unregister(db.config->listeners[i].security_options.pid,
184 						MOSQ_EVT_BASIC_AUTH, mosquitto_unpwd_check_default, NULL);
185 				mosquitto_callback_unregister(db.config->listeners[i].security_options.pid,
186 						MOSQ_EVT_ACL_CHECK, mosquitto_acl_check_default, NULL);
187 
188 				mosquitto__free(db.config->listeners[i].security_options.pid);
189 			}
190 		}
191 	}else{
192 		if(db.config->security_options.pid){
193 			mosquitto_callback_unregister(db.config->security_options.pid,
194 					MOSQ_EVT_BASIC_AUTH, mosquitto_unpwd_check_default, NULL);
195 			mosquitto_callback_unregister(db.config->security_options.pid,
196 					MOSQ_EVT_ACL_CHECK, mosquitto_acl_check_default, NULL);
197 
198 			mosquitto__free(db.config->security_options.pid);
199 		}
200 	}
201 	return MOSQ_ERR_SUCCESS;
202 }
203 
204 
add__acl(struct mosquitto__security_options * security_opts,const char * user,const char * topic,int access)205 static int add__acl(struct mosquitto__security_options *security_opts, const char *user, const char *topic, int access)
206 {
207 	struct mosquitto__acl_user *acl_user=NULL, *user_tail;
208 	struct mosquitto__acl *acl, *acl_tail;
209 	char *local_topic;
210 	bool new_user = false;
211 
212 	if(!security_opts || !topic) return MOSQ_ERR_INVAL;
213 
214 	local_topic = mosquitto__strdup(topic);
215 	if(!local_topic){
216 		return MOSQ_ERR_NOMEM;
217 	}
218 
219 	if(security_opts->acl_list){
220 		user_tail = security_opts->acl_list;
221 		while(user_tail){
222 			if(user == NULL){
223 				if(user_tail->username == NULL){
224 					acl_user = user_tail;
225 					break;
226 				}
227 			}else if(user_tail->username && !strcmp(user_tail->username, user)){
228 				acl_user = user_tail;
229 				break;
230 			}
231 			user_tail = user_tail->next;
232 		}
233 	}
234 	if(!acl_user){
235 		acl_user = mosquitto__malloc(sizeof(struct mosquitto__acl_user));
236 		if(!acl_user){
237 			mosquitto__free(local_topic);
238 			return MOSQ_ERR_NOMEM;
239 		}
240 		new_user = true;
241 		if(user){
242 			acl_user->username = mosquitto__strdup(user);
243 			if(!acl_user->username){
244 				mosquitto__free(local_topic);
245 				mosquitto__free(acl_user);
246 				return MOSQ_ERR_NOMEM;
247 			}
248 		}else{
249 			acl_user->username = NULL;
250 		}
251 		acl_user->next = NULL;
252 		acl_user->acl = NULL;
253 	}
254 
255 	acl = mosquitto__malloc(sizeof(struct mosquitto__acl));
256 	if(!acl){
257 		mosquitto__free(local_topic);
258 		mosquitto__free(acl_user->username);
259 		mosquitto__free(acl_user);
260 		return MOSQ_ERR_NOMEM;
261 	}
262 	acl->access = access;
263 	acl->topic = local_topic;
264 	acl->next = NULL;
265 	acl->ccount = 0;
266 	acl->ucount = 0;
267 
268 	/* Add acl to user acl list */
269 	if(acl_user->acl){
270 		acl_tail = acl_user->acl;
271 		if(access == MOSQ_ACL_NONE){
272 			/* Put "deny" acls at front of the list */
273 			acl->next = acl_tail;
274 			acl_user->acl = acl;
275 		}else{
276 			while(acl_tail->next){
277 				acl_tail = acl_tail->next;
278 			}
279 			acl_tail->next = acl;
280 		}
281 	}else{
282 		acl_user->acl = acl;
283 	}
284 
285 	if(new_user){
286 		/* Add to end of list */
287 		if(security_opts->acl_list){
288 			user_tail = security_opts->acl_list;
289 			while(user_tail->next){
290 				user_tail = user_tail->next;
291 			}
292 			user_tail->next = acl_user;
293 		}else{
294 			security_opts->acl_list = acl_user;
295 		}
296 	}
297 
298 	return MOSQ_ERR_SUCCESS;
299 }
300 
add__acl_pattern(struct mosquitto__security_options * security_opts,const char * topic,int access)301 static int add__acl_pattern(struct mosquitto__security_options *security_opts, const char *topic, int access)
302 {
303 	struct mosquitto__acl *acl, *acl_tail;
304 	char *local_topic;
305 	char *s;
306 
307 	if(!security_opts| !topic) return MOSQ_ERR_INVAL;
308 
309 	local_topic = mosquitto__strdup(topic);
310 	if(!local_topic){
311 		return MOSQ_ERR_NOMEM;
312 	}
313 
314 	acl = mosquitto__malloc(sizeof(struct mosquitto__acl));
315 	if(!acl){
316 		mosquitto__free(local_topic);
317 		return MOSQ_ERR_NOMEM;
318 	}
319 	acl->access = access;
320 	acl->topic = local_topic;
321 	acl->next = NULL;
322 
323 	acl->ccount = 0;
324 	s = local_topic;
325 	while(s){
326 		s = strstr(s, "%c");
327 		if(s){
328 			acl->ccount++;
329 			s+=2;
330 		}
331 	}
332 
333 	acl->ucount = 0;
334 	s = local_topic;
335 	while(s){
336 		s = strstr(s, "%u");
337 		if(s){
338 			acl->ucount++;
339 			s+=2;
340 		}
341 	}
342 
343 	if(acl->ccount == 0 && acl->ucount == 0){
344 		log__printf(NULL, MOSQ_LOG_WARNING,
345 				"Warning: ACL pattern '%s' does not contain '%%c' or '%%u'.",
346 				topic);
347 	}
348 
349 	if(security_opts->acl_patterns){
350 		acl_tail = security_opts->acl_patterns;
351 		if(access == MOSQ_ACL_NONE){
352 			/* Put "deny" acls at front of the list */
353 			acl->next = acl_tail;
354 			security_opts->acl_patterns = acl;
355 		}else{
356 			while(acl_tail->next){
357 				acl_tail = acl_tail->next;
358 			}
359 			acl_tail->next = acl;
360 		}
361 	}else{
362 		security_opts->acl_patterns = acl;
363 	}
364 
365 	return MOSQ_ERR_SUCCESS;
366 }
367 
mosquitto_acl_check_default(int event,void * event_data,void * userdata)368 static int mosquitto_acl_check_default(int event, void *event_data, void *userdata)
369 {
370 	struct mosquitto_evt_acl_check *ed = event_data;
371 	char *local_acl;
372 	struct mosquitto__acl *acl_root;
373 	bool result;
374 	size_t i;
375 	size_t len, tlen, clen, ulen;
376 	char *s;
377 	struct mosquitto__security_options *security_opts = NULL;
378 
379 	UNUSED(event);
380 	UNUSED(userdata);
381 
382 	if(ed->client->bridge) return MOSQ_ERR_SUCCESS;
383 	if(ed->access == MOSQ_ACL_SUBSCRIBE || ed->access == MOSQ_ACL_UNSUBSCRIBE) return MOSQ_ERR_SUCCESS; /* FIXME - implement ACL subscription strings. */
384 
385 	if(db.config->per_listener_settings){
386 		if(!ed->client->listener) return MOSQ_ERR_ACL_DENIED;
387 		security_opts = &ed->client->listener->security_options;
388 	}else{
389 		security_opts = &db.config->security_options;
390 	}
391 	if(!security_opts->acl_file && !security_opts->acl_list && !security_opts->acl_patterns){
392 		return MOSQ_ERR_PLUGIN_DEFER;
393 	}
394 
395 	if(!ed->client->acl_list && !security_opts->acl_patterns) return MOSQ_ERR_ACL_DENIED;
396 
397 	if(ed->client->acl_list){
398 		acl_root = ed->client->acl_list->acl;
399 	}else{
400 		acl_root = NULL;
401 	}
402 
403 	/* Loop through all ACLs for this client. ACL denials are iterated over first. */
404 	while(acl_root){
405 		/* Loop through the topic looking for matches to this ACL. */
406 
407 		/* If subscription starts with $, acl_root->topic must also start with $. */
408 		if(ed->topic[0] == '$' && acl_root->topic[0] != '$'){
409 			acl_root = acl_root->next;
410 			continue;
411 		}
412 		mosquitto_topic_matches_sub(acl_root->topic, ed->topic, &result);
413 		if(result){
414 			if(acl_root->access == MOSQ_ACL_NONE){
415 				/* Access was explicitly denied for this topic. */
416 				return MOSQ_ERR_ACL_DENIED;
417 			}
418 			if(ed->access & acl_root->access){
419 				/* And access is allowed. */
420 				return MOSQ_ERR_SUCCESS;
421 			}
422 		}
423 		acl_root = acl_root->next;
424 	}
425 
426 	acl_root = security_opts->acl_patterns;
427 
428 	if(acl_root){
429 		/* We are using pattern based acls. Check whether the username or
430 		 * client id contains a + or # and if so deny access.
431 		 *
432 		 * Without this, a malicious client may configure its username/client
433 		 * id to bypass ACL checks (or have a username/client id that cannot
434 		 * publish or receive messages to its own place in the hierarchy).
435 		 */
436 		if(ed->client->username && strpbrk(ed->client->username, "+#")){
437 			log__printf(NULL, MOSQ_LOG_NOTICE, "ACL denying access to client with dangerous username \"%s\"", ed->client->username);
438 			return MOSQ_ERR_ACL_DENIED;
439 		}
440 
441 		if(ed->client->id && strpbrk(ed->client->id, "+#")){
442 			log__printf(NULL, MOSQ_LOG_NOTICE, "ACL denying access to client with dangerous client id \"%s\"", ed->client->id);
443 			return MOSQ_ERR_ACL_DENIED;
444 		}
445 	}
446 
447 	/* Loop through all pattern ACLs. ACL denial patterns are iterated over first. */
448 	if(!ed->client->id) return MOSQ_ERR_ACL_DENIED;
449 	clen = strlen(ed->client->id);
450 
451 	while(acl_root){
452 		tlen = strlen(acl_root->topic);
453 
454 		if(acl_root->ucount && !ed->client->username){
455 			acl_root = acl_root->next;
456 			continue;
457 		}
458 
459 		if(ed->client->username){
460 			ulen = strlen(ed->client->username);
461 			len = tlen + (size_t)acl_root->ccount*(clen-2) + (size_t)acl_root->ucount*(ulen-2);
462 		}else{
463 			ulen = 0;
464 			len = tlen + (size_t)acl_root->ccount*(clen-2);
465 		}
466 		local_acl = mosquitto__malloc(len+1);
467 		if(!local_acl) return MOSQ_ERR_NOMEM;
468 		s = local_acl;
469 		for(i=0; i<tlen; i++){
470 			if(i<tlen-1 && acl_root->topic[i] == '%'){
471 				if(acl_root->topic[i+1] == 'c'){
472 					i++;
473 					strncpy(s, ed->client->id, clen);
474 					s+=clen;
475 					continue;
476 				}else if(ed->client->username && acl_root->topic[i+1] == 'u'){
477 					i++;
478 					strncpy(s, ed->client->username, ulen);
479 					s+=ulen;
480 					continue;
481 				}
482 			}
483 			s[0] = acl_root->topic[i];
484 			s++;
485 		}
486 		local_acl[len] = '\0';
487 
488 		mosquitto_topic_matches_sub(local_acl, ed->topic, &result);
489 		mosquitto__free(local_acl);
490 		if(result){
491 			if(acl_root->access == MOSQ_ACL_NONE){
492 				/* Access was explicitly denied for this topic pattern. */
493 				return MOSQ_ERR_ACL_DENIED;
494 			}
495 			if(ed->access & acl_root->access){
496 				/* And access is allowed. */
497 				return MOSQ_ERR_SUCCESS;
498 			}
499 		}
500 
501 		acl_root = acl_root->next;
502 	}
503 
504 	return MOSQ_ERR_ACL_DENIED;
505 }
506 
507 
aclfile__parse(struct mosquitto__security_options * security_opts)508 static int aclfile__parse(struct mosquitto__security_options *security_opts)
509 {
510 	FILE *aclfptr = NULL;
511 	char *token;
512 	char *user = NULL;
513 	char *topic;
514 	char *access_s;
515 	int access;
516 	int rc = MOSQ_ERR_SUCCESS;
517 	size_t slen;
518 	int topic_pattern;
519 	char *saveptr = NULL;
520 	char *buf = NULL;
521 	int buflen = 256;
522 
523 	if(!db.config) return MOSQ_ERR_INVAL;
524 	if(!security_opts) return MOSQ_ERR_INVAL;
525 	if(!security_opts->acl_file) return MOSQ_ERR_SUCCESS;
526 
527 	buf = mosquitto__malloc((size_t)buflen);
528 	if(buf == NULL){
529 		log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
530 		return MOSQ_ERR_NOMEM;
531 	}
532 
533 	aclfptr = mosquitto__fopen(security_opts->acl_file, "rt", false);
534 	if(!aclfptr){
535 		mosquitto__free(buf);
536 		log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open acl_file \"%s\".", security_opts->acl_file);
537 		return MOSQ_ERR_UNKNOWN;
538 	}
539 
540 	/* topic [read|write] <topic>
541 	 * user <user>
542 	 */
543 
544 	while(fgets_extending(&buf, &buflen, aclfptr)){
545 		slen = strlen(buf);
546 		while(slen > 0 && isspace(buf[slen-1])){
547 			buf[slen-1] = '\0';
548 			slen = strlen(buf);
549 		}
550 		if(buf[0] == '#'){
551 			continue;
552 		}
553 		token = strtok_r(buf, " ", &saveptr);
554 		if(token){
555 			if(!strcmp(token, "topic") || !strcmp(token, "pattern")){
556 				if(!strcmp(token, "topic")){
557 					topic_pattern = 0;
558 				}else{
559 					topic_pattern = 1;
560 				}
561 
562 				access_s = strtok_r(NULL, " ", &saveptr);
563 				if(!access_s){
564 					log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty topic in acl_file \"%s\".", security_opts->acl_file);
565 					rc = MOSQ_ERR_INVAL;
566 					break;
567 				}
568 				token = strtok_r(NULL, "", &saveptr);
569 				if(token){
570 					topic = misc__trimblanks(token);
571 				}else{
572 					topic = access_s;
573 					access_s = NULL;
574 				}
575 				if(access_s){
576 					if(!strcmp(access_s, "read")){
577 						access = MOSQ_ACL_READ;
578 					}else if(!strcmp(access_s, "write")){
579 						access = MOSQ_ACL_WRITE;
580 					}else if(!strcmp(access_s, "readwrite")){
581 						access = MOSQ_ACL_READ | MOSQ_ACL_WRITE;
582 					}else if(!strcmp(access_s, "deny")){
583 						access = MOSQ_ACL_NONE;
584 					}else{
585 						log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid topic access type \"%s\" in acl_file \"%s\".", access_s, security_opts->acl_file);
586 						rc = MOSQ_ERR_INVAL;
587 						break;
588 					}
589 				}else{
590 					access = MOSQ_ACL_READ | MOSQ_ACL_WRITE;
591 				}
592 				rc = mosquitto_sub_topic_check(topic);
593 				if(rc != MOSQ_ERR_SUCCESS){
594 					log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid ACL topic \"%s\" in acl_file \"%s\".", topic, security_opts->acl_file);
595 					rc = MOSQ_ERR_INVAL;
596 					break;
597 				}
598 
599 				if(topic_pattern == 0){
600 					rc = add__acl(security_opts, user, topic, access);
601 				}else{
602 					rc = add__acl_pattern(security_opts, topic, access);
603 				}
604 				if(rc){
605 					break;
606 				}
607 			}else if(!strcmp(token, "user")){
608 				token = strtok_r(NULL, "", &saveptr);
609 				if(token){
610 					token = misc__trimblanks(token);
611 					if(slen == 0){
612 						log__printf(NULL, MOSQ_LOG_ERR, "Error: Missing username in acl_file \"%s\".", security_opts->acl_file);
613 						rc = MOSQ_ERR_INVAL;
614 						break;
615 					}
616 					mosquitto__free(user);
617 					user = mosquitto__strdup(token);
618 					if(!user){
619 						rc = MOSQ_ERR_NOMEM;
620 						break;
621 					}
622 				}else{
623 					log__printf(NULL, MOSQ_LOG_ERR, "Error: Missing username in acl_file \"%s\".", security_opts->acl_file);
624 					rc = MOSQ_ERR_INVAL;
625 					break;
626 				}
627 			}else{
628 				log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid line in acl_file \"%s\": %s.", security_opts->acl_file, buf);
629 				rc = MOSQ_ERR_INVAL;
630 				break;
631 			}
632 		}
633 	}
634 
635 	mosquitto__free(buf);
636 	mosquitto__free(user);
637 	fclose(aclfptr);
638 
639 	return rc;
640 }
641 
free__acl(struct mosquitto__acl * acl)642 static void free__acl(struct mosquitto__acl *acl)
643 {
644 	if(!acl) return;
645 
646 	if(acl->next){
647 		free__acl(acl->next);
648 	}
649 	mosquitto__free(acl->topic);
650 	mosquitto__free(acl);
651 }
652 
653 
acl__cleanup_single(struct mosquitto__security_options * security_opts)654 static void acl__cleanup_single(struct mosquitto__security_options *security_opts)
655 {
656 	struct mosquitto__acl_user *user_tail;
657 
658 	while(security_opts->acl_list){
659 		user_tail = security_opts->acl_list->next;
660 
661 		free__acl(security_opts->acl_list->acl);
662 		mosquitto__free(security_opts->acl_list->username);
663 		mosquitto__free(security_opts->acl_list);
664 
665 		security_opts->acl_list = user_tail;
666 	}
667 
668 	if(security_opts->acl_patterns){
669 		free__acl(security_opts->acl_patterns);
670 		security_opts->acl_patterns = NULL;
671 	}
672 }
673 
674 
acl__cleanup(bool reload)675 static int acl__cleanup(bool reload)
676 {
677 	struct mosquitto *context, *ctxt_tmp = NULL;
678 	int i;
679 
680 	UNUSED(reload);
681 
682 	/* As we're freeing ACLs, we must clear context->acl_list to ensure no
683 	 * invalid memory accesses take place later.
684 	 * This *requires* the ACLs to be reapplied after acl__cleanup()
685 	 * is called if we are reloading the config. If this is not done, all
686 	 * access will be denied to currently connected clients.
687 	 */
688 	HASH_ITER(hh_id, db.contexts_by_id, context, ctxt_tmp){
689 		context->acl_list = NULL;
690 	}
691 
692 	if(db.config->per_listener_settings){
693 		for(i=0; i<db.config->listener_count; i++){
694 			acl__cleanup_single(&db.config->listeners[i].security_options);
695 		}
696 	}else{
697 		acl__cleanup_single(&db.config->security_options);
698 	}
699 
700 	return MOSQ_ERR_SUCCESS;
701 }
702 
703 
acl__find_acls(struct mosquitto * context)704 int acl__find_acls(struct mosquitto *context)
705 {
706 	struct mosquitto__acl_user *acl_tail;
707 	struct mosquitto__security_options *security_opts;
708 
709 	/* Associate user with its ACL, assuming we have ACLs loaded. */
710 	if(db.config->per_listener_settings){
711 		if(!context->listener){
712 			return MOSQ_ERR_INVAL;
713 		}
714 		security_opts = &context->listener->security_options;
715 	}else{
716 		security_opts = &db.config->security_options;
717 	}
718 
719 	if(security_opts->acl_list){
720 		acl_tail = security_opts->acl_list;
721 		while(acl_tail){
722 			if(context->username){
723 				if(acl_tail->username && !strcmp(context->username, acl_tail->username)){
724 					context->acl_list = acl_tail;
725 					break;
726 				}
727 			}else{
728 				if(acl_tail->username == NULL){
729 					context->acl_list = acl_tail;
730 					break;
731 				}
732 			}
733 			acl_tail = acl_tail->next;
734 		}
735 	}else{
736 		context->acl_list = NULL;
737 	}
738 
739 	return MOSQ_ERR_SUCCESS;
740 }
741 
742 
pwfile__parse(const char * file,struct mosquitto__unpwd ** root)743 static int pwfile__parse(const char *file, struct mosquitto__unpwd **root)
744 {
745 	FILE *pwfile;
746 	struct mosquitto__unpwd *unpwd;
747 	char *username, *password;
748 	char *saveptr = NULL;
749 	char *buf;
750 	int buflen = 256;
751 
752 	buf = mosquitto__malloc((size_t)buflen);
753 	if(buf == NULL){
754 		log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
755 		return MOSQ_ERR_NOMEM;
756 	}
757 
758 	pwfile = mosquitto__fopen(file, "rt", false);
759 	if(!pwfile){
760 		log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to open pwfile \"%s\".", file);
761 		mosquitto__free(buf);
762 		return MOSQ_ERR_UNKNOWN;
763 	}
764 
765 	while(!feof(pwfile)){
766 		if(fgets_extending(&buf, &buflen, pwfile)){
767 			if(buf[0] == '#') continue;
768 			if(!strchr(buf, ':')) continue;
769 
770 			username = strtok_r(buf, ":", &saveptr);
771 			if(username){
772 				unpwd = mosquitto__calloc(1, sizeof(struct mosquitto__unpwd));
773 				if(!unpwd){
774 					fclose(pwfile);
775 					mosquitto__free(buf);
776 					return MOSQ_ERR_NOMEM;
777 				}
778 				username = misc__trimblanks(username);
779 				if(strlen(username) > 65535){
780 					log__printf(NULL, MOSQ_LOG_NOTICE, "Warning: Invalid line in password file '%s', username too long.", file);
781 					mosquitto__free(unpwd);
782 					continue;
783 				}
784 
785 				unpwd->username = mosquitto__strdup(username);
786 				if(!unpwd->username){
787 					mosquitto__free(unpwd);
788 					mosquitto__free(buf);
789 					fclose(pwfile);
790 					return MOSQ_ERR_NOMEM;
791 				}
792 				password = strtok_r(NULL, ":", &saveptr);
793 				if(password){
794 					password = misc__trimblanks(password);
795 
796 					if(strlen(password) > 65535){
797 						log__printf(NULL, MOSQ_LOG_NOTICE, "Warning: Invalid line in password file '%s', password too long.", file);
798 						mosquitto__free(unpwd->username);
799 						mosquitto__free(unpwd);
800 						continue;
801 					}
802 
803 					unpwd->password = mosquitto__strdup(password);
804 					if(!unpwd->password){
805 						fclose(pwfile);
806 						mosquitto__free(unpwd->username);
807 						mosquitto__free(unpwd);
808 						mosquitto__free(buf);
809 						return MOSQ_ERR_NOMEM;
810 					}
811 
812 					HASH_ADD_KEYPTR(hh, *root, unpwd->username, strlen(unpwd->username), unpwd);
813 				}else{
814 					log__printf(NULL, MOSQ_LOG_NOTICE, "Warning: Invalid line in password file '%s': %s", file, buf);
815 					mosquitto__free(unpwd->username);
816 					mosquitto__free(unpwd);
817 				}
818 			}
819 		}
820 	}
821 	fclose(pwfile);
822 	mosquitto__free(buf);
823 
824 	return MOSQ_ERR_SUCCESS;
825 }
826 
827 
unpwd__free_item(struct mosquitto__unpwd ** unpwd,struct mosquitto__unpwd * item)828 void unpwd__free_item(struct mosquitto__unpwd **unpwd, struct mosquitto__unpwd *item)
829 {
830 	mosquitto__free(item->username);
831 	mosquitto__free(item->password);
832 #ifdef WITH_TLS
833 	mosquitto__free(item->salt);
834 #endif
835 	HASH_DEL(*unpwd, item);
836 	mosquitto__free(item);
837 }
838 
839 
840 #ifdef WITH_TLS
unpwd__decode_passwords(struct mosquitto__unpwd ** unpwd)841 static int unpwd__decode_passwords(struct mosquitto__unpwd **unpwd)
842 {
843 	struct mosquitto__unpwd *u, *tmp = NULL;
844 	char *token;
845 	unsigned char *salt;
846 	unsigned int salt_len;
847 	unsigned char *password;
848 	unsigned int password_len;
849 	int rc;
850 	enum mosquitto_pwhash_type hashtype;
851 
852 	HASH_ITER(hh, *unpwd, u, tmp){
853 		/* Need to decode password into hashed data + salt. */
854 		if(u->password == NULL){
855 			log__printf(NULL, MOSQ_LOG_ERR, "Error: Missing password hash for user %s, removing entry.", u->username);
856 			unpwd__free_item(unpwd, u);
857 			continue;
858 		}
859 
860 		token = strtok(u->password, "$");
861 		if(token == NULL){
862 			log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid password hash for user %s, removing entry.", u->username);
863 			unpwd__free_item(unpwd, u);
864 			continue;
865 		}
866 
867 		if(!strcmp(token, "6")){
868 			hashtype = pw_sha512;
869 		}else if(!strcmp(token, "7")){
870 			hashtype = pw_sha512_pbkdf2;
871 		}else{
872 			log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid password hash type for user %s, removing entry.", u->username);
873 			unpwd__free_item(unpwd, u);
874 			continue;
875 		}
876 
877 		if(hashtype == pw_sha512_pbkdf2){
878 			token = strtok(NULL, "$");
879 			if(token == NULL){
880 				log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid password hash for user %s, removing entry.", u->username);
881 				unpwd__free_item(unpwd, u);
882 				continue;
883 			}
884 			u->iterations = atoi(token);
885 			if(u->iterations < 1){
886 				log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid hash iterations for user %s, removing entry.", u->username);
887 				unpwd__free_item(unpwd, u);
888 				continue;
889 			}
890 		}
891 
892 		token = strtok(NULL, "$");
893 		if(token == NULL){
894 			log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid password hash for user %s, removing entry.", u->username);
895 			unpwd__free_item(unpwd, u);
896 			continue;
897 		}
898 		rc = base64__decode(token, &salt, &salt_len);
899 		if(rc == MOSQ_ERR_SUCCESS && salt_len == 12){
900 			u->salt = salt;
901 			u->salt_len = salt_len;
902 			token = strtok(NULL, "$");
903 			if(token){
904 				rc = base64__decode(token, &password, &password_len);
905 				if(rc == MOSQ_ERR_SUCCESS && password_len == 64){
906 					mosquitto__free(u->password);
907 					u->password = (char *)password;
908 					u->password_len = password_len;
909 					u->hashtype = hashtype;
910 				}else{
911 					log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to decode password for user %s, removing entry.", u->username);
912 					unpwd__free_item(unpwd, u);
913 				}
914 			}else{
915 				log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid password hash for user %s, removing entry.", u->username);
916 				unpwd__free_item(unpwd, u);
917 			}
918 		}else{
919 			log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to decode password salt for user %s, removing entry.", u->username);
920 			unpwd__free_item(unpwd, u);
921 		}
922 	}
923 
924 	return MOSQ_ERR_SUCCESS;
925 }
926 #endif
927 
928 
unpwd__file_parse(struct mosquitto__unpwd ** unpwd,const char * password_file)929 static int unpwd__file_parse(struct mosquitto__unpwd **unpwd, const char *password_file)
930 {
931 	int rc;
932 	if(!unpwd) return MOSQ_ERR_INVAL;
933 
934 	if(!password_file) return MOSQ_ERR_SUCCESS;
935 
936 	rc = pwfile__parse(password_file, unpwd);
937 
938 #ifdef WITH_TLS
939 	if(rc) return rc;
940 	rc = unpwd__decode_passwords(unpwd);
941 #endif
942 
943 	return rc;
944 }
945 
psk__file_parse(struct mosquitto__unpwd ** psk_id,const char * psk_file)946 static int psk__file_parse(struct mosquitto__unpwd **psk_id, const char *psk_file)
947 {
948 	int rc;
949 	struct mosquitto__unpwd *u, *tmp = NULL;
950 
951 	if(!db.config || !psk_id) return MOSQ_ERR_INVAL;
952 
953 	/* We haven't been asked to parse a psk file. */
954 	if(!psk_file) return MOSQ_ERR_SUCCESS;
955 
956 	rc = pwfile__parse(psk_file, psk_id);
957 	if(rc) return rc;
958 
959 	HASH_ITER(hh, (*psk_id), u, tmp){
960 		/* Check for hex only digits */
961 		if(!u->password){
962 			log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty psk for identity \"%s\".", u->username);
963 			return MOSQ_ERR_INVAL;
964 		}
965 		if(strspn(u->password, "0123456789abcdefABCDEF") < strlen(u->password)){
966 			log__printf(NULL, MOSQ_LOG_ERR, "Error: psk for identity \"%s\" contains non-hexadecimal characters.", u->username);
967 			return MOSQ_ERR_INVAL;
968 		}
969 	}
970 	return MOSQ_ERR_SUCCESS;
971 }
972 
973 
974 #ifdef WITH_TLS
mosquitto__memcmp_const(const void * a,const void * b,size_t len)975 static int mosquitto__memcmp_const(const void *a, const void *b, size_t len)
976 {
977 	size_t i;
978 	int rc = 0;
979 
980 	if(!a || !b) return 1;
981 
982 	for(i=0; i<len; i++){
983 		if( ((char *)a)[i] != ((char *)b)[i] ){
984 			rc = 1;
985 		}
986 	}
987 	return rc;
988 }
989 #endif
990 
991 
mosquitto_unpwd_check_default(int event,void * event_data,void * userdata)992 static int mosquitto_unpwd_check_default(int event, void *event_data, void *userdata)
993 {
994 	struct mosquitto_evt_basic_auth *ed = event_data;
995 	struct mosquitto__unpwd *u;
996 	struct mosquitto__unpwd *unpwd_ref;
997 #ifdef WITH_TLS
998 	unsigned char hash[EVP_MAX_MD_SIZE];
999 	unsigned int hash_len;
1000 	int rc;
1001 #endif
1002 
1003 	UNUSED(event);
1004 	UNUSED(userdata);
1005 
1006 	if(ed->client->username == NULL){
1007 		return MOSQ_ERR_PLUGIN_DEFER;
1008 	}
1009 
1010 	if(db.config->per_listener_settings){
1011 		if(ed->client->bridge) return MOSQ_ERR_SUCCESS;
1012 		if(!ed->client->listener) return MOSQ_ERR_INVAL;
1013 		unpwd_ref = ed->client->listener->security_options.unpwd;
1014 	}else{
1015 		unpwd_ref = db.config->security_options.unpwd;
1016 	}
1017 
1018 	HASH_FIND(hh, unpwd_ref, ed->client->username, strlen(ed->client->username), u);
1019 	if(u){
1020 		if(u->password){
1021 			if(ed->client->password){
1022 #ifdef WITH_TLS
1023 				rc = pw__digest(ed->client->password, u->salt, u->salt_len, hash, &hash_len, u->hashtype, u->iterations);
1024 				if(rc == MOSQ_ERR_SUCCESS){
1025 					if(hash_len == u->password_len && !mosquitto__memcmp_const(u->password, hash, hash_len)){
1026 						return MOSQ_ERR_SUCCESS;
1027 					}else{
1028 						return MOSQ_ERR_AUTH;
1029 					}
1030 				}else{
1031 					return rc;
1032 				}
1033 #else
1034 				if(!strcmp(u->password, ed->client->password)){
1035 					return MOSQ_ERR_SUCCESS;
1036 				}
1037 #endif
1038 			}else{
1039 				return MOSQ_ERR_AUTH;
1040 			}
1041 		}else{
1042 			return MOSQ_ERR_SUCCESS;
1043 		}
1044 	}
1045 
1046 	return MOSQ_ERR_AUTH;
1047 }
1048 
unpwd__cleanup(struct mosquitto__unpwd ** root,bool reload)1049 static int unpwd__cleanup(struct mosquitto__unpwd **root, bool reload)
1050 {
1051 	struct mosquitto__unpwd *u, *tmp = NULL;
1052 
1053 	UNUSED(reload);
1054 
1055 	if(!root) return MOSQ_ERR_INVAL;
1056 
1057 	HASH_ITER(hh, *root, u, tmp){
1058 		HASH_DEL(*root, u);
1059 		mosquitto__free(u->password);
1060 		mosquitto__free(u->username);
1061 #ifdef WITH_TLS
1062 		mosquitto__free(u->salt);
1063 #endif
1064 		mosquitto__free(u);
1065 	}
1066 
1067 	*root = NULL;
1068 
1069 	return MOSQ_ERR_SUCCESS;
1070 }
1071 
1072 
1073 #ifdef WITH_TLS
security__disconnect_auth(struct mosquitto * context)1074 static void security__disconnect_auth(struct mosquitto *context)
1075 {
1076 	if(context->protocol == mosq_p_mqtt5){
1077 		send__disconnect(context, MQTT_RC_ADMINISTRATIVE_ACTION, NULL);
1078 	}
1079 	mosquitto__set_state(context, mosq_cs_disconnecting);
1080 	do_disconnect(context, MOSQ_ERR_AUTH);
1081 }
1082 #endif
1083 
1084 /* Apply security settings after a reload.
1085  * Includes:
1086  * - Disconnecting anonymous users if appropriate
1087  * - Disconnecting users with invalid passwords
1088  * - Reapplying ACLs
1089  */
mosquitto_security_apply_default(void)1090 int mosquitto_security_apply_default(void)
1091 {
1092 	struct mosquitto *context, *ctxt_tmp = NULL;
1093 	struct mosquitto__acl_user *acl_user_tail;
1094 	bool allow_anonymous;
1095 	struct mosquitto__security_options *security_opts = NULL;
1096 #ifdef WITH_TLS
1097 	int i;
1098 	X509 *client_cert = NULL;
1099 	X509_NAME *name;
1100 	X509_NAME_ENTRY *name_entry;
1101 	ASN1_STRING *name_asn1 = NULL;
1102 	struct mosquitto__listener *listener;
1103 	BIO *subject_bio;
1104 	char *data_start;
1105 	size_t name_length;
1106 	char *subject;
1107 #endif
1108 
1109 #ifdef WITH_TLS
1110 	for(i=0; i<db.config->listener_count; i++){
1111 		listener = &db.config->listeners[i];
1112 		if(listener && listener->ssl_ctx && listener->certfile && listener->keyfile && listener->crlfile && listener->require_certificate){
1113 			if(net__tls_server_ctx(listener)){
1114 				return MOSQ_ERR_TLS;
1115 			}
1116 
1117 			if(net__tls_load_verify(listener)){
1118 				return MOSQ_ERR_TLS;
1119 			}
1120 		}
1121 	}
1122 #endif
1123 
1124 	HASH_ITER(hh_id, db.contexts_by_id, context, ctxt_tmp){
1125 		if(context->bridge){
1126 			continue;
1127 		}
1128 
1129 		/* Check for anonymous clients when allow_anonymous is false */
1130 		if(db.config->per_listener_settings){
1131 			if(context->listener){
1132 				allow_anonymous = context->listener->security_options.allow_anonymous;
1133 			}else{
1134 				/* Client not currently connected, so defer judgement until it does connect */
1135 				allow_anonymous = true;
1136 			}
1137 		}else{
1138 			allow_anonymous = db.config->security_options.allow_anonymous;
1139 		}
1140 
1141 		if(!allow_anonymous && !context->username){
1142 			mosquitto__set_state(context, mosq_cs_disconnecting);
1143 			do_disconnect(context, MOSQ_ERR_AUTH);
1144 			continue;
1145 		}
1146 
1147 		/* Check for connected clients that are no longer authorised */
1148 #ifdef WITH_TLS
1149 		if(context->listener && context->listener->ssl_ctx && (context->listener->use_identity_as_username || context->listener->use_subject_as_username)){
1150 			/* Client must have either a valid certificate, or valid PSK used as a username. */
1151 			if(!context->ssl){
1152 				if(context->protocol == mosq_p_mqtt5){
1153 					send__disconnect(context, MQTT_RC_ADMINISTRATIVE_ACTION, NULL);
1154 				}
1155 				mosquitto__set_state(context, mosq_cs_disconnecting);
1156 				do_disconnect(context, MOSQ_ERR_AUTH);
1157 				continue;
1158 			}
1159 #ifdef FINAL_WITH_TLS_PSK
1160 			if(context->listener->psk_hint){
1161 				/* Client should have provided an identity to get this far. */
1162 				if(!context->username){
1163 					security__disconnect_auth(context);
1164 					continue;
1165 				}
1166 			}else
1167 #endif /* FINAL_WITH_TLS_PSK */
1168 			{
1169 				/* Free existing credentials and then recover them. */
1170 				mosquitto__free(context->username);
1171 				context->username = NULL;
1172 				mosquitto__free(context->password);
1173 				context->password = NULL;
1174 
1175 				client_cert = SSL_get_peer_certificate(context->ssl);
1176 				if(!client_cert){
1177 					security__disconnect_auth(context);
1178 					continue;
1179 				}
1180 				name = X509_get_subject_name(client_cert);
1181 				if(!name){
1182 					X509_free(client_cert);
1183 					client_cert = NULL;
1184 					security__disconnect_auth(context);
1185 					continue;
1186 				}
1187 				if (context->listener->use_identity_as_username) { /* use_identity_as_username */
1188 					i = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
1189 					if(i == -1){
1190 						X509_free(client_cert);
1191 						client_cert = NULL;
1192 						security__disconnect_auth(context);
1193 						continue;
1194 					}
1195 					name_entry = X509_NAME_get_entry(name, i);
1196 					if(name_entry){
1197 						name_asn1 = X509_NAME_ENTRY_get_data(name_entry);
1198 						if (name_asn1 == NULL) {
1199 							X509_free(client_cert);
1200 							client_cert = NULL;
1201 							security__disconnect_auth(context);
1202 							continue;
1203 						}
1204 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1205 						context->username = mosquitto__strdup((char *) ASN1_STRING_data(name_asn1));
1206 #else
1207 						context->username = mosquitto__strdup((char *) ASN1_STRING_get0_data(name_asn1));
1208 #endif
1209 						if(!context->username){
1210 							X509_free(client_cert);
1211 							client_cert = NULL;
1212 							security__disconnect_auth(context);
1213 							continue;
1214 						}
1215 						/* Make sure there isn't an embedded NUL character in the CN */
1216 						if ((size_t)ASN1_STRING_length(name_asn1) != strlen(context->username)) {
1217 							X509_free(client_cert);
1218 							client_cert = NULL;
1219 							security__disconnect_auth(context);
1220 							continue;
1221 						}
1222 					}
1223 				} else { /* use_subject_as_username */
1224 					subject_bio = BIO_new(BIO_s_mem());
1225 					X509_NAME_print_ex(subject_bio, X509_get_subject_name(client_cert), 0, XN_FLAG_RFC2253);
1226 					data_start = NULL;
1227 					name_length = (size_t)BIO_get_mem_data(subject_bio, &data_start);
1228 					subject = mosquitto__malloc(sizeof(char)*name_length+1);
1229 					if(!subject){
1230 						BIO_free(subject_bio);
1231 						X509_free(client_cert);
1232 						client_cert = NULL;
1233 						security__disconnect_auth(context);
1234 						continue;
1235 					}
1236 					memcpy(subject, data_start, name_length);
1237 					subject[name_length] = '\0';
1238 					BIO_free(subject_bio);
1239 					context->username = subject;
1240 				}
1241 				if(!context->username){
1242 					X509_free(client_cert);
1243 					client_cert = NULL;
1244 					security__disconnect_auth(context);
1245 					continue;
1246 				}
1247 				X509_free(client_cert);
1248 				client_cert = NULL;
1249 			}
1250 		}else
1251 #endif
1252 		{
1253 			/* Username/password check only if the identity/subject check not used */
1254 			if(mosquitto_unpwd_check(context) != MOSQ_ERR_SUCCESS){
1255 				mosquitto__set_state(context, mosq_cs_disconnecting);
1256 				do_disconnect(context, MOSQ_ERR_AUTH);
1257 				continue;
1258 			}
1259 		}
1260 
1261 
1262 		/* Check for ACLs and apply to user. */
1263 		if(db.config->per_listener_settings){
1264 			if(context->listener){
1265 				security_opts = &context->listener->security_options;
1266 			}else{
1267 				if(context->state != mosq_cs_active){
1268 					mosquitto__set_state(context, mosq_cs_disconnecting);
1269 					do_disconnect(context, MOSQ_ERR_AUTH);
1270 					continue;
1271 				}
1272 			}
1273 		}else{
1274 			security_opts = &db.config->security_options;
1275 		}
1276 
1277 		if(security_opts && security_opts->acl_list){
1278 			acl_user_tail = security_opts->acl_list;
1279 			while(acl_user_tail){
1280 				if(acl_user_tail->username){
1281 					if(context->username){
1282 						if(!strcmp(acl_user_tail->username, context->username)){
1283 							context->acl_list = acl_user_tail;
1284 							break;
1285 						}
1286 					}
1287 				}else{
1288 					if(!context->username){
1289 						context->acl_list = acl_user_tail;
1290 						break;
1291 					}
1292 				}
1293 				acl_user_tail = acl_user_tail->next;
1294 			}
1295 		}
1296 	}
1297 	return MOSQ_ERR_SUCCESS;
1298 }
1299 
mosquitto_psk_key_get_default(struct mosquitto * context,const char * hint,const char * identity,char * key,int max_key_len)1300 int mosquitto_psk_key_get_default(struct mosquitto *context, const char *hint, const char *identity, char *key, int max_key_len)
1301 {
1302 	struct mosquitto__unpwd *u, *tmp = NULL;
1303 	struct mosquitto__unpwd *psk_id_ref = NULL;
1304 
1305 	if(!hint || !identity || !key) return MOSQ_ERR_INVAL;
1306 
1307 	if(db.config->per_listener_settings){
1308 		if(!context->listener) return MOSQ_ERR_INVAL;
1309 		psk_id_ref = context->listener->security_options.psk_id;
1310 	}else{
1311 		psk_id_ref = db.config->security_options.psk_id;
1312 	}
1313 	if(!psk_id_ref) return MOSQ_ERR_PLUGIN_DEFER;
1314 
1315 	HASH_ITER(hh, psk_id_ref, u, tmp){
1316 		if(!strcmp(u->username, identity)){
1317 			strncpy(key, u->password, (size_t)max_key_len);
1318 			return MOSQ_ERR_SUCCESS;
1319 		}
1320 	}
1321 
1322 	return MOSQ_ERR_AUTH;
1323 }
1324 
1325 #ifdef WITH_TLS
pw__digest(const char * password,const unsigned char * salt,unsigned int salt_len,unsigned char * hash,unsigned int * hash_len,enum mosquitto_pwhash_type hashtype,int iterations)1326 int pw__digest(const char *password, const unsigned char *salt, unsigned int salt_len, unsigned char *hash, unsigned int *hash_len, enum mosquitto_pwhash_type hashtype, int iterations)
1327 {
1328 	const EVP_MD *digest;
1329 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1330 	EVP_MD_CTX context;
1331 #else
1332 	EVP_MD_CTX *context;
1333 #endif
1334 
1335 	digest = EVP_get_digestbyname("sha512");
1336 	if(!digest){
1337 		/* FIXME fprintf(stderr, "Error: Unable to create openssl digest.\n"); */
1338 		return 1;
1339 	}
1340 
1341 	if(hashtype == pw_sha512){
1342 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1343 		EVP_MD_CTX_init(&context);
1344 		EVP_DigestInit_ex(&context, digest, NULL);
1345 		EVP_DigestUpdate(&context, password, strlen(password));
1346 		EVP_DigestUpdate(&context, salt, salt_len);
1347 		/* hash is assumed to be EVP_MAX_MD_SIZE bytes long. */
1348 		EVP_DigestFinal_ex(&context, hash, hash_len);
1349 		EVP_MD_CTX_cleanup(&context);
1350 #else
1351 		context = EVP_MD_CTX_new();
1352 		EVP_DigestInit_ex(context, digest, NULL);
1353 		EVP_DigestUpdate(context, password, strlen(password));
1354 		EVP_DigestUpdate(context, salt, salt_len);
1355 		/* hash is assumed to be EVP_MAX_MD_SIZE bytes long. */
1356 		EVP_DigestFinal_ex(context, hash, hash_len);
1357 		EVP_MD_CTX_free(context);
1358 #endif
1359 	}else{
1360 		*hash_len = EVP_MAX_MD_SIZE;
1361 		PKCS5_PBKDF2_HMAC(password, (int)strlen(password),
1362 			salt, (int)salt_len, iterations,
1363 			digest, (int)(*hash_len), hash);
1364 	}
1365 
1366 	return MOSQ_ERR_SUCCESS;
1367 }
1368 
1369 #endif
1370