util_mosq.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. Copyright (c) 2009-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. #include <assert.h>
  16. #include <ctype.h>
  17. #include <string.h>
  18. #ifdef WIN32
  19. # include <winsock2.h>
  20. # include <aclapi.h>
  21. # include <io.h>
  22. # include <lmcons.h>
  23. #else
  24. # include <sys/stat.h>
  25. #endif
  26. #if !defined(WITH_TLS) && defined(__linux__) && defined(__GLIBC__)
  27. # if __GLIBC_PREREQ(2, 25)
  28. # include <sys/random.h>
  29. # define HAVE_GETRANDOM 1
  30. # endif
  31. #endif
  32. #ifdef WITH_TLS
  33. # include <openssl/bn.h>
  34. # include <openssl/rand.h>
  35. #endif
  36. #ifdef WITH_BROKER
  37. #include "mosquitto_broker_internal.h"
  38. #endif
  39. #include "mosquitto.h"
  40. #include "memory_mosq.h"
  41. #include "net_mosq.h"
  42. #include "send_mosq.h"
  43. #include "time_mosq.h"
  44. #include "tls_mosq.h"
  45. #include "util_mosq.h"
  46. #ifdef WITH_WEBSOCKETS
  47. #include <libwebsockets.h>
  48. #endif
  49. int mosquitto__check_keepalive(struct mosquitto *mosq)
  50. {
  51. time_t next_msg_out;
  52. time_t last_msg_in;
  53. time_t now;
  54. #ifndef WITH_BROKER
  55. int rc;
  56. #endif
  57. enum mosquitto_client_state state;
  58. assert(mosq);
  59. #ifdef WITH_BROKER
  60. now = db.now_s;
  61. #else
  62. now = mosquitto_time();
  63. #endif
  64. #if defined(WITH_BROKER) && defined(WITH_BRIDGE)
  65. /* Check if a lazy bridge should be timed out due to idle. */
  66. if(mosq->bridge && mosq->bridge->start_type == bst_lazy
  67. && mosq->sock != INVALID_SOCKET
  68. && now - mosq->next_msg_out - mosq->keepalive >= mosq->bridge->idle_timeout){
  69. log__printf(NULL, MOSQ_LOG_NOTICE, "Bridge connection %s has exceeded idle timeout, disconnecting.", mosq->id);
  70. net__socket_close(mosq);
  71. return MOSQ_ERR_SUCCESS;
  72. }
  73. #endif
  74. pthread_mutex_lock(&mosq->msgtime_mutex);
  75. next_msg_out = mosq->next_msg_out;
  76. last_msg_in = mosq->last_msg_in;
  77. pthread_mutex_unlock(&mosq->msgtime_mutex);
  78. if(mosq->keepalive && mosq->sock != INVALID_SOCKET &&
  79. (now >= next_msg_out || now - last_msg_in >= mosq->keepalive)){
  80. state = mosquitto__get_state(mosq);
  81. if(state == mosq_cs_active && mosq->ping_t == 0){
  82. send__pingreq(mosq);
  83. /* Reset last msg times to give the server time to send a pingresp */
  84. pthread_mutex_lock(&mosq->msgtime_mutex);
  85. mosq->last_msg_in = now;
  86. mosq->next_msg_out = now + mosq->keepalive;
  87. pthread_mutex_unlock(&mosq->msgtime_mutex);
  88. }else{
  89. #ifdef WITH_BROKER
  90. net__socket_close(mosq);
  91. #else
  92. net__socket_close(mosq);
  93. state = mosquitto__get_state(mosq);
  94. if(state == mosq_cs_disconnecting){
  95. rc = MOSQ_ERR_SUCCESS;
  96. }else{
  97. rc = MOSQ_ERR_KEEPALIVE;
  98. }
  99. pthread_mutex_lock(&mosq->callback_mutex);
  100. if(mosq->on_disconnect){
  101. mosq->in_callback = true;
  102. mosq->on_disconnect(mosq, mosq->userdata, rc);
  103. mosq->in_callback = false;
  104. }
  105. if(mosq->on_disconnect_v5){
  106. mosq->in_callback = true;
  107. mosq->on_disconnect_v5(mosq, mosq->userdata, rc, NULL);
  108. mosq->in_callback = false;
  109. }
  110. pthread_mutex_unlock(&mosq->callback_mutex);
  111. return rc;
  112. #endif
  113. }
  114. }
  115. return MOSQ_ERR_SUCCESS;
  116. }
  117. uint16_t mosquitto__mid_generate(struct mosquitto *mosq)
  118. {
  119. /* FIXME - this would be better with atomic increment, but this is safer
  120. * for now for a bug fix release.
  121. *
  122. * If this is changed to use atomic increment, callers of this function
  123. * will have to be aware that they may receive a 0 result, which may not be
  124. * used as a mid.
  125. */
  126. uint16_t mid;
  127. assert(mosq);
  128. pthread_mutex_lock(&mosq->mid_mutex);
  129. mosq->last_mid++;
  130. if(mosq->last_mid == 0) mosq->last_mid++;
  131. mid = mosq->last_mid;
  132. pthread_mutex_unlock(&mosq->mid_mutex);
  133. return mid;
  134. }
  135. #ifdef WITH_TLS
  136. int mosquitto__hex2bin_sha1(const char *hex, unsigned char **bin)
  137. {
  138. unsigned char *sha, tmp[SHA_DIGEST_LENGTH];
  139. if(mosquitto__hex2bin(hex, tmp, SHA_DIGEST_LENGTH) != SHA_DIGEST_LENGTH){
  140. return MOSQ_ERR_INVAL;
  141. }
  142. sha = mosquitto__malloc(SHA_DIGEST_LENGTH);
  143. if(!sha){
  144. return MOSQ_ERR_NOMEM;
  145. }
  146. memcpy(sha, tmp, SHA_DIGEST_LENGTH);
  147. *bin = sha;
  148. return MOSQ_ERR_SUCCESS;
  149. }
  150. int mosquitto__hex2bin(const char *hex, unsigned char *bin, int bin_max_len)
  151. {
  152. BIGNUM *bn = NULL;
  153. int len;
  154. int leading_zero = 0;
  155. int start = 0;
  156. size_t i = 0;
  157. /* Count the number of leading zero */
  158. for(i=0; i<strlen(hex); i=i+2) {
  159. if(strncmp(hex + i, "00", 2) == 0) {
  160. leading_zero++;
  161. /* output leading zero to bin */
  162. bin[start++] = 0;
  163. }else{
  164. break;
  165. }
  166. }
  167. if(BN_hex2bn(&bn, hex) == 0){
  168. if(bn) BN_free(bn);
  169. return 0;
  170. }
  171. if(BN_num_bytes(bn) + leading_zero > bin_max_len){
  172. BN_free(bn);
  173. return 0;
  174. }
  175. len = BN_bn2bin(bn, bin + leading_zero);
  176. BN_free(bn);
  177. return len + leading_zero;
  178. }
  179. #endif
  180. void util__increment_receive_quota(struct mosquitto *mosq)
  181. {
  182. if(mosq->msgs_in.inflight_quota < mosq->msgs_in.inflight_maximum){
  183. mosq->msgs_in.inflight_quota++;
  184. }
  185. }
  186. void util__increment_send_quota(struct mosquitto *mosq)
  187. {
  188. if(mosq->msgs_out.inflight_quota < mosq->msgs_out.inflight_maximum){
  189. mosq->msgs_out.inflight_quota++;
  190. }
  191. }
  192. void util__decrement_receive_quota(struct mosquitto *mosq)
  193. {
  194. if(mosq->msgs_in.inflight_quota > 0){
  195. mosq->msgs_in.inflight_quota--;
  196. }
  197. }
  198. void util__decrement_send_quota(struct mosquitto *mosq)
  199. {
  200. if(mosq->msgs_out.inflight_quota > 0){
  201. mosq->msgs_out.inflight_quota--;
  202. }
  203. }
  204. int util__random_bytes(void *bytes, int count)
  205. {
  206. int rc = MOSQ_ERR_UNKNOWN;
  207. #ifdef WITH_TLS
  208. if(RAND_bytes(bytes, count) == 1){
  209. rc = MOSQ_ERR_SUCCESS;
  210. }
  211. #elif defined(HAVE_GETRANDOM)
  212. if(getrandom(bytes, (size_t)count, 0) == count){
  213. rc = MOSQ_ERR_SUCCESS;
  214. }
  215. #elif defined(WIN32)
  216. HCRYPTPROV provider;
  217. if(!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)){
  218. return MOSQ_ERR_UNKNOWN;
  219. }
  220. if(CryptGenRandom(provider, count, bytes)){
  221. rc = MOSQ_ERR_SUCCESS;
  222. }
  223. CryptReleaseContext(provider, 0);
  224. #else
  225. int i;
  226. for(i=0; i<count; i++){
  227. ((uint8_t *)bytes)[i] = (uint8_t )(random()&0xFF);
  228. }
  229. rc = MOSQ_ERR_SUCCESS;
  230. #endif
  231. return rc;
  232. }
  233. int mosquitto__set_state(struct mosquitto *mosq, enum mosquitto_client_state state)
  234. {
  235. pthread_mutex_lock(&mosq->state_mutex);
  236. #ifdef WITH_BROKER
  237. if(mosq->state != mosq_cs_disused)
  238. #endif
  239. {
  240. mosq->state = state;
  241. }
  242. pthread_mutex_unlock(&mosq->state_mutex);
  243. return MOSQ_ERR_SUCCESS;
  244. }
  245. enum mosquitto_client_state mosquitto__get_state(struct mosquitto *mosq)
  246. {
  247. enum mosquitto_client_state state;
  248. pthread_mutex_lock(&mosq->state_mutex);
  249. state = mosq->state;
  250. pthread_mutex_unlock(&mosq->state_mutex);
  251. return state;
  252. }