1 /*
2 Copyright (c) 2009-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 <stdio.h>
22 #include <string.h>
23 #include <utlist.h>
24 
25 #include "mosquitto_broker_internal.h"
26 #include "mqtt_protocol.h"
27 #include "memory_mosq.h"
28 #include "packet_mosq.h"
29 #include "property_mosq.h"
30 #include "send_mosq.h"
31 #include "sys_tree.h"
32 #include "time_mosq.h"
33 #include "tls_mosq.h"
34 #include "util_mosq.h"
35 #include "will_mosq.h"
36 
37 #ifdef WITH_WEBSOCKETS
38 #  include <libwebsockets.h>
39 #endif
40 
41 
nibble_to_hex(uint8_t value)42 static char nibble_to_hex(uint8_t value)
43 {
44 	if(value < 0x0A){
45 		return (char)('0'+value);
46 	}else{
47 		return (char)(65 /*'A'*/ +value-10);
48 	}
49 }
50 
client_id_gen(uint16_t * idlen,const char * auto_id_prefix,uint16_t auto_id_prefix_len)51 static char *client_id_gen(uint16_t *idlen, const char *auto_id_prefix, uint16_t auto_id_prefix_len)
52 {
53 	char *client_id;
54 	uint8_t rnd[16];
55 	int i;
56 	int pos;
57 
58 	if(util__random_bytes(rnd, 16)) return NULL;
59 
60 	*idlen = (uint16_t)(auto_id_prefix_len + 36);
61 
62 	client_id = (char *)mosquitto__calloc((size_t)(*idlen) + 1, sizeof(char));
63 	if(!client_id){
64 		return NULL;
65 	}
66 	if(auto_id_prefix){
67 		memcpy(client_id, auto_id_prefix, auto_id_prefix_len);
68 	}
69 
70 	pos = 0;
71 	for(i=0; i<16; i++){
72 		client_id[auto_id_prefix_len + pos + 0] = nibble_to_hex(rnd[i] & 0x0F);
73 		client_id[auto_id_prefix_len + pos + 1] = nibble_to_hex((rnd[i] >> 4) & 0x0F);
74 		pos += 2;
75 		if(pos == 8 || pos == 13 || pos == 18 || pos == 23){
76 			client_id[auto_id_prefix_len + pos] = '-';
77 			pos++;
78 		}
79 	}
80 
81 	return client_id;
82 }
83 
84 /* Remove any queued messages that are no longer allowed through ACL,
85  * assuming a possible change of username. */
connection_check_acl(struct mosquitto * context,struct mosquitto_client_msg ** head)86 static void connection_check_acl(struct mosquitto *context, struct mosquitto_client_msg **head)
87 {
88 	struct mosquitto_client_msg *msg_tail, *tmp;
89 	int access;
90 
91 	DL_FOREACH_SAFE((*head), msg_tail, tmp){
92 		if(msg_tail->direction == mosq_md_out){
93 			access = MOSQ_ACL_READ;
94 		}else{
95 			access = MOSQ_ACL_WRITE;
96 		}
97 		if(mosquitto_acl_check(context, msg_tail->store->topic,
98 							   msg_tail->store->payloadlen, msg_tail->store->payload,
99 							   msg_tail->store->qos, msg_tail->store->retain, access) != MOSQ_ERR_SUCCESS){
100 
101 			DL_DELETE((*head), msg_tail);
102 			db__msg_store_ref_dec(&msg_tail->store);
103 			mosquitto_property_free_all(&msg_tail->properties);
104 			mosquitto__free(msg_tail);
105 		}
106 	}
107 }
108 
connect__on_authorised(struct mosquitto * context,void * auth_data_out,uint16_t auth_data_out_len)109 int connect__on_authorised(struct mosquitto *context, void *auth_data_out, uint16_t auth_data_out_len)
110 {
111 	struct mosquitto *found_context;
112 	struct mosquitto__subleaf *leaf;
113 	mosquitto_property *connack_props = NULL;
114 	uint8_t connect_ack = 0;
115 	int i;
116 	int rc;
117 	int in_quota, out_quota;
118 	uint16_t in_maximum, out_maximum;
119 
120 	/* Find if this client already has an entry. This must be done *after* any security checks. */
121 	HASH_FIND(hh_id, db.contexts_by_id, context->id, strlen(context->id), found_context);
122 	if(found_context){
123 		/* Found a matching client */
124 		if(found_context->sock == INVALID_SOCKET){
125 			/* Client is reconnecting after a disconnect */
126 			/* FIXME - does anything need to be done here? */
127 		}else{
128 			/* Client is already connected, disconnect old version. This is
129 			 * done in context__cleanup() below. */
130 			if(db.config->connection_messages == true){
131 				log__printf(NULL, MOSQ_LOG_ERR, "Client %s already connected, closing old connection.", context->id);
132 			}
133 		}
134 
135 		if(context->clean_start == false && found_context->session_expiry_interval > 0){
136 			if(context->protocol == mosq_p_mqtt311 || context->protocol == mosq_p_mqtt5){
137 				connect_ack |= 0x01;
138 			}
139 
140 			if(found_context->msgs_in.inflight || found_context->msgs_in.queued
141 					|| found_context->msgs_out.inflight || found_context->msgs_out.queued){
142 
143 				in_quota = context->msgs_in.inflight_quota;
144 				out_quota = context->msgs_out.inflight_quota;
145 				in_maximum = context->msgs_in.inflight_maximum;
146 				out_maximum = context->msgs_out.inflight_maximum;
147 
148 				memcpy(&context->msgs_in, &found_context->msgs_in, sizeof(struct mosquitto_msg_data));
149 				memcpy(&context->msgs_out, &found_context->msgs_out, sizeof(struct mosquitto_msg_data));
150 
151 				memset(&found_context->msgs_in, 0, sizeof(struct mosquitto_msg_data));
152 				memset(&found_context->msgs_out, 0, sizeof(struct mosquitto_msg_data));
153 
154 				context->msgs_in.inflight_quota = in_quota;
155 				context->msgs_out.inflight_quota = out_quota;
156 				context->msgs_in.inflight_maximum = in_maximum;
157 				context->msgs_out.inflight_maximum = out_maximum;
158 
159 				db__message_reconnect_reset(context);
160 			}
161 			context->subs = found_context->subs;
162 			found_context->subs = NULL;
163 			context->sub_count = found_context->sub_count;
164 			found_context->sub_count = 0;
165 			context->last_mid = found_context->last_mid;
166 
167 			for(i=0; i<context->sub_count; i++){
168 				if(context->subs[i]){
169 					leaf = context->subs[i]->hier->subs;
170 					while(leaf){
171 						if(leaf->context == found_context){
172 							leaf->context = context;
173 						}
174 						leaf = leaf->next;
175 					}
176 
177 					if(context->subs[i]->shared){
178 						leaf = context->subs[i]->shared->subs;
179 						while(leaf){
180 							if(leaf->context == found_context){
181 								leaf->context = context;
182 							}
183 							leaf = leaf->next;
184 						}
185 					}
186 				}
187 			}
188 		}
189 
190 		if(context->clean_start == true){
191 			sub__clean_session(found_context);
192 		}
193 		if((found_context->protocol == mosq_p_mqtt5 && found_context->session_expiry_interval == 0)
194 				|| (found_context->protocol != mosq_p_mqtt5 && found_context->clean_start == true)
195 				|| (context->clean_start == true)
196 				){
197 
198 			context__send_will(found_context);
199 		}
200 
201 		session_expiry__remove(found_context);
202 		will_delay__remove(found_context);
203 		will__clear(found_context);
204 
205 		found_context->clean_start = true;
206 		found_context->session_expiry_interval = 0;
207 		mosquitto__set_state(found_context, mosq_cs_duplicate);
208 		do_disconnect(found_context, MOSQ_ERR_SUCCESS);
209 	}
210 
211 	rc = acl__find_acls(context);
212 	if(rc){
213 		free(auth_data_out);
214 		return rc;
215 	}
216 
217 	if(db.config->connection_messages == true){
218 		if(context->is_bridge){
219 			if(context->username){
220 				log__printf(NULL, MOSQ_LOG_NOTICE, "New bridge connected from %s:%d as %s (p%d, c%d, k%d, u'%s').",
221 						context->address, context->remote_port, context->id, context->protocol, context->clean_start, context->keepalive, context->username);
222 			}else{
223 				log__printf(NULL, MOSQ_LOG_NOTICE, "New bridge connected from %s:%d as %s (p%d, c%d, k%d).",
224 						context->address, context->remote_port, context->id, context->protocol, context->clean_start, context->keepalive);
225 			}
226 		}else{
227 			if(context->username){
228 				log__printf(NULL, MOSQ_LOG_NOTICE, "New client connected from %s:%d as %s (p%d, c%d, k%d, u'%s').",
229 						context->address, context->remote_port, context->id, context->protocol, context->clean_start, context->keepalive, context->username);
230 			}else{
231 				log__printf(NULL, MOSQ_LOG_NOTICE, "New client connected from %s:%d as %s (p%d, c%d, k%d).",
232 						context->address, context->remote_port, context->id, context->protocol, context->clean_start, context->keepalive);
233 			}
234 		}
235 
236 		if(context->will) {
237 			log__printf(NULL, MOSQ_LOG_DEBUG, "Will message specified (%ld bytes) (r%d, q%d).",
238 					(long)context->will->msg.payloadlen,
239 					context->will->msg.retain,
240 					context->will->msg.qos);
241 
242 			log__printf(NULL, MOSQ_LOG_DEBUG, "\t%s", context->will->msg.topic);
243 		} else {
244 			log__printf(NULL, MOSQ_LOG_DEBUG, "No will message specified.");
245 		}
246 	}
247 
248 	context->ping_t = 0;
249 	context->is_dropping = false;
250 
251 	connection_check_acl(context, &context->msgs_in.inflight);
252 	connection_check_acl(context, &context->msgs_in.queued);
253 	connection_check_acl(context, &context->msgs_out.inflight);
254 	connection_check_acl(context, &context->msgs_out.queued);
255 
256 	context__add_to_by_id(context);
257 
258 #ifdef WITH_PERSISTENCE
259 	if(!context->clean_start){
260 		db.persistence_changes++;
261 	}
262 #endif
263 	context->max_qos = context->listener->max_qos;
264 
265 	if(db.config->max_keepalive &&
266 			(context->keepalive > db.config->max_keepalive || context->keepalive == 0)){
267 
268 		context->keepalive = db.config->max_keepalive;
269 		if(context->protocol == mosq_p_mqtt5){
270 			if(mosquitto_property_add_int16(&connack_props, MQTT_PROP_SERVER_KEEP_ALIVE, context->keepalive)){
271 				rc = MOSQ_ERR_NOMEM;
272 				goto error;
273 			}
274 		}else{
275 			send__connack(context, connect_ack, CONNACK_REFUSED_IDENTIFIER_REJECTED, NULL);
276 			rc = MOSQ_ERR_INVAL;
277 			goto error;
278 		}
279 	}
280 
281 	if(context->protocol == mosq_p_mqtt5){
282 		if(context->listener->max_topic_alias > 0){
283 			if(mosquitto_property_add_int16(&connack_props, MQTT_PROP_TOPIC_ALIAS_MAXIMUM, context->listener->max_topic_alias)){
284 				rc = MOSQ_ERR_NOMEM;
285 				goto error;
286 			}
287 		}
288 		if(context->assigned_id){
289 			if(mosquitto_property_add_string(&connack_props, MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER, context->id)){
290 				rc = MOSQ_ERR_NOMEM;
291 				goto error;
292 			}
293 		}
294 		if(context->auth_method){
295 			if(mosquitto_property_add_string(&connack_props, MQTT_PROP_AUTHENTICATION_METHOD, context->auth_method)){
296 				rc = MOSQ_ERR_NOMEM;
297 				goto error;
298 			}
299 
300 			if(auth_data_out && auth_data_out_len > 0){
301 				if(mosquitto_property_add_binary(&connack_props, MQTT_PROP_AUTHENTICATION_DATA, auth_data_out, auth_data_out_len)){
302 					rc = MOSQ_ERR_NOMEM;
303 					goto error;
304 				}
305 			}
306 		}
307 	}
308 	free(auth_data_out);
309 	auth_data_out = NULL;
310 
311 	keepalive__add(context);
312 
313 	mosquitto__set_state(context, mosq_cs_active);
314 	rc = send__connack(context, connect_ack, CONNACK_ACCEPTED, connack_props);
315 	mosquitto_property_free_all(&connack_props);
316 	if(rc) return rc;
317 	rc = db__message_write_queued_out(context);
318 	if(rc) return rc;
319 	rc = db__message_write_inflight_out_all(context);
320 	return rc;
321 error:
322 	free(auth_data_out);
323 	mosquitto_property_free_all(&connack_props);
324 	return rc;
325 }
326 
327 
will__read(struct mosquitto * context,const char * client_id,struct mosquitto_message_all ** will,uint8_t will_qos,int will_retain)328 static int will__read(struct mosquitto *context, const char *client_id, struct mosquitto_message_all **will, uint8_t will_qos, int will_retain)
329 {
330 	int rc = MOSQ_ERR_SUCCESS;
331 	size_t slen;
332 	uint16_t tlen;
333 	struct mosquitto_message_all *will_struct = NULL;
334 	char *will_topic_mount = NULL;
335 	uint16_t payloadlen;
336 	mosquitto_property *properties = NULL;
337 
338 	will_struct = mosquitto__calloc(1, sizeof(struct mosquitto_message_all));
339 	if(!will_struct){
340 		rc = MOSQ_ERR_NOMEM;
341 		goto error_cleanup;
342 	}
343 	if(context->protocol == PROTOCOL_VERSION_v5){
344 		rc = property__read_all(CMD_WILL, &context->in_packet, &properties);
345 		if(rc) goto error_cleanup;
346 
347 		rc = property__process_will(context, will_struct, &properties);
348 		mosquitto_property_free_all(&properties);
349 		if(rc) goto error_cleanup;
350 	}
351 	rc = packet__read_string(&context->in_packet, &will_struct->msg.topic, &tlen);
352 	if(rc) goto error_cleanup;
353 	if(!tlen){
354 		rc = MOSQ_ERR_PROTOCOL;
355 		goto error_cleanup;
356 	}
357 
358 	if(context->listener->mount_point){
359 		slen = strlen(context->listener->mount_point) + strlen(will_struct->msg.topic) + 1;
360 		will_topic_mount = mosquitto__malloc(slen+1);
361 		if(!will_topic_mount){
362 			rc = MOSQ_ERR_NOMEM;
363 			goto error_cleanup;
364 		}
365 
366 		snprintf(will_topic_mount, slen, "%s%s", context->listener->mount_point, will_struct->msg.topic);
367 		will_topic_mount[slen] = '\0';
368 
369 		mosquitto__free(will_struct->msg.topic);
370 		will_struct->msg.topic = will_topic_mount;
371 	}
372 
373 	rc = mosquitto_pub_topic_check(will_struct->msg.topic);
374 	if(rc) goto error_cleanup;
375 
376 	rc = packet__read_uint16(&context->in_packet, &payloadlen);
377 	if(rc) goto error_cleanup;
378 
379 	will_struct->msg.payloadlen = payloadlen;
380 	if(will_struct->msg.payloadlen > 0){
381 		if(db.config->message_size_limit && will_struct->msg.payloadlen > (int)db.config->message_size_limit){
382 			log__printf(NULL, MOSQ_LOG_DEBUG, "Client %s connected with too large Will payload", client_id);
383 			if(context->protocol == mosq_p_mqtt5){
384 				send__connack(context, 0, MQTT_RC_PACKET_TOO_LARGE, NULL);
385 			}else{
386 				send__connack(context, 0, CONNACK_REFUSED_NOT_AUTHORIZED, NULL);
387 			}
388 			rc = MOSQ_ERR_PAYLOAD_SIZE;
389 			goto error_cleanup;
390 		}
391 		will_struct->msg.payload = mosquitto__malloc((size_t)will_struct->msg.payloadlen);
392 		if(!will_struct->msg.payload){
393 			rc = MOSQ_ERR_NOMEM;
394 			goto error_cleanup;
395 		}
396 
397 		rc = packet__read_bytes(&context->in_packet, will_struct->msg.payload, (uint32_t)will_struct->msg.payloadlen);
398 		if(rc) goto error_cleanup;
399 	}
400 
401 	will_struct->msg.qos = will_qos;
402 	will_struct->msg.retain = will_retain;
403 
404 	*will = will_struct;
405 	return MOSQ_ERR_SUCCESS;
406 
407 error_cleanup:
408 	if(will_struct){
409 		mosquitto__free(will_struct->msg.topic);
410 		mosquitto__free(will_struct->msg.payload);
411 		mosquitto_property_free_all(&will_struct->properties);
412 		mosquitto__free(will_struct);
413 	}
414 	return rc;
415 }
416 
417 
418 
handle__connect(struct mosquitto * context)419 int handle__connect(struct mosquitto *context)
420 {
421 	char protocol_name[7];
422 	uint8_t protocol_version;
423 	uint8_t connect_flags;
424 	char *client_id = NULL;
425 	struct mosquitto_message_all *will_struct = NULL;
426 	uint8_t will, will_retain, will_qos, clean_start;
427 	uint8_t username_flag, password_flag;
428 	char *username = NULL, *password = NULL;
429 	int rc;
430 	uint16_t slen;
431 	mosquitto_property *properties = NULL;
432 	void *auth_data = NULL;
433 	uint16_t auth_data_len = 0;
434 	void *auth_data_out = NULL;
435 	uint16_t auth_data_out_len = 0;
436 	bool allow_zero_length_clientid;
437 #ifdef WITH_TLS
438 	int i;
439 	X509 *client_cert = NULL;
440 	X509_NAME *name;
441 	X509_NAME_ENTRY *name_entry;
442 	ASN1_STRING *name_asn1 = NULL;
443 	BIO *subject_bio;
444 	char *data_start;
445 	long name_length;
446 	char *subject;
447 #endif
448 
449 	G_CONNECTION_COUNT_INC();
450 
451 	if(!context->listener){
452 		return MOSQ_ERR_INVAL;
453 	}
454 
455 	/* Don't accept multiple CONNECT commands. */
456 	if(context->state != mosq_cs_new){
457 		log__printf(NULL, MOSQ_LOG_NOTICE, "Bad client %s sending multiple CONNECT messages.", context->id);
458 		rc = MOSQ_ERR_PROTOCOL;
459 		goto handle_connect_error;
460 	}
461 	if(context->in_packet.command != CMD_CONNECT){
462 		return MOSQ_ERR_MALFORMED_PACKET;
463 	}
464 
465 	/* Read protocol name as length then bytes rather than with read_string
466 	 * because the length is fixed and we can check that. Removes the need
467 	 * for another malloc as well. */
468 	if(packet__read_uint16(&context->in_packet, &slen)){
469 		rc = MOSQ_ERR_PROTOCOL;
470 		goto handle_connect_error;
471 	}
472 	if(slen != 4 /* MQTT */ && slen != 6 /* MQIsdp */){
473 		rc = MOSQ_ERR_PROTOCOL;
474 		goto handle_connect_error;
475 	}
476 	if(packet__read_bytes(&context->in_packet, protocol_name, slen)){
477 		rc = MOSQ_ERR_PROTOCOL;
478 		goto handle_connect_error;
479 	}
480 	protocol_name[slen] = '\0';
481 
482 	if(packet__read_byte(&context->in_packet, &protocol_version)){
483 		rc = MOSQ_ERR_PROTOCOL;
484 		goto handle_connect_error;
485 	}
486 	if(!strcmp(protocol_name, PROTOCOL_NAME_v31)){
487 		if((protocol_version&0x7F) != PROTOCOL_VERSION_v31){
488 			if(db.config->connection_messages == true){
489 				log__printf(NULL, MOSQ_LOG_INFO, "Invalid protocol version %d in CONNECT from %s.",
490 						protocol_version, context->address);
491 			}
492 			send__connack(context, 0, CONNACK_REFUSED_PROTOCOL_VERSION, NULL);
493 			rc = MOSQ_ERR_PROTOCOL;
494 			goto handle_connect_error;
495 		}
496 		context->protocol = mosq_p_mqtt31;
497 		if((protocol_version&0x80) == 0x80){
498 			context->is_bridge = true;
499 		}
500 	}else if(!strcmp(protocol_name, PROTOCOL_NAME)){
501 		if((protocol_version&0x7F) == PROTOCOL_VERSION_v311){
502 			context->protocol = mosq_p_mqtt311;
503 
504 			if((protocol_version&0x80) == 0x80){
505 				context->is_bridge = true;
506 			}
507 		}else if((protocol_version&0x7F) == PROTOCOL_VERSION_v5){
508 			context->protocol = mosq_p_mqtt5;
509 		}else{
510 			if(db.config->connection_messages == true){
511 				log__printf(NULL, MOSQ_LOG_INFO, "Invalid protocol version %d in CONNECT from %s.",
512 						protocol_version, context->address);
513 			}
514 			send__connack(context, 0, CONNACK_REFUSED_PROTOCOL_VERSION, NULL);
515 			rc = MOSQ_ERR_PROTOCOL;
516 			goto handle_connect_error;
517 		}
518 		if((context->in_packet.command&0x0F) != 0x00){
519 			/* Reserved flags not set to 0, must disconnect. */
520 			rc = MOSQ_ERR_PROTOCOL;
521 			goto handle_connect_error;
522 		}
523 	}else{
524 		if(db.config->connection_messages == true){
525 			log__printf(NULL, MOSQ_LOG_INFO, "Invalid protocol \"%s\" in CONNECT from %s.",
526 					protocol_name, context->address);
527 		}
528 		rc = MOSQ_ERR_PROTOCOL;
529 		goto handle_connect_error;
530 	}
531 
532 	if(packet__read_byte(&context->in_packet, &connect_flags)){
533 		rc = MOSQ_ERR_PROTOCOL;
534 		goto handle_connect_error;
535 	}
536 	if(context->protocol == mosq_p_mqtt311 || context->protocol == mosq_p_mqtt5){
537 		if((connect_flags & 0x01) != 0x00){
538 			rc = MOSQ_ERR_PROTOCOL;
539 			goto handle_connect_error;
540 		}
541 	}
542 
543 	clean_start = (connect_flags & 0x02) >> 1;
544 	/* session_expiry_interval will be overriden if the properties are read later */
545 	if(clean_start == false && protocol_version != PROTOCOL_VERSION_v5){
546 		/* v3* has clean_start == false mean the session never expires */
547 		context->session_expiry_interval = UINT32_MAX;
548 	}else{
549 		context->session_expiry_interval = 0;
550 	}
551 	will = connect_flags & 0x04;
552 	will_qos = (connect_flags & 0x18) >> 3;
553 	if(will_qos == 3){
554 		log__printf(NULL, MOSQ_LOG_INFO, "Invalid Will QoS in CONNECT from %s.",
555 				context->address);
556 		rc = MOSQ_ERR_PROTOCOL;
557 		goto handle_connect_error;
558 	}
559 	will_retain = ((connect_flags & 0x20) == 0x20);
560 	password_flag = connect_flags & 0x40;
561 	username_flag = connect_flags & 0x80;
562 
563 	if(will && will_retain && db.config->retain_available == false){
564 		if(protocol_version == mosq_p_mqtt5){
565 			send__connack(context, 0, MQTT_RC_RETAIN_NOT_SUPPORTED, NULL);
566 		}
567 		rc = MOSQ_ERR_NOT_SUPPORTED;
568 		goto handle_connect_error;
569 	}
570 
571 	if(packet__read_uint16(&context->in_packet, &(context->keepalive))){
572 		rc = MOSQ_ERR_PROTOCOL;
573 		goto handle_connect_error;
574 	}
575 
576 	if(protocol_version == PROTOCOL_VERSION_v5){
577 		rc = property__read_all(CMD_CONNECT, &context->in_packet, &properties);
578 		if(rc) goto handle_connect_error;
579 	}
580 	property__process_connect(context, &properties);
581 
582 	if(will && will_qos > context->listener->max_qos){
583 		if(protocol_version == mosq_p_mqtt5){
584 			send__connack(context, 0, MQTT_RC_QOS_NOT_SUPPORTED, NULL);
585 		}
586 		rc = MOSQ_ERR_NOT_SUPPORTED;
587 		goto handle_connect_error;
588 	}
589 
590 	if(mosquitto_property_read_string(properties, MQTT_PROP_AUTHENTICATION_METHOD, &context->auth_method, false)){
591 		mosquitto_property_read_binary(properties, MQTT_PROP_AUTHENTICATION_DATA, &auth_data, &auth_data_len, false);
592 	}
593 
594 	mosquitto_property_free_all(&properties); /* FIXME - TEMPORARY UNTIL PROPERTIES PROCESSED */
595 
596 	if(packet__read_string(&context->in_packet, &client_id, &slen)){
597 		rc = MOSQ_ERR_PROTOCOL;
598 		goto handle_connect_error;
599 	}
600 
601 	if(slen == 0){
602 		if(context->protocol == mosq_p_mqtt31){
603 			send__connack(context, 0, CONNACK_REFUSED_IDENTIFIER_REJECTED, NULL);
604 			rc = MOSQ_ERR_PROTOCOL;
605 			goto handle_connect_error;
606 		}else{ /* mqtt311/mqtt5 */
607 			mosquitto__free(client_id);
608 			client_id = NULL;
609 
610 			if(db.config->per_listener_settings){
611 				allow_zero_length_clientid = context->listener->security_options.allow_zero_length_clientid;
612 			}else{
613 				allow_zero_length_clientid = db.config->security_options.allow_zero_length_clientid;
614 			}
615 			if((context->protocol == mosq_p_mqtt311 && clean_start == 0) || allow_zero_length_clientid == false){
616 				if(context->protocol == mosq_p_mqtt311){
617 					send__connack(context, 0, CONNACK_REFUSED_IDENTIFIER_REJECTED, NULL);
618 				}else{
619 					send__connack(context, 0, MQTT_RC_UNSPECIFIED, NULL);
620 				}
621 				rc = MOSQ_ERR_PROTOCOL;
622 				goto handle_connect_error;
623 			}else{
624 				if(db.config->per_listener_settings){
625 					client_id = client_id_gen(&slen, context->listener->security_options.auto_id_prefix, context->listener->security_options.auto_id_prefix_len);
626 				}else{
627 					client_id = client_id_gen(&slen, db.config->security_options.auto_id_prefix, db.config->security_options.auto_id_prefix_len);
628 				}
629 				if(!client_id){
630 					rc = MOSQ_ERR_NOMEM;
631 					goto handle_connect_error;
632 				}
633 				context->assigned_id = true;
634 			}
635 		}
636 	}
637 
638 	/* clientid_prefixes check */
639 	if(db.config->clientid_prefixes){
640 		if(strncmp(db.config->clientid_prefixes, client_id, strlen(db.config->clientid_prefixes))){
641 			if(context->protocol == mosq_p_mqtt5){
642 				send__connack(context, 0, MQTT_RC_NOT_AUTHORIZED, NULL);
643 			}else{
644 				send__connack(context, 0, CONNACK_REFUSED_NOT_AUTHORIZED, NULL);
645 			}
646 			rc = MOSQ_ERR_AUTH;
647 			goto handle_connect_error;
648 		}
649 	}
650 
651 	if(will){
652 		rc = will__read(context, client_id, &will_struct, will_qos, will_retain);
653 		if(rc) goto handle_connect_error;
654 	}else{
655 		if(context->protocol == mosq_p_mqtt311 || context->protocol == mosq_p_mqtt5){
656 			if(will_qos != 0 || will_retain != 0){
657 				rc = MOSQ_ERR_PROTOCOL;
658 				goto handle_connect_error;
659 			}
660 		}
661 	}
662 
663 	if(username_flag){
664 		rc = packet__read_string(&context->in_packet, &username, &slen);
665 		if(rc == MOSQ_ERR_NOMEM){
666 			rc = MOSQ_ERR_NOMEM;
667 			goto handle_connect_error;
668 		}else if(rc != MOSQ_ERR_SUCCESS){
669 			if(context->protocol == mosq_p_mqtt31){
670 				/* Username flag given, but no username. Ignore. */
671 				username_flag = 0;
672 			}else{
673 				rc = MOSQ_ERR_PROTOCOL;
674 				goto handle_connect_error;
675 			}
676 		}
677 	}else{
678 		if(context->protocol == mosq_p_mqtt311 || context->protocol == mosq_p_mqtt31){
679 			if(password_flag){
680 				/* username_flag == 0 && password_flag == 1 is forbidden */
681 				log__printf(NULL, MOSQ_LOG_ERR, "Protocol error from %s: password without username, closing connection.", client_id);
682 				rc = MOSQ_ERR_PROTOCOL;
683 				goto handle_connect_error;
684 			}
685 		}
686 	}
687 	if(password_flag){
688 		rc = packet__read_binary(&context->in_packet, (uint8_t **)&password, &slen);
689 		if(rc == MOSQ_ERR_NOMEM){
690 			rc = MOSQ_ERR_NOMEM;
691 			goto handle_connect_error;
692 		}else if(rc == MOSQ_ERR_MALFORMED_PACKET){
693 			if(context->protocol == mosq_p_mqtt31){
694 				/* Password flag given, but no password. Ignore. */
695 			}else{
696 				rc = MOSQ_ERR_PROTOCOL;
697 				goto handle_connect_error;
698 			}
699 		}
700 	}
701 
702 	if(context->in_packet.pos != context->in_packet.remaining_length){
703 		/* Surplus data at end of packet, this must be an error. */
704 		rc = MOSQ_ERR_PROTOCOL;
705 		goto handle_connect_error;
706 	}
707 
708 	/* Once context->id is set, if we return from this function with an error
709 	 * we must make sure that context->id is freed and set to NULL, so that the
710 	 * client isn't erroneously removed from the by_id hash table. */
711 	context->id = client_id;
712 	client_id = NULL;
713 
714 #ifdef WITH_TLS
715 	if(context->listener->ssl_ctx && (context->listener->use_identity_as_username || context->listener->use_subject_as_username)){
716 		/* Don't need the username or password if provided */
717 		mosquitto__free(username);
718 		username = NULL;
719 		mosquitto__free(password);
720 		password = NULL;
721 
722 		if(!context->ssl){
723 			if(context->protocol == mosq_p_mqtt5){
724 				send__connack(context, 0, MQTT_RC_BAD_USERNAME_OR_PASSWORD, NULL);
725 			}else{
726 				send__connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD, NULL);
727 			}
728 			rc = MOSQ_ERR_AUTH;
729 			goto handle_connect_error;
730 		}
731 #ifdef FINAL_WITH_TLS_PSK
732 		if(context->listener->psk_hint){
733 			/* Client should have provided an identity to get this far. */
734 			if(!context->username){
735 				if(context->protocol == mosq_p_mqtt5){
736 					send__connack(context, 0, MQTT_RC_BAD_USERNAME_OR_PASSWORD, NULL);
737 				}else{
738 					send__connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD, NULL);
739 				}
740 				rc = MOSQ_ERR_AUTH;
741 				goto handle_connect_error;
742 			}
743 		}else{
744 #endif /* FINAL_WITH_TLS_PSK */
745 			client_cert = SSL_get_peer_certificate(context->ssl);
746 			if(!client_cert){
747 				if(context->protocol == mosq_p_mqtt5){
748 					send__connack(context, 0, MQTT_RC_BAD_USERNAME_OR_PASSWORD, NULL);
749 				}else{
750 					send__connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD, NULL);
751 				}
752 				rc = MOSQ_ERR_AUTH;
753 				goto handle_connect_error;
754 			}
755 			name = X509_get_subject_name(client_cert);
756 			if(!name){
757 				if(context->protocol == mosq_p_mqtt5){
758 					send__connack(context, 0, MQTT_RC_BAD_USERNAME_OR_PASSWORD, NULL);
759 				}else{
760 					send__connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD, NULL);
761 				}
762 				rc = MOSQ_ERR_AUTH;
763 				goto handle_connect_error;
764 			}
765 			if (context->listener->use_identity_as_username) { /* use_identity_as_username */
766 				i = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
767 				if(i == -1){
768 					if(context->protocol == mosq_p_mqtt5){
769 						send__connack(context, 0, MQTT_RC_BAD_USERNAME_OR_PASSWORD, NULL);
770 					}else{
771 						send__connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD, NULL);
772 					}
773 					rc = MOSQ_ERR_AUTH;
774 					goto handle_connect_error;
775 				}
776 				name_entry = X509_NAME_get_entry(name, i);
777 				if(name_entry){
778 					name_asn1 = X509_NAME_ENTRY_get_data(name_entry);
779 					if (name_asn1 == NULL) {
780 						if(context->protocol == mosq_p_mqtt5){
781 							send__connack(context, 0, MQTT_RC_BAD_USERNAME_OR_PASSWORD, NULL);
782 						}else{
783 							send__connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD, NULL);
784 						}
785 						rc = MOSQ_ERR_AUTH;
786 						goto handle_connect_error;
787 					}
788 #if OPENSSL_VERSION_NUMBER < 0x10100000L
789 					context->username = mosquitto__strdup((char *) ASN1_STRING_data(name_asn1));
790 #else
791 					context->username = mosquitto__strdup((char *) ASN1_STRING_get0_data(name_asn1));
792 #endif
793 					if(!context->username){
794 						if(context->protocol == mosq_p_mqtt5){
795 							send__connack(context, 0, MQTT_RC_SERVER_UNAVAILABLE, NULL);
796 						}else{
797 							send__connack(context, 0, CONNACK_REFUSED_SERVER_UNAVAILABLE, NULL);
798 						}
799 						rc = MOSQ_ERR_NOMEM;
800 						goto handle_connect_error;
801 					}
802 					/* Make sure there isn't an embedded NUL character in the CN */
803 					if ((size_t)ASN1_STRING_length(name_asn1) != strlen(context->username)) {
804 						if(context->protocol == mosq_p_mqtt5){
805 							send__connack(context, 0, MQTT_RC_BAD_USERNAME_OR_PASSWORD, NULL);
806 						}else{
807 							send__connack(context, 0, CONNACK_REFUSED_BAD_USERNAME_PASSWORD, NULL);
808 						}
809 						rc = MOSQ_ERR_AUTH;
810 						goto handle_connect_error;
811 					}
812 				}
813 			} else { /* use_subject_as_username */
814 				subject_bio = BIO_new(BIO_s_mem());
815 				X509_NAME_print_ex(subject_bio, X509_get_subject_name(client_cert), 0, XN_FLAG_RFC2253);
816 				data_start = NULL;
817 				name_length = BIO_get_mem_data(subject_bio, &data_start);
818 				subject = mosquitto__malloc(sizeof(char)*(size_t)(name_length+1));
819 				if(!subject){
820 					BIO_free(subject_bio);
821 					rc = MOSQ_ERR_NOMEM;
822 					goto handle_connect_error;
823 				}
824 				memcpy(subject, data_start, (size_t)name_length);
825 				subject[name_length] = '\0';
826 				BIO_free(subject_bio);
827 				context->username = subject;
828 			}
829 			if(!context->username){
830 				rc = MOSQ_ERR_AUTH;
831 				goto handle_connect_error;
832 			}
833 			X509_free(client_cert);
834 			client_cert = NULL;
835 #ifdef FINAL_WITH_TLS_PSK
836 		}
837 #endif /* FINAL_WITH_TLS_PSK */
838 	}else
839 #endif /* WITH_TLS */
840 	{
841 		/* FIXME - these ensure the mosquitto_client_id() and
842 		 * mosquitto_client_username() functions work, but is hacky */
843 		context->username = username;
844 		context->password = password;
845 		username = NULL; /* Avoid free() in error: below. */
846 		password = NULL;
847 	}
848 
849 	if(context->listener->use_username_as_clientid){
850 		if(context->username){
851 			mosquitto__free(context->id);
852 			context->id = mosquitto__strdup(context->username);
853 			if(!context->id){
854 				rc = MOSQ_ERR_NOMEM;
855 				goto handle_connect_error;
856 			}
857 		}else{
858 			if(context->protocol == mosq_p_mqtt5){
859 				send__connack(context, 0, MQTT_RC_NOT_AUTHORIZED, NULL);
860 			}else{
861 				send__connack(context, 0, CONNACK_REFUSED_NOT_AUTHORIZED, NULL);
862 			}
863 			rc = MOSQ_ERR_AUTH;
864 			goto handle_connect_error;
865 		}
866 	}
867 	context->clean_start = clean_start;
868 	context->will = will_struct;
869 	will_struct = NULL;
870 
871 	if(context->auth_method){
872 		rc = mosquitto_security_auth_start(context, false, auth_data, auth_data_len, &auth_data_out, &auth_data_out_len);
873 		mosquitto__free(auth_data);
874 		auth_data = NULL;
875 		if(rc == MOSQ_ERR_SUCCESS){
876 			return connect__on_authorised(context, auth_data_out, auth_data_out_len);
877 		}else if(rc == MOSQ_ERR_AUTH_CONTINUE){
878 			mosquitto__set_state(context, mosq_cs_authenticating);
879 			rc = send__auth(context, MQTT_RC_CONTINUE_AUTHENTICATION, auth_data_out, auth_data_out_len);
880 			free(auth_data_out);
881 			return rc;
882 		}else{
883 			free(auth_data_out);
884 			auth_data_out = NULL;
885 			will__clear(context);
886 			if(rc == MOSQ_ERR_AUTH){
887 				send__connack(context, 0, MQTT_RC_NOT_AUTHORIZED, NULL);
888 				mosquitto__free(context->id);
889 				context->id = NULL;
890 				goto handle_connect_error;
891 			}else if(rc == MOSQ_ERR_NOT_SUPPORTED){
892 				/* Client has requested extended authentication, but we don't support it. */
893 				send__connack(context, 0, MQTT_RC_BAD_AUTHENTICATION_METHOD, NULL);
894 				mosquitto__free(context->id);
895 				context->id = NULL;
896 				goto handle_connect_error;
897 			}else{
898 				mosquitto__free(context->id);
899 				context->id = NULL;
900 				goto handle_connect_error;
901 			}
902 		}
903 	}else{
904 #ifdef WITH_TLS
905 		if(context->listener->ssl_ctx && (context->listener->use_identity_as_username || context->listener->use_subject_as_username)){
906 			/* Authentication assumed to be cleared */
907 		}else
908 #endif
909 		{
910 			rc = mosquitto_unpwd_check(context);
911 			switch(rc){
912 				case MOSQ_ERR_SUCCESS:
913 					break;
914 				case MOSQ_ERR_AUTH:
915 					if(context->protocol == mosq_p_mqtt5){
916 						send__connack(context, 0, MQTT_RC_NOT_AUTHORIZED, NULL);
917 					}else{
918 						send__connack(context, 0, CONNACK_REFUSED_NOT_AUTHORIZED, NULL);
919 					}
920 					rc = MOSQ_ERR_AUTH;
921 					goto handle_connect_error;
922 					break;
923 				default:
924 					rc = MOSQ_ERR_UNKNOWN;
925 					goto handle_connect_error;
926 					break;
927 			}
928 		}
929 		return connect__on_authorised(context, NULL, 0);
930 	}
931 
932 
933 handle_connect_error:
934 	mosquitto__free(auth_data);
935 	mosquitto__free(client_id);
936 	mosquitto__free(username);
937 	mosquitto__free(password);
938 	if(will_struct){
939 		mosquitto_property_free_all(&will_struct->properties);
940 		mosquitto__free(will_struct->msg.payload);
941 		mosquitto__free(will_struct->msg.topic);
942 		mosquitto__free(will_struct);
943 	}
944 	context->will = NULL;
945 #ifdef WITH_TLS
946 	if(client_cert) X509_free(client_cert);
947 #endif
948 	/* We return an error here which means the client is freed later on. */
949 	context->clean_start = true;
950 	context->session_expiry_interval = 0;
951 	context->will_delay_interval = 0;
952 	return rc;
953 }
954