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