Line | Count | Source |
1 | | /* |
2 | | Copyright (c) 2009-2021 Roger Light <roger@atchoo.org> |
3 | | |
4 | | All rights reserved. This program and the accompanying materials |
5 | | are made available under the terms of the Eclipse Public License 2.0 |
6 | | and Eclipse Distribution License v1.0 which accompany this distribution. |
7 | | |
8 | | The Eclipse Public License is available at |
9 | | https://www.eclipse.org/legal/epl-2.0/ |
10 | | and the Eclipse Distribution License is available at |
11 | | http://www.eclipse.org/org/documents/edl-v10.php. |
12 | | |
13 | | SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
14 | | |
15 | | Contributors: |
16 | | Roger Light - initial implementation and documentation. |
17 | | */ |
18 | | |
19 | | #include "config.h" |
20 | | |
21 | | #ifndef WIN32 |
22 | | # include <arpa/inet.h> |
23 | | # ifndef _AIX |
24 | | # include <ifaddrs.h> |
25 | | # endif |
26 | | # include <netdb.h> |
27 | | # include <netinet/tcp.h> |
28 | | # include <strings.h> |
29 | | # include <sys/socket.h> |
30 | | # include <unistd.h> |
31 | | #else |
32 | | # include <winsock2.h> |
33 | | # include <ws2tcpip.h> |
34 | | #endif |
35 | | |
36 | | #include <errno.h> |
37 | | #include <fcntl.h> |
38 | | #include <stdio.h> |
39 | | #include <string.h> |
40 | | #ifdef WITH_WRAP |
41 | | # include <tcpd.h> |
42 | | #endif |
43 | | |
44 | | #ifdef HAVE_NETINET_IN_H |
45 | | # include <netinet/in.h> |
46 | | #endif |
47 | | |
48 | | #if defined(WITH_UNIX_SOCKETS) || defined(WITH_TLS) |
49 | | # include "sys/stat.h" |
50 | | #endif |
51 | | |
52 | | #ifdef WITH_UNIX_SOCKETS |
53 | | # include "sys/un.h" |
54 | | #endif |
55 | | |
56 | | #ifdef __QNX__ |
57 | | # include <net/netbyte.h> |
58 | | #endif |
59 | | |
60 | | #include "mosquitto_broker_internal.h" |
61 | | #include "mosquitto/mqtt_protocol.h" |
62 | | #include "net_mosq.h" |
63 | | #include "util_mosq.h" |
64 | | |
65 | | #ifdef WITH_TLS |
66 | | # include "tls_mosq.h" |
67 | | # include <openssl/err.h> |
68 | | static int tls_ex_index_context = -1; |
69 | | static int tls_ex_index_listener = -1; |
70 | | #endif |
71 | | |
72 | | #include "sys_tree.h" |
73 | | |
74 | | /* For EMFILE handling */ |
75 | | static mosq_sock_t spare_sock = INVALID_SOCKET; |
76 | | |
77 | | |
78 | | void net__broker_init(void) |
79 | 0 | { |
80 | 0 | spare_sock = socket(AF_INET, SOCK_STREAM, 0); |
81 | 0 | net__init(); |
82 | 0 | #ifdef WITH_TLS |
83 | 0 | net__init_tls(); |
84 | 0 | #endif |
85 | 0 | } |
86 | | |
87 | | |
88 | | void net__broker_cleanup(void) |
89 | 0 | { |
90 | 0 | if(spare_sock != INVALID_SOCKET){ |
91 | 0 | COMPAT_CLOSE(spare_sock); |
92 | 0 | spare_sock = INVALID_SOCKET; |
93 | 0 | } |
94 | 0 | net__cleanup(); |
95 | 0 | } |
96 | | |
97 | | |
98 | | static void net__print_error(unsigned int log, const char *format_str) |
99 | 0 | { |
100 | 0 | char *buf; |
101 | |
|
102 | | #ifdef WIN32 |
103 | | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, |
104 | | NULL, WSAGetLastError(), LANG_NEUTRAL, (LPTSTR)&buf, 0, NULL); |
105 | | |
106 | | log__printf(NULL, log, format_str, buf); |
107 | | LocalFree(buf); |
108 | | #else |
109 | 0 | buf = strerror(errno); |
110 | 0 | log__printf(NULL, log, format_str, buf); |
111 | 0 | #endif |
112 | 0 | } |
113 | | |
114 | | |
115 | | struct mosquitto *net__socket_accept(struct mosquitto__listener_sock *listensock) |
116 | 0 | { |
117 | 0 | mosq_sock_t new_sock = INVALID_SOCKET; |
118 | 0 | struct mosquitto *new_context; |
119 | 0 | #ifdef WITH_TLS |
120 | 0 | BIO *bio; |
121 | 0 | #endif |
122 | | #ifdef WITH_WRAP |
123 | | struct request_info wrap_req; |
124 | | char address[1024]; |
125 | | #endif |
126 | |
|
127 | 0 | new_sock = accept(listensock->sock, NULL, 0); |
128 | 0 | if(new_sock == INVALID_SOCKET){ |
129 | | #ifdef WIN32 |
130 | | WINDOWS_SET_ERRNO(); |
131 | | if(errno == WSAEMFILE){ |
132 | | #else |
133 | 0 | if(errno == EMFILE || errno == ENFILE){ |
134 | 0 | #endif |
135 | | /* Close the spare socket, which means we should be able to accept |
136 | | * this connection. Accept it, then close it immediately and create |
137 | | * a new spare_sock. This prevents the situation of ever properly |
138 | | * running out of sockets. |
139 | | * It would be nice to send a "server not available" connack here, |
140 | | * but there are lots of reasons why this would be tricky (TLS |
141 | | * being the big one). */ |
142 | 0 | COMPAT_CLOSE(spare_sock); |
143 | 0 | new_sock = accept(listensock->sock, NULL, 0); |
144 | 0 | if(new_sock != INVALID_SOCKET){ |
145 | 0 | COMPAT_CLOSE(new_sock); |
146 | 0 | } |
147 | 0 | spare_sock = socket(AF_INET, SOCK_STREAM, 0); |
148 | 0 | log__printf(NULL, MOSQ_LOG_WARNING, |
149 | 0 | "Unable to accept new connection, system socket count has been exceeded. Try increasing \"ulimit -n\" or equivalent."); |
150 | 0 | } |
151 | 0 | return NULL; |
152 | 0 | } |
153 | | |
154 | 0 | metrics__int_inc(mosq_counter_socket_connections, 1); |
155 | |
|
156 | 0 | if(net__socket_nonblock(&new_sock)){ |
157 | 0 | return NULL; |
158 | 0 | } |
159 | | |
160 | | #ifdef WITH_WRAP |
161 | | /* Use tcpd / libwrap to determine whether a connection is allowed. */ |
162 | | request_init(&wrap_req, RQ_FILE, new_sock, RQ_DAEMON, "mosquitto", 0); |
163 | | fromhost(&wrap_req); |
164 | | if(!hosts_access(&wrap_req)){ |
165 | | /* Access is denied */ |
166 | | if(db.config->connection_messages == true){ |
167 | | if(!net__socket_get_address(new_sock, address, 1024, NULL)){ |
168 | | log__printf(NULL, MOSQ_LOG_NOTICE, "Client connection from %s denied access by tcpd.", address); |
169 | | } |
170 | | } |
171 | | COMPAT_CLOSE(new_sock); |
172 | | return NULL; |
173 | | } |
174 | | #endif |
175 | | |
176 | 0 | if(db.config->set_tcp_nodelay && listensock->listener->port){ |
177 | 0 | int flag = 1; |
178 | | #ifdef WIN32 |
179 | | if(setsockopt(new_sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) != 0){ |
180 | | #else |
181 | 0 | if(setsockopt(new_sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int)) != 0){ |
182 | 0 | #endif |
183 | 0 | log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Unable to set TCP_NODELAY."); |
184 | 0 | } |
185 | 0 | } |
186 | |
|
187 | 0 | new_context = context__init(); |
188 | 0 | if(!new_context){ |
189 | 0 | COMPAT_CLOSE(new_sock); |
190 | 0 | return NULL; |
191 | 0 | } |
192 | 0 | new_context->listener = listensock->listener; |
193 | 0 | if(!new_context->listener){ |
194 | 0 | context__cleanup(new_context, true); |
195 | 0 | return NULL; |
196 | 0 | } |
197 | 0 | new_context->listener->client_count++; |
198 | |
|
199 | 0 | if(new_context->listener->enable_proxy_protocol){ |
200 | 0 | if(context__init_sock(new_context, new_sock, false) != MOSQ_ERR_SUCCESS){ |
201 | 0 | context__cleanup(new_context, true); |
202 | 0 | COMPAT_CLOSE(new_sock); |
203 | 0 | return NULL; |
204 | 0 | } |
205 | 0 | if(new_context->listener->enable_proxy_protocol == 2){ |
206 | 0 | new_context->transport = mosq_t_proxy_v2; |
207 | 0 | }else{ |
208 | 0 | new_context->transport = mosq_t_proxy_v1; |
209 | 0 | } |
210 | 0 | new_context->proxy.cmd = -1; |
211 | 0 | }else{ |
212 | 0 | if(context__init_sock(new_context, new_sock, true) != MOSQ_ERR_SUCCESS){ |
213 | 0 | context__cleanup(new_context, true); |
214 | 0 | COMPAT_CLOSE(new_sock); |
215 | 0 | return NULL; |
216 | 0 | } |
217 | 0 | switch(new_context->listener->protocol){ |
218 | 0 | case mp_mqtt: |
219 | 0 | new_context->transport = mosq_t_tcp; |
220 | 0 | break; |
221 | 0 | #if defined(WITH_WEBSOCKETS) && WITH_WEBSOCKETS == WS_IS_BUILTIN |
222 | 0 | case mp_websockets: |
223 | 0 | if(http__context_init(new_context)){ |
224 | 0 | context__cleanup(new_context, true); |
225 | 0 | return NULL; |
226 | 0 | } |
227 | 0 | break; |
228 | 0 | #endif |
229 | 0 | default: |
230 | 0 | context__cleanup(new_context, true); |
231 | 0 | return NULL; |
232 | 0 | } |
233 | 0 | } |
234 | | |
235 | 0 | if((new_context->listener->max_connections > 0 && new_context->listener->client_count > new_context->listener->max_connections) |
236 | 0 | || (db.config->global_max_connections > 0 && HASH_CNT(hh_sock, db.contexts_by_sock) > (unsigned int)db.config->global_max_connections)){ |
237 | |
|
238 | 0 | if(db.config->connection_messages == true){ |
239 | 0 | log__printf(NULL, MOSQ_LOG_NOTICE, "Client connection from %s denied: max_connections exceeded.", new_context->address); |
240 | 0 | } |
241 | 0 | context__cleanup(new_context, true); |
242 | 0 | return NULL; |
243 | 0 | } |
244 | | |
245 | 0 | #ifdef WITH_TLS |
246 | | /* TLS init */ |
247 | 0 | if(new_context->listener->ssl_ctx){ |
248 | 0 | new_context->ssl = SSL_new(new_context->listener->ssl_ctx); |
249 | 0 | if(!new_context->ssl){ |
250 | 0 | context__cleanup(new_context, true); |
251 | 0 | return NULL; |
252 | 0 | } |
253 | 0 | if(!SSL_set_ex_data(new_context->ssl, tls_ex_index_context, new_context) |
254 | 0 | || !SSL_set_ex_data(new_context->ssl, tls_ex_index_listener, new_context->listener)){ |
255 | 0 | context__cleanup(new_context, true); |
256 | 0 | return NULL; |
257 | 0 | } |
258 | 0 | new_context->want_write = true; |
259 | 0 | bio = BIO_new_socket(new_sock, BIO_NOCLOSE); |
260 | 0 | SSL_set_bio(new_context->ssl, bio, bio); |
261 | 0 | ERR_clear_error(); |
262 | 0 | SSL_set_accept_state(new_context->ssl); |
263 | 0 | } |
264 | 0 | #endif |
265 | | |
266 | 0 | if(db.config->connection_messages == true |
267 | 0 | && !new_context->listener->enable_proxy_protocol){ |
268 | |
|
269 | 0 | log__printf(NULL, MOSQ_LOG_NOTICE, "New connection from %s:%d on port %d.", |
270 | 0 | new_context->address, new_context->remote_port, new_context->listener->port); |
271 | 0 | } |
272 | |
|
273 | 0 | mux__new(new_context); |
274 | 0 | keepalive__add(new_context); |
275 | |
|
276 | 0 | return new_context; |
277 | 0 | } |
278 | | |
279 | | #ifdef WITH_TLS |
280 | | |
281 | | |
282 | | static int client_certificate_verify(int preverify_ok, X509_STORE_CTX *ctx) |
283 | 0 | { |
284 | | /* Preverify should check expiry, revocation. */ |
285 | 0 | if(preverify_ok == 0){ |
286 | 0 | SSL *ssl; |
287 | 0 | ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); |
288 | 0 | if(ssl){ |
289 | 0 | struct mosquitto__listener *listener; |
290 | 0 | listener = SSL_get_ex_data(ssl, tls_ex_index_listener); |
291 | |
|
292 | 0 | if(listener && listener->disable_client_cert_date_checks){ |
293 | 0 | int err = X509_STORE_CTX_get_error(ctx); |
294 | 0 | if(err == X509_V_ERR_CERT_NOT_YET_VALID || err == X509_V_ERR_CERT_HAS_EXPIRED){ |
295 | 0 | preverify_ok = 1; |
296 | 0 | } |
297 | 0 | } |
298 | 0 | } |
299 | 0 | } |
300 | 0 | return preverify_ok; |
301 | 0 | } |
302 | | #endif |
303 | | |
304 | | #ifdef FINAL_WITH_TLS_PSK |
305 | | |
306 | | |
307 | | static unsigned int psk_server_callback(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len) |
308 | 0 | { |
309 | 0 | struct mosquitto *context; |
310 | 0 | struct mosquitto__listener *listener; |
311 | 0 | char *psk_key = NULL; |
312 | 0 | int len; |
313 | 0 | const char *psk_hint; |
314 | |
|
315 | 0 | if(!identity){ |
316 | 0 | return 0; |
317 | 0 | } |
318 | | |
319 | 0 | context = SSL_get_ex_data(ssl, tls_ex_index_context); |
320 | 0 | if(!context){ |
321 | 0 | return 0; |
322 | 0 | } |
323 | | |
324 | 0 | listener = SSL_get_ex_data(ssl, tls_ex_index_listener); |
325 | 0 | if(!listener){ |
326 | 0 | return 0; |
327 | 0 | } |
328 | | |
329 | 0 | psk_hint = listener->psk_hint; |
330 | | |
331 | | /* The hex to BN conversion results in the length halving, so we can pass |
332 | | * max_psk_len*2 as the max hex key here. */ |
333 | 0 | psk_key = mosquitto_calloc(1, (size_t)max_psk_len*2 + 1); |
334 | 0 | if(!psk_key){ |
335 | 0 | return 0; |
336 | 0 | } |
337 | | |
338 | 0 | if(mosquitto_psk_key_get(context, psk_hint, identity, psk_key, (int)max_psk_len*2) != MOSQ_ERR_SUCCESS){ |
339 | 0 | mosquitto_FREE(psk_key); |
340 | 0 | return 0; |
341 | 0 | } |
342 | | |
343 | 0 | len = mosquitto__hex2bin(psk_key, psk, (int)max_psk_len); |
344 | 0 | if(len < 0){ |
345 | 0 | mosquitto_FREE(psk_key); |
346 | 0 | return 0; |
347 | 0 | } |
348 | | |
349 | 0 | if(listener->use_identity_as_username){ |
350 | 0 | if(mosquitto_validate_utf8(identity, (int)strlen(identity))){ |
351 | 0 | mosquitto_free(psk_key); |
352 | 0 | return 0; |
353 | 0 | } |
354 | 0 | context->username = mosquitto_strdup(identity); |
355 | 0 | if(!context->username){ |
356 | 0 | mosquitto_FREE(psk_key); |
357 | 0 | return 0; |
358 | 0 | } |
359 | 0 | } |
360 | | |
361 | 0 | mosquitto_FREE(psk_key); |
362 | 0 | return (unsigned int)len; |
363 | 0 | } |
364 | | #endif |
365 | | |
366 | | #ifdef WITH_TLS |
367 | | |
368 | | |
369 | | static void tls_keylog_callback(const SSL *ssl, const char *line) |
370 | 0 | { |
371 | 0 | UNUSED(ssl); |
372 | |
|
373 | 0 | if(db.tls_keylog){ |
374 | 0 | FILE *fptr; |
375 | 0 | fptr = mosquitto_fopen(db.tls_keylog, "at", true); |
376 | 0 | if(fptr){ |
377 | 0 | #ifndef WIN32 |
378 | | /* Until mosquitto_fopen enforces file permissions on all files, |
379 | | * enforce it here. We can enforce it here, because it isn't a |
380 | | * change of behaviour. */ |
381 | 0 | struct stat statbuf; |
382 | 0 | if(fstat(fileno(fptr), &statbuf) < 0 |
383 | 0 | || statbuf.st_mode & (S_IRWXG | S_IRWXO)){ |
384 | |
|
385 | 0 | fclose(fptr); |
386 | 0 | return; |
387 | 0 | } |
388 | 0 | #endif |
389 | 0 | fprintf(fptr, "%s\n", line); |
390 | 0 | fclose(fptr); |
391 | 0 | }else{ |
392 | 0 | #ifndef WIN32 |
393 | 0 | if(errno == ELOOP){ |
394 | 0 | log__printf(NULL, MOSQ_LOG_INFO, "Error: keylog file must not be a symbolic link"); |
395 | 0 | }else |
396 | 0 | #endif |
397 | 0 | { |
398 | 0 | log__printf(NULL, MOSQ_LOG_INFO, "Error: Unable to open keylog file: %s", strerror(errno)); |
399 | 0 | } |
400 | 0 | } |
401 | 0 | } |
402 | 0 | } |
403 | | |
404 | | |
405 | | int net__tls_server_ctx(struct mosquitto__listener *listener) |
406 | 0 | { |
407 | 0 | char buf[256]; |
408 | 0 | int rc; |
409 | |
|
410 | 0 | if(listener->ssl_ctx){ |
411 | 0 | SSL_CTX_free(listener->ssl_ctx); |
412 | 0 | listener->ssl_ctx = NULL; |
413 | 0 | } |
414 | |
|
415 | 0 | listener->ssl_ctx = SSL_CTX_new(TLS_server_method()); |
416 | |
|
417 | 0 | if(!listener->ssl_ctx){ |
418 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to create TLS context."); |
419 | 0 | return MOSQ_ERR_TLS; |
420 | 0 | } |
421 | | |
422 | 0 | #ifdef SSL_OP_NO_TLSv1_3 |
423 | 0 | if(db.config->per_listener_settings){ |
424 | 0 | if(listener->security_options->psk_file){ |
425 | 0 | SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_TLSv1_3); |
426 | 0 | } |
427 | 0 | }else{ |
428 | 0 | if(db.config->security_options.psk_file){ |
429 | 0 | SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_TLSv1_3); |
430 | 0 | } |
431 | 0 | } |
432 | 0 | #endif |
433 | |
|
434 | 0 | if(listener->tls_version == NULL){ |
435 | 0 | SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); |
436 | 0 | #ifdef SSL_OP_NO_TLSv1_3 |
437 | 0 | }else if(!strcmp(listener->tls_version, "tlsv1.3")){ |
438 | 0 | SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2); |
439 | 0 | #endif |
440 | 0 | }else if(!strcmp(listener->tls_version, "tlsv1.2")){ |
441 | 0 | SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); |
442 | 0 | }else{ |
443 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unsupported tls_version \"%s\".", listener->tls_version); |
444 | 0 | return MOSQ_ERR_TLS; |
445 | 0 | } |
446 | | |
447 | 0 | #ifdef SSL_OP_NO_COMPRESSION |
448 | | /* Disable compression */ |
449 | 0 | SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_COMPRESSION); |
450 | 0 | #endif |
451 | 0 | #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE |
452 | | /* Server chooses cipher */ |
453 | 0 | SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); |
454 | 0 | #endif |
455 | |
|
456 | 0 | #ifdef SSL_MODE_RELEASE_BUFFERS |
457 | | /* Use even less memory per SSL connection. */ |
458 | 0 | SSL_CTX_set_mode(listener->ssl_ctx, SSL_MODE_RELEASE_BUFFERS); |
459 | 0 | #endif |
460 | |
|
461 | 0 | SSL_CTX_set_dh_auto(listener->ssl_ctx, 1); |
462 | |
|
463 | 0 | #ifdef SSL_OP_NO_RENEGOTIATION |
464 | 0 | SSL_CTX_set_options(listener->ssl_ctx, SSL_OP_NO_RENEGOTIATION); |
465 | 0 | #endif |
466 | |
|
467 | 0 | if(db.tls_keylog){ |
468 | 0 | log__printf(NULL, MOSQ_LOG_NOTICE, "TLS key logging to '%s' enabled for all listeners.", |
469 | 0 | db.tls_keylog); |
470 | 0 | log__printf(NULL, MOSQ_LOG_NOTICE, "TLS key logging is for DEBUGGING only."); |
471 | |
|
472 | 0 | SSL_CTX_set_keylog_callback(listener->ssl_ctx, tls_keylog_callback); |
473 | 0 | } |
474 | |
|
475 | 0 | snprintf(buf, 256, "mosquitto-%d", listener->port); |
476 | 0 | SSL_CTX_set_session_id_context(listener->ssl_ctx, (unsigned char *)buf, (unsigned int)strlen(buf)); |
477 | |
|
478 | 0 | if(listener->ciphers){ |
479 | 0 | rc = SSL_CTX_set_cipher_list(listener->ssl_ctx, listener->ciphers); |
480 | 0 | if(rc == 0){ |
481 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", listener->ciphers); |
482 | 0 | return MOSQ_ERR_TLS; |
483 | 0 | } |
484 | 0 | }else{ |
485 | 0 | rc = SSL_CTX_set_cipher_list(listener->ssl_ctx, "DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:@STRENGTH"); |
486 | 0 | if(rc == 0){ |
487 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set TLS ciphers. Check cipher list \"%s\".", listener->ciphers); |
488 | 0 | return MOSQ_ERR_TLS; |
489 | 0 | } |
490 | 0 | } |
491 | 0 | if(listener->ciphers_tls13){ |
492 | 0 | rc = SSL_CTX_set_ciphersuites(listener->ssl_ctx, listener->ciphers_tls13); |
493 | 0 | if(rc == 0){ |
494 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set TLS 1.3 ciphersuites. Check cipher_tls13 list \"%s\".", listener->ciphers_tls13); |
495 | 0 | return MOSQ_ERR_TLS; |
496 | 0 | } |
497 | 0 | } |
498 | | |
499 | 0 | return MOSQ_ERR_SUCCESS; |
500 | 0 | } |
501 | | #endif |
502 | | |
503 | | |
504 | | #ifdef WITH_TLS |
505 | | |
506 | | |
507 | | static int net__load_crl_file(struct mosquitto__listener *listener) |
508 | 0 | { |
509 | 0 | X509_STORE *store; |
510 | 0 | X509_LOOKUP *lookup; |
511 | 0 | int rc; |
512 | |
|
513 | 0 | store = SSL_CTX_get_cert_store(listener->ssl_ctx); |
514 | 0 | if(!store){ |
515 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to obtain TLS store."); |
516 | 0 | net__print_error(MOSQ_LOG_ERR, "Error: %s"); |
517 | 0 | return MOSQ_ERR_TLS; |
518 | 0 | } |
519 | 0 | lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); |
520 | 0 | rc = X509_load_crl_file(lookup, listener->crlfile, X509_FILETYPE_PEM); |
521 | 0 | if(rc < 1){ |
522 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load certificate revocation file \"%s\". Check crlfile.", listener->crlfile); |
523 | 0 | net__print_error(MOSQ_LOG_ERR, "Error: %s"); |
524 | 0 | net__print_ssl_error(NULL, NULL); |
525 | 0 | return MOSQ_ERR_TLS; |
526 | 0 | } |
527 | 0 | X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK); |
528 | |
|
529 | 0 | return MOSQ_ERR_SUCCESS; |
530 | 0 | } |
531 | | #endif |
532 | | |
533 | | |
534 | | int net__load_certificates(struct mosquitto__listener *listener) |
535 | 0 | { |
536 | 0 | #ifdef WITH_TLS |
537 | 0 | int rc; |
538 | |
|
539 | 0 | if(listener->require_certificate){ |
540 | 0 | SSL_CTX_set_verify(listener->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, client_certificate_verify); |
541 | 0 | }else{ |
542 | 0 | SSL_CTX_set_verify(listener->ssl_ctx, SSL_VERIFY_NONE, client_certificate_verify); |
543 | 0 | } |
544 | 0 | rc = SSL_CTX_use_certificate_chain_file(listener->ssl_ctx, listener->certfile); |
545 | 0 | if(rc != 1){ |
546 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load server certificate \"%s\". Check certfile.", listener->certfile); |
547 | 0 | net__print_ssl_error(NULL, NULL); |
548 | 0 | return MOSQ_ERR_TLS; |
549 | 0 | } |
550 | 0 | if(listener->tls_engine == NULL || listener->tls_keyform == mosq_k_pem){ |
551 | 0 | rc = SSL_CTX_use_PrivateKey_file(listener->ssl_ctx, listener->keyfile, SSL_FILETYPE_PEM); |
552 | 0 | if(rc != 1){ |
553 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load server key file \"%s\". Check keyfile.", listener->keyfile); |
554 | 0 | net__print_ssl_error(NULL, NULL); |
555 | 0 | return MOSQ_ERR_TLS; |
556 | 0 | } |
557 | 0 | } |
558 | 0 | rc = SSL_CTX_check_private_key(listener->ssl_ctx); |
559 | 0 | if(rc != 1){ |
560 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Server certificate/key are inconsistent."); |
561 | 0 | net__print_ssl_error(NULL, NULL); |
562 | 0 | return MOSQ_ERR_TLS; |
563 | 0 | } |
564 | | /* Load CRLs if they exist. */ |
565 | 0 | if(listener->crlfile){ |
566 | 0 | rc = net__load_crl_file(listener); |
567 | 0 | if(rc){ |
568 | 0 | return rc; |
569 | 0 | } |
570 | 0 | } |
571 | | #else |
572 | | UNUSED(listener); |
573 | | #endif |
574 | 0 | return MOSQ_ERR_SUCCESS; |
575 | 0 | } |
576 | | |
577 | | |
578 | | #if defined(WITH_TLS) && !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 |
579 | | |
580 | | |
581 | | static int net__load_engine(struct mosquitto__listener *listener) |
582 | 0 | { |
583 | 0 | ENGINE *engine = NULL; |
584 | 0 | UI_METHOD *ui_method; |
585 | 0 | EVP_PKEY *pkey; |
586 | |
|
587 | 0 | if(!listener->tls_engine){ |
588 | 0 | return MOSQ_ERR_SUCCESS; |
589 | 0 | } |
590 | | |
591 | 0 | engine = ENGINE_by_id(listener->tls_engine); |
592 | 0 | if(!engine){ |
593 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error loading %s engine\n", listener->tls_engine); |
594 | 0 | net__print_ssl_error(NULL, NULL); |
595 | 0 | return MOSQ_ERR_TLS; |
596 | 0 | } |
597 | 0 | if(!ENGINE_init(engine)){ |
598 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Failed engine initialisation\n"); |
599 | 0 | net__print_ssl_error(NULL, NULL); |
600 | 0 | return MOSQ_ERR_TLS; |
601 | 0 | } |
602 | 0 | ENGINE_set_default(engine, ENGINE_METHOD_ALL); |
603 | |
|
604 | 0 | if(listener->tls_keyform == mosq_k_engine){ |
605 | 0 | ui_method = net__get_ui_method(); |
606 | 0 | if(listener->tls_engine_kpass_sha1){ |
607 | 0 | if(!ENGINE_ctrl_cmd(engine, ENGINE_SECRET_MODE, ENGINE_SECRET_MODE_SHA, NULL, NULL, 0)){ |
608 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set engine secret mode sha"); |
609 | 0 | net__print_ssl_error(NULL, NULL); |
610 | 0 | return MOSQ_ERR_TLS; |
611 | 0 | } |
612 | 0 | if(!ENGINE_ctrl_cmd(engine, ENGINE_PIN, 0, listener->tls_engine_kpass_sha1, NULL, 0)){ |
613 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set engine pin"); |
614 | 0 | net__print_ssl_error(NULL, NULL); |
615 | 0 | return MOSQ_ERR_TLS; |
616 | 0 | } |
617 | 0 | ui_method = NULL; |
618 | 0 | } |
619 | 0 | pkey = ENGINE_load_private_key(engine, listener->keyfile, ui_method, NULL); |
620 | 0 | if(!pkey){ |
621 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load engine private key file \"%s\".", listener->keyfile); |
622 | 0 | net__print_ssl_error(NULL, NULL); |
623 | 0 | return MOSQ_ERR_TLS; |
624 | 0 | } |
625 | 0 | if(SSL_CTX_use_PrivateKey(listener->ssl_ctx, pkey) <= 0){ |
626 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to use engine private key file \"%s\".", listener->keyfile); |
627 | 0 | net__print_ssl_error(NULL, NULL); |
628 | 0 | return MOSQ_ERR_TLS; |
629 | 0 | } |
630 | 0 | } |
631 | 0 | ENGINE_free(engine); /* release the structural reference from ENGINE_by_id() */ |
632 | |
|
633 | 0 | return MOSQ_ERR_SUCCESS; |
634 | 0 | } |
635 | | #endif |
636 | | |
637 | | |
638 | | int net__tls_load_verify(struct mosquitto__listener *listener) |
639 | 0 | { |
640 | 0 | #ifdef WITH_TLS |
641 | 0 | int rc; |
642 | |
|
643 | 0 | # if OPENSSL_VERSION_NUMBER < 0x30000000L |
644 | 0 | if(listener->cafile || listener->capath){ |
645 | 0 | rc = SSL_CTX_load_verify_locations(listener->ssl_ctx, listener->cafile, listener->capath); |
646 | 0 | if(rc == 0){ |
647 | 0 | if(listener->cafile && listener->capath){ |
648 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check cafile \"%s\" and capath \"%s\".", listener->cafile, listener->capath); |
649 | 0 | }else if(listener->cafile){ |
650 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check cafile \"%s\".", listener->cafile); |
651 | 0 | }else{ |
652 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check capath \"%s\".", listener->capath); |
653 | 0 | } |
654 | 0 | } |
655 | 0 | } |
656 | | # else |
657 | | STACK_OF(X509_NAME) *ca_names = NULL; |
658 | | if(listener->cafile || listener->capath){ |
659 | | ca_names = sk_X509_NAME_new_null(); |
660 | | } |
661 | | |
662 | | if(listener->cafile){ |
663 | | rc = SSL_CTX_load_verify_file(listener->ssl_ctx, listener->cafile); |
664 | | if(rc == 0){ |
665 | | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check cafile \"%s\".", listener->cafile); |
666 | | net__print_ssl_error(NULL, NULL); |
667 | | return MOSQ_ERR_TLS; |
668 | | } |
669 | | |
670 | | STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(listener->cafile); |
671 | | if(cert_names){ |
672 | | for(int i=0; i<sk_X509_NAME_num(cert_names); i++){ |
673 | | sk_X509_NAME_push(ca_names, X509_NAME_dup(sk_X509_NAME_value(cert_names, i))); |
674 | | } |
675 | | sk_X509_NAME_free(cert_names); |
676 | | } |
677 | | |
678 | | } |
679 | | if(listener->capath){ |
680 | | rc = SSL_CTX_load_verify_dir(listener->ssl_ctx, listener->capath); |
681 | | if(rc == 0){ |
682 | | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to load CA certificates. Check capath \"%s\".", listener->capath); |
683 | | net__print_ssl_error(NULL, NULL); |
684 | | return MOSQ_ERR_TLS; |
685 | | } |
686 | | |
687 | | SSL_add_dir_cert_subjects_to_stack(ca_names, listener->capath); |
688 | | } |
689 | | if(ca_names){ |
690 | | SSL_CTX_set_client_CA_list(listener->ssl_ctx, ca_names); |
691 | | } |
692 | | # endif |
693 | |
|
694 | 0 | # if !defined(OPENSSL_NO_ENGINE) && OPENSSL_API_LEVEL < 30000 |
695 | 0 | if(net__load_engine(listener)){ |
696 | 0 | return MOSQ_ERR_TLS; |
697 | 0 | } |
698 | 0 | # endif |
699 | 0 | #endif |
700 | 0 | return net__load_certificates(listener); |
701 | 0 | } |
702 | | |
703 | | |
704 | | #if !defined(WIN32) && !defined(_AIX) |
705 | | |
706 | | |
707 | | static int net__bind_interface(struct mosquitto__listener *listener, struct addrinfo *rp) |
708 | 0 | { |
709 | | /* |
710 | | * This binds the listener sock to a network interface. |
711 | | * The use of SO_BINDTODEVICE requires root access, which we don't have, so instead |
712 | | * use getifaddrs to find the interface addresses, and use IP of the |
713 | | * matching interface in the later bind(). |
714 | | */ |
715 | 0 | struct ifaddrs *ifaddr; |
716 | 0 | bool have_interface = false; |
717 | |
|
718 | 0 | if(getifaddrs(&ifaddr) < 0){ |
719 | 0 | net__print_error(MOSQ_LOG_ERR, "Error: %s"); |
720 | 0 | return MOSQ_ERR_ERRNO; |
721 | 0 | } |
722 | | |
723 | 0 | for(struct ifaddrs *ifa=ifaddr; ifa!=NULL; ifa=ifa->ifa_next){ |
724 | 0 | if(ifa->ifa_addr == NULL){ |
725 | 0 | continue; |
726 | 0 | } |
727 | | |
728 | 0 | if(!strcasecmp(listener->bind_interface, ifa->ifa_name)){ |
729 | 0 | have_interface = true; |
730 | |
|
731 | 0 | if(ifa->ifa_addr->sa_family == rp->ai_addr->sa_family){ |
732 | 0 | if(rp->ai_addr->sa_family == AF_INET){ |
733 | 0 | if(listener->host && |
734 | 0 | memcmp(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, |
735 | 0 | &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, |
736 | 0 | sizeof(struct in_addr))){ |
737 | |
|
738 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface address for %s does not match specified listener address (%s).", |
739 | 0 | listener->bind_interface, listener->host); |
740 | 0 | return MOSQ_ERR_INVAL; |
741 | 0 | }else{ |
742 | 0 | memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr, |
743 | 0 | &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, |
744 | 0 | sizeof(struct in_addr)); |
745 | |
|
746 | 0 | freeifaddrs(ifaddr); |
747 | 0 | return MOSQ_ERR_SUCCESS; |
748 | 0 | } |
749 | 0 | }else if(rp->ai_addr->sa_family == AF_INET6){ |
750 | 0 | if(listener->host && |
751 | 0 | memcmp(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, |
752 | 0 | &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, |
753 | 0 | sizeof(struct in6_addr))){ |
754 | |
|
755 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface address for %s does not match specified listener address (%s).", |
756 | 0 | listener->bind_interface, listener->host); |
757 | 0 | return MOSQ_ERR_INVAL; |
758 | 0 | }else{ |
759 | 0 | memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, |
760 | 0 | &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, |
761 | 0 | sizeof(struct in6_addr)); |
762 | |
|
763 | 0 | ((struct sockaddr_in6 *)rp->ai_addr)->sin6_scope_id = ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id; |
764 | |
|
765 | 0 | freeifaddrs(ifaddr); |
766 | 0 | return MOSQ_ERR_SUCCESS; |
767 | 0 | } |
768 | 0 | } |
769 | 0 | } |
770 | 0 | } |
771 | 0 | } |
772 | 0 | freeifaddrs(ifaddr); |
773 | 0 | if(have_interface){ |
774 | 0 | log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Interface %s does not support %s configuration.", |
775 | 0 | listener->bind_interface, rp->ai_addr->sa_family == AF_INET ? "IPv4" : "IPv6"); |
776 | 0 | return MOSQ_ERR_NOT_SUPPORTED; |
777 | 0 | }else{ |
778 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface %s does not exist.", listener->bind_interface); |
779 | 0 | return MOSQ_ERR_NOT_FOUND; |
780 | 0 | } |
781 | 0 | } |
782 | | #endif |
783 | | |
784 | | |
785 | | static int net__socket_listen_tcp(struct mosquitto__listener *listener) |
786 | 0 | { |
787 | 0 | mosq_sock_t sock = INVALID_SOCKET; |
788 | 0 | struct addrinfo hints; |
789 | 0 | struct addrinfo *ainfo, *rp; |
790 | 0 | char service[10]; |
791 | 0 | int rc; |
792 | 0 | int ss_opt = 1; |
793 | 0 | #ifndef WIN32 |
794 | 0 | bool interface_bound = false; |
795 | 0 | #endif |
796 | |
|
797 | 0 | if(!listener){ |
798 | 0 | return MOSQ_ERR_INVAL; |
799 | 0 | } |
800 | | |
801 | 0 | snprintf(service, 10, "%d", listener->port); |
802 | 0 | memset(&hints, 0, sizeof(struct addrinfo)); |
803 | 0 | if(listener->socket_domain){ |
804 | 0 | hints.ai_family = listener->socket_domain; |
805 | 0 | }else{ |
806 | 0 | hints.ai_family = AF_UNSPEC; |
807 | 0 | } |
808 | 0 | hints.ai_flags = AI_PASSIVE; |
809 | 0 | hints.ai_socktype = SOCK_STREAM; |
810 | |
|
811 | 0 | rc = getaddrinfo(listener->host, service, &hints, &ainfo); |
812 | 0 | if(rc){ |
813 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error creating listener: %s.", gai_strerror(rc)); |
814 | 0 | return INVALID_SOCKET; |
815 | 0 | } |
816 | | |
817 | 0 | listener->sock_count = 0; |
818 | 0 | listener->socks = NULL; |
819 | |
|
820 | 0 | for(rp = ainfo; rp; rp = rp->ai_next){ |
821 | 0 | if(rp->ai_family == AF_INET){ |
822 | 0 | log__printf(NULL, MOSQ_LOG_INFO, "Opening ipv4 listen socket on port %d.", ntohs(((struct sockaddr_in *)rp->ai_addr)->sin_port)); |
823 | 0 | }else if(rp->ai_family == AF_INET6){ |
824 | 0 | log__printf(NULL, MOSQ_LOG_INFO, "Opening ipv6 listen socket on port %d.", ntohs(((struct sockaddr_in6 *)rp->ai_addr)->sin6_port)); |
825 | 0 | }else{ |
826 | 0 | continue; |
827 | 0 | } |
828 | | |
829 | 0 | sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); |
830 | 0 | if(sock == INVALID_SOCKET){ |
831 | 0 | net__print_error(MOSQ_LOG_WARNING, "Warning: %s"); |
832 | 0 | continue; |
833 | 0 | } |
834 | 0 | listener->sock_count++; |
835 | 0 | listener->socks = mosquitto_realloc(listener->socks, sizeof(mosq_sock_t)*(size_t)listener->sock_count); |
836 | 0 | if(!listener->socks){ |
837 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); |
838 | 0 | freeaddrinfo(ainfo); |
839 | 0 | COMPAT_CLOSE(sock); |
840 | 0 | return MOSQ_ERR_NOMEM; |
841 | 0 | } |
842 | 0 | listener->socks[listener->sock_count-1] = sock; |
843 | |
|
844 | 0 | #ifndef WIN32 |
845 | 0 | ss_opt = 1; |
846 | | /* Unimportant if this fails */ |
847 | 0 | (void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &ss_opt, sizeof(ss_opt)); |
848 | 0 | #endif |
849 | 0 | #ifdef IPV6_V6ONLY |
850 | 0 | ss_opt = 1; |
851 | 0 | (void)setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ss_opt, sizeof(ss_opt)); |
852 | 0 | #endif |
853 | |
|
854 | 0 | if(net__socket_nonblock(&sock)){ |
855 | 0 | freeaddrinfo(ainfo); |
856 | 0 | mosquitto_FREE(listener->socks); |
857 | 0 | return 1; |
858 | 0 | } |
859 | | |
860 | 0 | #if !defined(WIN32) && !defined(_AIX) |
861 | 0 | if(listener->bind_interface){ |
862 | | /* It might be possible that an interface does not support all relevant sa_families. |
863 | | * We should successfully find at least one. */ |
864 | 0 | rc = net__bind_interface(listener, rp); |
865 | 0 | if(rc){ |
866 | 0 | COMPAT_CLOSE(sock); |
867 | 0 | listener->sock_count--; |
868 | 0 | if(rc == MOSQ_ERR_NOT_FOUND || rc == MOSQ_ERR_INVAL){ |
869 | 0 | freeaddrinfo(ainfo); |
870 | 0 | return rc; |
871 | 0 | }else{ |
872 | 0 | continue; |
873 | 0 | } |
874 | 0 | } |
875 | 0 | interface_bound = true; |
876 | 0 | } |
877 | 0 | #endif |
878 | | |
879 | 0 | if(bind(sock, rp->ai_addr, rp->ai_addrlen) == -1){ |
880 | 0 | #if defined(__linux__) |
881 | 0 | if(errno == EACCES){ |
882 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "If you are trying to bind to a privileged port (<1024), try using setcap and do not start the broker as root:"); |
883 | 0 | log__printf(NULL, MOSQ_LOG_ERR, " sudo setcap 'CAP_NET_BIND_SERVICE=+ep /usr/sbin/mosquitto'"); |
884 | 0 | } |
885 | 0 | #endif |
886 | 0 | net__print_error(MOSQ_LOG_ERR, "Error: %s"); |
887 | 0 | COMPAT_CLOSE(sock); |
888 | 0 | freeaddrinfo(ainfo); |
889 | 0 | mosquitto_FREE(listener->socks); |
890 | 0 | return 1; |
891 | 0 | } |
892 | | |
893 | 0 | if(listen(sock, 100) == -1){ |
894 | 0 | net__print_error(MOSQ_LOG_ERR, "Error: %s"); |
895 | 0 | freeaddrinfo(ainfo); |
896 | 0 | COMPAT_CLOSE(sock); |
897 | 0 | mosquitto_FREE(listener->socks); |
898 | 0 | return 1; |
899 | 0 | } |
900 | 0 | } |
901 | 0 | freeaddrinfo(ainfo); |
902 | |
|
903 | 0 | #ifndef WIN32 |
904 | 0 | if(listener->bind_interface && !interface_bound){ |
905 | 0 | mosquitto_FREE(listener->socks); |
906 | 0 | return 1; |
907 | 0 | } |
908 | 0 | #endif |
909 | | |
910 | 0 | return 0; |
911 | 0 | } |
912 | | |
913 | | |
914 | | #ifdef WITH_UNIX_SOCKETS |
915 | | |
916 | | |
917 | | static int net__socket_listen_unix(struct mosquitto__listener *listener) |
918 | 0 | { |
919 | 0 | struct sockaddr_un addr; |
920 | 0 | int sock; |
921 | 0 | int rc; |
922 | 0 | mode_t old_mask; |
923 | |
|
924 | 0 | if(listener->unix_socket_path == NULL){ |
925 | 0 | return MOSQ_ERR_INVAL; |
926 | 0 | } |
927 | 0 | if(strlen(listener->unix_socket_path) > sizeof(addr.sun_path)-1){ |
928 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Path to unix socket is too long \"%s\".", listener->unix_socket_path); |
929 | 0 | return MOSQ_ERR_INVAL; |
930 | 0 | } |
931 | | |
932 | 0 | unlink(listener->unix_socket_path); |
933 | 0 | log__printf(NULL, MOSQ_LOG_INFO, "Opening unix listen socket on path %s.", listener->unix_socket_path); |
934 | 0 | memset(&addr, 0, sizeof(struct sockaddr_un)); |
935 | 0 | addr.sun_family = AF_UNIX; |
936 | 0 | strncpy(addr.sun_path, listener->unix_socket_path, sizeof(addr.sun_path)-1); |
937 | |
|
938 | 0 | sock = socket(AF_UNIX, SOCK_STREAM, 0); |
939 | 0 | if(sock == INVALID_SOCKET){ |
940 | 0 | net__print_error(MOSQ_LOG_ERR, "Error creating unix socket: %s"); |
941 | 0 | return 1; |
942 | 0 | } |
943 | 0 | listener->sock_count++; |
944 | 0 | listener->socks = mosquitto_realloc(listener->socks, sizeof(mosq_sock_t)*(size_t)listener->sock_count); |
945 | 0 | if(!listener->socks){ |
946 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); |
947 | 0 | COMPAT_CLOSE(sock); |
948 | 0 | return MOSQ_ERR_NOMEM; |
949 | 0 | } |
950 | 0 | listener->socks[listener->sock_count-1] = sock; |
951 | | |
952 | |
|
953 | 0 | old_mask = umask(0007); |
954 | 0 | rc = bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)); |
955 | 0 | umask(old_mask); |
956 | |
|
957 | 0 | if(rc == -1){ |
958 | 0 | net__print_error(MOSQ_LOG_ERR, "Error binding unix socket: %s"); |
959 | 0 | return 1; |
960 | 0 | } |
961 | | |
962 | 0 | if(listen(sock, 10) == -1){ |
963 | 0 | net__print_error(MOSQ_LOG_ERR, "Error listening to unix socket: %s"); |
964 | 0 | return 1; |
965 | 0 | } |
966 | | |
967 | 0 | if(net__socket_nonblock(&sock)){ |
968 | 0 | return 1; |
969 | 0 | } |
970 | | |
971 | 0 | return 0; |
972 | 0 | } |
973 | | #endif |
974 | | |
975 | | |
976 | | /* Creates a socket and listens on port 'port'. |
977 | | * Returns 1 on failure |
978 | | * Returns 0 on success. |
979 | | */ |
980 | | int net__socket_listen(struct mosquitto__listener *listener) |
981 | 0 | { |
982 | 0 | int rc; |
983 | |
|
984 | 0 | if(!listener){ |
985 | 0 | return MOSQ_ERR_INVAL; |
986 | 0 | } |
987 | | |
988 | 0 | #ifdef WITH_UNIX_SOCKETS |
989 | 0 | if(listener->port == 0 && listener->unix_socket_path != NULL){ |
990 | 0 | rc = net__socket_listen_unix(listener); |
991 | 0 | }else |
992 | 0 | #endif |
993 | 0 | { |
994 | 0 | rc = net__socket_listen_tcp(listener); |
995 | 0 | } |
996 | 0 | if(rc){ |
997 | 0 | return rc; |
998 | 0 | } |
999 | | |
1000 | | /* We need to have at least one working socket. */ |
1001 | 0 | if(listener->sock_count > 0){ |
1002 | 0 | #ifdef WITH_TLS |
1003 | 0 | if(listener->certfile && listener->keyfile){ |
1004 | 0 | if(net__tls_server_ctx(listener)){ |
1005 | 0 | return 1; |
1006 | 0 | } |
1007 | | |
1008 | 0 | if(net__tls_load_verify(listener)){ |
1009 | 0 | return 1; |
1010 | 0 | } |
1011 | 0 | } |
1012 | 0 | # ifdef FINAL_WITH_TLS_PSK |
1013 | 0 | if(listener->psk_hint){ |
1014 | 0 | if(listener->certfile == NULL || listener->keyfile == NULL){ |
1015 | 0 | if(net__tls_server_ctx(listener)){ |
1016 | 0 | return 1; |
1017 | 0 | } |
1018 | 0 | } |
1019 | 0 | SSL_CTX_set_psk_server_callback(listener->ssl_ctx, psk_server_callback); |
1020 | 0 | if(listener->psk_hint){ |
1021 | 0 | rc = SSL_CTX_use_psk_identity_hint(listener->ssl_ctx, listener->psk_hint); |
1022 | 0 | if(rc == 0){ |
1023 | 0 | log__printf(NULL, MOSQ_LOG_ERR, "Error: Unable to set TLS PSK hint."); |
1024 | 0 | net__print_ssl_error(NULL, NULL); |
1025 | 0 | return 1; |
1026 | 0 | } |
1027 | 0 | } |
1028 | 0 | } |
1029 | 0 | # endif /* FINAL_WITH_TLS_PSK */ |
1030 | 0 | if(tls_ex_index_context == -1){ |
1031 | 0 | tls_ex_index_context = SSL_get_ex_new_index(0, "client context", NULL, NULL, NULL); |
1032 | 0 | } |
1033 | 0 | if(tls_ex_index_listener == -1){ |
1034 | 0 | tls_ex_index_listener = SSL_get_ex_new_index(0, "listener", NULL, NULL, NULL); |
1035 | 0 | } |
1036 | 0 | #endif /* WITH_TLS */ |
1037 | 0 | return 0; |
1038 | 0 | }else{ |
1039 | 0 | return 1; |
1040 | 0 | } |
1041 | 0 | } |
1042 | | |
1043 | | |
1044 | | int net__socket_get_address(mosq_sock_t sock, char *buf, size_t len, uint16_t *remote_port) |
1045 | 0 | { |
1046 | 0 | struct sockaddr_storage addr; |
1047 | 0 | socklen_t addrlen; |
1048 | |
|
1049 | 0 | memset(&addr, 0, sizeof(struct sockaddr_storage)); |
1050 | 0 | addrlen = sizeof(addr); |
1051 | 0 | if(!getpeername(sock, (struct sockaddr *)&addr, &addrlen)){ |
1052 | 0 | if(addr.ss_family == AF_INET){ |
1053 | 0 | if(remote_port){ |
1054 | 0 | *remote_port = ntohs(((struct sockaddr_in *)&addr)->sin_port); |
1055 | 0 | } |
1056 | 0 | if(inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr.s_addr, buf, (socklen_t)len)){ |
1057 | 0 | return 0; |
1058 | 0 | } |
1059 | 0 | }else if(addr.ss_family == AF_INET6){ |
1060 | 0 | if(remote_port){ |
1061 | 0 | *remote_port = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port); |
1062 | 0 | } |
1063 | 0 | if(inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr.s6_addr, buf, (socklen_t)len)){ |
1064 | 0 | return 0; |
1065 | 0 | } |
1066 | 0 | #ifdef WITH_UNIX_SOCKETS |
1067 | 0 | }else if(addr.ss_family == AF_UNIX){ |
1068 | 0 | struct sockaddr_un un; |
1069 | 0 | addrlen = sizeof(struct sockaddr_un); |
1070 | 0 | if(!getsockname(sock, (struct sockaddr *)&un, &addrlen)){ |
1071 | 0 | snprintf(buf, len, "%s", un.sun_path); |
1072 | 0 | }else{ |
1073 | 0 | snprintf(buf, len, "unix-socket"); |
1074 | 0 | } |
1075 | 0 | return 0; |
1076 | 0 | #endif |
1077 | 0 | } |
1078 | 0 | } |
1079 | 0 | return 1; |
1080 | 0 | } |