options.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /*
  2. Copyright (c) 2010-2020 Roger Light <roger@atchoo.org>
  3. All rights reserved. This program and the accompanying materials
  4. are made available under the terms of the Eclipse Public License 2.0
  5. and Eclipse Distribution License v1.0 which accompany this distribution.
  6. The Eclipse Public License is available at
  7. https://www.eclipse.org/legal/epl-2.0/
  8. and the Eclipse Distribution License is available at
  9. http://www.eclipse.org/org/documents/edl-v10.php.
  10. SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
  11. Contributors:
  12. Roger Light - initial implementation and documentation.
  13. */
  14. #include "config.h"
  15. #ifndef WIN32
  16. # include <strings.h>
  17. #endif
  18. #include <string.h>
  19. #ifdef WITH_TLS
  20. # ifdef WIN32
  21. # include <winsock2.h>
  22. # endif
  23. # include <openssl/engine.h>
  24. #endif
  25. #include "mosquitto.h"
  26. #include "mosquitto_internal.h"
  27. #include "memory_mosq.h"
  28. #include "misc_mosq.h"
  29. #include "mqtt_protocol.h"
  30. #include "util_mosq.h"
  31. #include "will_mosq.h"
  32. int mosquitto_will_set(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain)
  33. {
  34. return mosquitto_will_set_v5(mosq, topic, payloadlen, payload, qos, retain, NULL);
  35. }
  36. int mosquitto_will_set_v5(struct mosquitto *mosq, const char *topic, int payloadlen, const void *payload, int qos, bool retain, mosquitto_property *properties)
  37. {
  38. int rc;
  39. if(!mosq) return MOSQ_ERR_INVAL;
  40. if(properties){
  41. rc = mosquitto_property_check_all(CMD_WILL, properties);
  42. if(rc) return rc;
  43. }
  44. return will__set(mosq, topic, payloadlen, payload, qos, retain, properties);
  45. }
  46. int mosquitto_will_clear(struct mosquitto *mosq)
  47. {
  48. if(!mosq) return MOSQ_ERR_INVAL;
  49. return will__clear(mosq);
  50. }
  51. int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password)
  52. {
  53. size_t slen;
  54. if(!mosq) return MOSQ_ERR_INVAL;
  55. if(mosq->protocol == mosq_p_mqtt311 || mosq->protocol == mosq_p_mqtt31){
  56. if(password != NULL && username == NULL){
  57. return MOSQ_ERR_INVAL;
  58. }
  59. }
  60. mosquitto__free(mosq->username);
  61. mosq->username = NULL;
  62. mosquitto__free(mosq->password);
  63. mosq->password = NULL;
  64. if(username){
  65. slen = strlen(username);
  66. if(slen > UINT16_MAX){
  67. return MOSQ_ERR_INVAL;
  68. }
  69. if(mosquitto_validate_utf8(username, (int)slen)){
  70. return MOSQ_ERR_MALFORMED_UTF8;
  71. }
  72. mosq->username = mosquitto__strdup(username);
  73. if(!mosq->username) return MOSQ_ERR_NOMEM;
  74. }
  75. if(password){
  76. mosq->password = mosquitto__strdup(password);
  77. if(!mosq->password){
  78. mosquitto__free(mosq->username);
  79. mosq->username = NULL;
  80. return MOSQ_ERR_NOMEM;
  81. }
  82. }
  83. return MOSQ_ERR_SUCCESS;
  84. }
  85. int mosquitto_reconnect_delay_set(struct mosquitto *mosq, unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff)
  86. {
  87. if(!mosq) return MOSQ_ERR_INVAL;
  88. if(reconnect_delay == 0) reconnect_delay = 1;
  89. mosq->reconnect_delay = reconnect_delay;
  90. mosq->reconnect_delay_max = reconnect_delay_max;
  91. mosq->reconnect_exponential_backoff = reconnect_exponential_backoff;
  92. return MOSQ_ERR_SUCCESS;
  93. }
  94. int mosquitto_tls_set(struct mosquitto *mosq, const char *cafile, const char *capath, const char *certfile, const char *keyfile, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata))
  95. {
  96. #ifdef WITH_TLS
  97. FILE *fptr;
  98. if(!mosq || (!cafile && !capath) || (certfile && !keyfile) || (!certfile && keyfile)) return MOSQ_ERR_INVAL;
  99. mosquitto__free(mosq->tls_cafile);
  100. mosq->tls_cafile = NULL;
  101. if(cafile){
  102. fptr = mosquitto__fopen(cafile, "rt", false);
  103. if(fptr){
  104. fclose(fptr);
  105. }else{
  106. return MOSQ_ERR_INVAL;
  107. }
  108. mosq->tls_cafile = mosquitto__strdup(cafile);
  109. if(!mosq->tls_cafile){
  110. return MOSQ_ERR_NOMEM;
  111. }
  112. }
  113. mosquitto__free(mosq->tls_capath);
  114. mosq->tls_capath = NULL;
  115. if(capath){
  116. mosq->tls_capath = mosquitto__strdup(capath);
  117. if(!mosq->tls_capath){
  118. return MOSQ_ERR_NOMEM;
  119. }
  120. }
  121. mosquitto__free(mosq->tls_certfile);
  122. mosq->tls_certfile = NULL;
  123. if(certfile){
  124. fptr = mosquitto__fopen(certfile, "rt", false);
  125. if(fptr){
  126. fclose(fptr);
  127. }else{
  128. mosquitto__free(mosq->tls_cafile);
  129. mosq->tls_cafile = NULL;
  130. mosquitto__free(mosq->tls_capath);
  131. mosq->tls_capath = NULL;
  132. return MOSQ_ERR_INVAL;
  133. }
  134. mosq->tls_certfile = mosquitto__strdup(certfile);
  135. if(!mosq->tls_certfile){
  136. return MOSQ_ERR_NOMEM;
  137. }
  138. }
  139. mosquitto__free(mosq->tls_keyfile);
  140. mosq->tls_keyfile = NULL;
  141. if(keyfile){
  142. fptr = mosquitto__fopen(keyfile, "rt", false);
  143. if(fptr){
  144. fclose(fptr);
  145. }else{
  146. mosquitto__free(mosq->tls_cafile);
  147. mosq->tls_cafile = NULL;
  148. mosquitto__free(mosq->tls_capath);
  149. mosq->tls_capath = NULL;
  150. mosquitto__free(mosq->tls_certfile);
  151. mosq->tls_certfile = NULL;
  152. return MOSQ_ERR_INVAL;
  153. }
  154. mosq->tls_keyfile = mosquitto__strdup(keyfile);
  155. if(!mosq->tls_keyfile){
  156. return MOSQ_ERR_NOMEM;
  157. }
  158. }
  159. mosq->tls_pw_callback = pw_callback;
  160. return MOSQ_ERR_SUCCESS;
  161. #else
  162. UNUSED(mosq);
  163. UNUSED(cafile);
  164. UNUSED(capath);
  165. UNUSED(certfile);
  166. UNUSED(keyfile);
  167. UNUSED(pw_callback);
  168. return MOSQ_ERR_NOT_SUPPORTED;
  169. #endif
  170. }
  171. int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers)
  172. {
  173. #ifdef WITH_TLS
  174. if(!mosq) return MOSQ_ERR_INVAL;
  175. mosq->tls_cert_reqs = cert_reqs;
  176. if(tls_version){
  177. if(!strcasecmp(tls_version, "tlsv1.3")
  178. || !strcasecmp(tls_version, "tlsv1.2")
  179. || !strcasecmp(tls_version, "tlsv1.1")){
  180. mosq->tls_version = mosquitto__strdup(tls_version);
  181. if(!mosq->tls_version) return MOSQ_ERR_NOMEM;
  182. }else{
  183. return MOSQ_ERR_INVAL;
  184. }
  185. }else{
  186. mosq->tls_version = mosquitto__strdup("tlsv1.2");
  187. if(!mosq->tls_version) return MOSQ_ERR_NOMEM;
  188. }
  189. if(ciphers){
  190. mosq->tls_ciphers = mosquitto__strdup(ciphers);
  191. if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM;
  192. }else{
  193. mosq->tls_ciphers = NULL;
  194. }
  195. return MOSQ_ERR_SUCCESS;
  196. #else
  197. UNUSED(mosq);
  198. UNUSED(cert_reqs);
  199. UNUSED(tls_version);
  200. UNUSED(ciphers);
  201. return MOSQ_ERR_NOT_SUPPORTED;
  202. #endif
  203. }
  204. int mosquitto_tls_insecure_set(struct mosquitto *mosq, bool value)
  205. {
  206. #ifdef WITH_TLS
  207. if(!mosq) return MOSQ_ERR_INVAL;
  208. mosq->tls_insecure = value;
  209. return MOSQ_ERR_SUCCESS;
  210. #else
  211. UNUSED(mosq);
  212. UNUSED(value);
  213. return MOSQ_ERR_NOT_SUPPORTED;
  214. #endif
  215. }
  216. int mosquitto_string_option(struct mosquitto *mosq, enum mosq_opt_t option, const char *value)
  217. {
  218. #ifdef WITH_TLS
  219. ENGINE *eng;
  220. char *str;
  221. #endif
  222. if(!mosq) return MOSQ_ERR_INVAL;
  223. switch(option){
  224. case MOSQ_OPT_TLS_ENGINE:
  225. #if defined(WITH_TLS) && !defined(OPENSSL_NO_ENGINE)
  226. eng = ENGINE_by_id(value);
  227. if(!eng){
  228. return MOSQ_ERR_INVAL;
  229. }
  230. ENGINE_free(eng); /* release the structural reference from ENGINE_by_id() */
  231. mosq->tls_engine = mosquitto__strdup(value);
  232. if(!mosq->tls_engine){
  233. return MOSQ_ERR_NOMEM;
  234. }
  235. return MOSQ_ERR_SUCCESS;
  236. #else
  237. return MOSQ_ERR_NOT_SUPPORTED;
  238. #endif
  239. break;
  240. case MOSQ_OPT_TLS_KEYFORM:
  241. #ifdef WITH_TLS
  242. if(!value) return MOSQ_ERR_INVAL;
  243. if(!strcasecmp(value, "pem")){
  244. mosq->tls_keyform = mosq_k_pem;
  245. }else if (!strcasecmp(value, "engine")){
  246. mosq->tls_keyform = mosq_k_engine;
  247. }else{
  248. return MOSQ_ERR_INVAL;
  249. }
  250. return MOSQ_ERR_SUCCESS;
  251. #else
  252. return MOSQ_ERR_NOT_SUPPORTED;
  253. #endif
  254. break;
  255. case MOSQ_OPT_TLS_ENGINE_KPASS_SHA1:
  256. #ifdef WITH_TLS
  257. if(mosquitto__hex2bin_sha1(value, (unsigned char**)&str) != MOSQ_ERR_SUCCESS){
  258. return MOSQ_ERR_INVAL;
  259. }
  260. mosq->tls_engine_kpass_sha1 = str;
  261. return MOSQ_ERR_SUCCESS;
  262. #else
  263. return MOSQ_ERR_NOT_SUPPORTED;
  264. #endif
  265. break;
  266. case MOSQ_OPT_TLS_ALPN:
  267. #ifdef WITH_TLS
  268. mosq->tls_alpn = mosquitto__strdup(value);
  269. if(!mosq->tls_alpn){
  270. return MOSQ_ERR_NOMEM;
  271. }
  272. return MOSQ_ERR_SUCCESS;
  273. #else
  274. return MOSQ_ERR_NOT_SUPPORTED;
  275. #endif
  276. break;
  277. case MOSQ_OPT_BIND_ADDRESS:
  278. mosquitto__free(mosq->bind_address);
  279. if(value){
  280. mosq->bind_address = mosquitto__strdup(value);
  281. if(mosq->bind_address){
  282. return MOSQ_ERR_SUCCESS;
  283. }else{
  284. return MOSQ_ERR_NOMEM;
  285. }
  286. }else{
  287. return MOSQ_ERR_SUCCESS;
  288. }
  289. default:
  290. return MOSQ_ERR_INVAL;
  291. }
  292. }
  293. int mosquitto_tls_psk_set(struct mosquitto *mosq, const char *psk, const char *identity, const char *ciphers)
  294. {
  295. #ifdef FINAL_WITH_TLS_PSK
  296. if(!mosq || !psk || !identity) return MOSQ_ERR_INVAL;
  297. /* Check for hex only digits */
  298. if(strspn(psk, "0123456789abcdefABCDEF") < strlen(psk)){
  299. return MOSQ_ERR_INVAL;
  300. }
  301. mosq->tls_psk = mosquitto__strdup(psk);
  302. if(!mosq->tls_psk) return MOSQ_ERR_NOMEM;
  303. mosq->tls_psk_identity = mosquitto__strdup(identity);
  304. if(!mosq->tls_psk_identity){
  305. mosquitto__free(mosq->tls_psk);
  306. return MOSQ_ERR_NOMEM;
  307. }
  308. if(ciphers){
  309. mosq->tls_ciphers = mosquitto__strdup(ciphers);
  310. if(!mosq->tls_ciphers) return MOSQ_ERR_NOMEM;
  311. }else{
  312. mosq->tls_ciphers = NULL;
  313. }
  314. return MOSQ_ERR_SUCCESS;
  315. #else
  316. UNUSED(mosq);
  317. UNUSED(psk);
  318. UNUSED(identity);
  319. UNUSED(ciphers);
  320. return MOSQ_ERR_NOT_SUPPORTED;
  321. #endif
  322. }
  323. int mosquitto_opts_set(struct mosquitto *mosq, enum mosq_opt_t option, void *value)
  324. {
  325. int ival;
  326. if(!mosq) return MOSQ_ERR_INVAL;
  327. switch(option){
  328. case MOSQ_OPT_PROTOCOL_VERSION:
  329. if(value == NULL){
  330. return MOSQ_ERR_INVAL;
  331. }
  332. ival = *((int *)value);
  333. return mosquitto_int_option(mosq, option, ival);
  334. case MOSQ_OPT_SSL_CTX:
  335. return mosquitto_void_option(mosq, option, value);
  336. default:
  337. return MOSQ_ERR_INVAL;
  338. }
  339. return MOSQ_ERR_SUCCESS;
  340. }
  341. int mosquitto_int_option(struct mosquitto *mosq, enum mosq_opt_t option, int value)
  342. {
  343. if(!mosq) return MOSQ_ERR_INVAL;
  344. switch(option){
  345. case MOSQ_OPT_PROTOCOL_VERSION:
  346. if(value == MQTT_PROTOCOL_V31){
  347. mosq->protocol = mosq_p_mqtt31;
  348. }else if(value == MQTT_PROTOCOL_V311){
  349. mosq->protocol = mosq_p_mqtt311;
  350. }else if(value == MQTT_PROTOCOL_V5){
  351. mosq->protocol = mosq_p_mqtt5;
  352. }else{
  353. return MOSQ_ERR_INVAL;
  354. }
  355. break;
  356. case MOSQ_OPT_RECEIVE_MAXIMUM:
  357. if(value < 0 || value > UINT16_MAX){
  358. return MOSQ_ERR_INVAL;
  359. }
  360. if(value == 0){
  361. mosq->msgs_in.inflight_maximum = UINT16_MAX;
  362. }else{
  363. mosq->msgs_in.inflight_maximum = (uint16_t)value;
  364. }
  365. break;
  366. case MOSQ_OPT_SEND_MAXIMUM:
  367. if(value < 0 || value > UINT16_MAX){
  368. return MOSQ_ERR_INVAL;
  369. }
  370. if(value == 0){
  371. mosq->msgs_out.inflight_maximum = UINT16_MAX;
  372. }else{
  373. mosq->msgs_out.inflight_maximum = (uint16_t)value;
  374. }
  375. break;
  376. case MOSQ_OPT_SSL_CTX_WITH_DEFAULTS:
  377. #if defined(WITH_TLS) && OPENSSL_VERSION_NUMBER >= 0x10100000L
  378. if(value){
  379. mosq->ssl_ctx_defaults = true;
  380. }else{
  381. mosq->ssl_ctx_defaults = false;
  382. }
  383. break;
  384. #else
  385. return MOSQ_ERR_NOT_SUPPORTED;
  386. #endif
  387. case MOSQ_OPT_TLS_USE_OS_CERTS:
  388. #ifdef WITH_TLS
  389. if(value){
  390. mosq->tls_use_os_certs = true;
  391. }else{
  392. mosq->tls_use_os_certs = false;
  393. }
  394. break;
  395. #else
  396. return MOSQ_ERR_NOT_SUPPORTED;
  397. #endif
  398. case MOSQ_OPT_TLS_OCSP_REQUIRED:
  399. #ifdef WITH_TLS
  400. mosq->tls_ocsp_required = (bool)value;
  401. #else
  402. return MOSQ_ERR_NOT_SUPPORTED;
  403. #endif
  404. break;
  405. case MOSQ_OPT_TCP_NODELAY:
  406. mosq->tcp_nodelay = (bool)value;
  407. break;
  408. default:
  409. return MOSQ_ERR_INVAL;
  410. }
  411. return MOSQ_ERR_SUCCESS;
  412. }
  413. int mosquitto_void_option(struct mosquitto *mosq, enum mosq_opt_t option, void *value)
  414. {
  415. if(!mosq) return MOSQ_ERR_INVAL;
  416. switch(option){
  417. case MOSQ_OPT_SSL_CTX:
  418. #ifdef WITH_TLS
  419. mosq->user_ssl_ctx = (SSL_CTX *)value;
  420. if(mosq->user_ssl_ctx){
  421. #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  422. SSL_CTX_up_ref(mosq->user_ssl_ctx);
  423. #else
  424. CRYPTO_add(&(mosq->user_ssl_ctx)->references, 1, CRYPTO_LOCK_SSL_CTX);
  425. #endif
  426. }
  427. break;
  428. #else
  429. return MOSQ_ERR_NOT_SUPPORTED;
  430. #endif
  431. default:
  432. return MOSQ_ERR_INVAL;
  433. }
  434. return MOSQ_ERR_SUCCESS;
  435. }
  436. void mosquitto_user_data_set(struct mosquitto *mosq, void *userdata)
  437. {
  438. if(mosq){
  439. mosq->userdata = userdata;
  440. }
  441. }
  442. void *mosquitto_userdata(struct mosquitto *mosq)
  443. {
  444. return mosq->userdata;
  445. }