handshake.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. *
  3. * Copyright 2015, Google Inc.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of Google Inc. nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. */
  33. #include "src/core/lib/security/transport/handshake.h"
  34. #include <stdbool.h>
  35. #include <string.h>
  36. #include <grpc/support/alloc.h>
  37. #include <grpc/support/log.h>
  38. #include <grpc/support/slice_buffer.h>
  39. #include "src/core/lib/security/context/security_context.h"
  40. #include "src/core/lib/security/transport/secure_endpoint.h"
  41. #include "src/core/lib/security/transport/tsi_error.h"
  42. #define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256
  43. typedef struct {
  44. grpc_security_connector *connector;
  45. tsi_handshaker *handshaker;
  46. bool is_client_side;
  47. unsigned char *handshake_buffer;
  48. size_t handshake_buffer_size;
  49. grpc_endpoint *wrapped_endpoint;
  50. grpc_endpoint *secure_endpoint;
  51. gpr_slice_buffer left_overs;
  52. gpr_slice_buffer incoming;
  53. gpr_slice_buffer outgoing;
  54. grpc_security_handshake_done_cb cb;
  55. void *user_data;
  56. grpc_closure on_handshake_data_sent_to_peer;
  57. grpc_closure on_handshake_data_received_from_peer;
  58. grpc_auth_context *auth_context;
  59. } grpc_security_handshake;
  60. static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
  61. void *setup,
  62. grpc_error *error);
  63. static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup,
  64. grpc_error *error);
  65. static void security_connector_remove_handshake(grpc_security_handshake *h) {
  66. GPR_ASSERT(!h->is_client_side);
  67. grpc_security_connector_handshake_list *node;
  68. grpc_security_connector_handshake_list *tmp;
  69. grpc_server_security_connector *sc =
  70. (grpc_server_security_connector *)h->connector;
  71. gpr_mu_lock(&sc->mu);
  72. node = sc->handshaking_handshakes;
  73. if (node && node->handshake == h) {
  74. sc->handshaking_handshakes = node->next;
  75. gpr_free(node);
  76. gpr_mu_unlock(&sc->mu);
  77. return;
  78. }
  79. while (node) {
  80. if (node->next->handshake == h) {
  81. tmp = node->next;
  82. node->next = node->next->next;
  83. gpr_free(tmp);
  84. gpr_mu_unlock(&sc->mu);
  85. return;
  86. }
  87. node = node->next;
  88. }
  89. gpr_mu_unlock(&sc->mu);
  90. }
  91. static void security_handshake_done(grpc_exec_ctx *exec_ctx,
  92. grpc_security_handshake *h,
  93. grpc_error *error) {
  94. if (!h->is_client_side) {
  95. security_connector_remove_handshake(h);
  96. }
  97. if (error == GRPC_ERROR_NONE) {
  98. h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint,
  99. h->auth_context);
  100. } else {
  101. const char *msg = grpc_error_string(error);
  102. gpr_log(GPR_ERROR, "Security handshake failed: %s", msg);
  103. grpc_error_free_string(msg);
  104. if (h->secure_endpoint != NULL) {
  105. grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint);
  106. grpc_endpoint_destroy(exec_ctx, h->secure_endpoint);
  107. } else {
  108. grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint);
  109. }
  110. h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL, NULL);
  111. }
  112. if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker);
  113. if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer);
  114. gpr_slice_buffer_destroy(&h->left_overs);
  115. gpr_slice_buffer_destroy(&h->outgoing);
  116. gpr_slice_buffer_destroy(&h->incoming);
  117. GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake");
  118. GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake");
  119. gpr_free(h);
  120. GRPC_ERROR_UNREF(error);
  121. }
  122. static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data,
  123. grpc_security_status status,
  124. grpc_auth_context *auth_context) {
  125. grpc_security_handshake *h = user_data;
  126. tsi_frame_protector *protector;
  127. tsi_result result;
  128. if (status != GRPC_SECURITY_OK) {
  129. security_handshake_done(
  130. exec_ctx, h,
  131. grpc_error_set_int(GRPC_ERROR_CREATE("Error checking peer."),
  132. GRPC_ERROR_INT_SECURITY_STATUS, status));
  133. return;
  134. }
  135. h->auth_context = GRPC_AUTH_CONTEXT_REF(auth_context, "handshake");
  136. result =
  137. tsi_handshaker_create_frame_protector(h->handshaker, NULL, &protector);
  138. if (result != TSI_OK) {
  139. security_handshake_done(
  140. exec_ctx, h,
  141. grpc_set_tsi_error_result(
  142. GRPC_ERROR_CREATE("Frame protector creation failed"), result));
  143. return;
  144. }
  145. h->secure_endpoint =
  146. grpc_secure_endpoint_create(protector, h->wrapped_endpoint,
  147. h->left_overs.slices, h->left_overs.count);
  148. h->left_overs.count = 0;
  149. h->left_overs.length = 0;
  150. security_handshake_done(exec_ctx, h, GRPC_ERROR_NONE);
  151. return;
  152. }
  153. static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) {
  154. tsi_peer peer;
  155. tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer);
  156. if (result != TSI_OK) {
  157. security_handshake_done(
  158. exec_ctx, h, grpc_set_tsi_error_result(
  159. GRPC_ERROR_CREATE("Peer extraction failed"), result));
  160. return;
  161. }
  162. grpc_security_connector_check_peer(exec_ctx, h->connector, peer,
  163. on_peer_checked, h);
  164. }
  165. static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx,
  166. grpc_security_handshake *h) {
  167. size_t offset = 0;
  168. tsi_result result = TSI_OK;
  169. gpr_slice to_send;
  170. do {
  171. size_t to_send_size = h->handshake_buffer_size - offset;
  172. result = tsi_handshaker_get_bytes_to_send_to_peer(
  173. h->handshaker, h->handshake_buffer + offset, &to_send_size);
  174. offset += to_send_size;
  175. if (result == TSI_INCOMPLETE_DATA) {
  176. h->handshake_buffer_size *= 2;
  177. h->handshake_buffer =
  178. gpr_realloc(h->handshake_buffer, h->handshake_buffer_size);
  179. }
  180. } while (result == TSI_INCOMPLETE_DATA);
  181. if (result != TSI_OK) {
  182. security_handshake_done(exec_ctx, h,
  183. grpc_set_tsi_error_result(
  184. GRPC_ERROR_CREATE("Handshake failed"), result));
  185. return;
  186. }
  187. to_send =
  188. gpr_slice_from_copied_buffer((const char *)h->handshake_buffer, offset);
  189. gpr_slice_buffer_reset_and_unref(&h->outgoing);
  190. gpr_slice_buffer_add(&h->outgoing, to_send);
  191. /* TODO(klempner,jboeuf): This should probably use the client setup
  192. deadline */
  193. grpc_endpoint_write(exec_ctx, h->wrapped_endpoint, &h->outgoing,
  194. &h->on_handshake_data_sent_to_peer);
  195. }
  196. static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx,
  197. void *handshake,
  198. grpc_error *error) {
  199. grpc_security_handshake *h = handshake;
  200. size_t consumed_slice_size = 0;
  201. tsi_result result = TSI_OK;
  202. size_t i;
  203. size_t num_left_overs;
  204. int has_left_overs_in_current_slice = 0;
  205. if (error != GRPC_ERROR_NONE) {
  206. security_handshake_done(
  207. exec_ctx, h,
  208. GRPC_ERROR_CREATE_REFERENCING("Handshake read failed", &error, 1));
  209. return;
  210. }
  211. for (i = 0; i < h->incoming.count; i++) {
  212. consumed_slice_size = GPR_SLICE_LENGTH(h->incoming.slices[i]);
  213. result = tsi_handshaker_process_bytes_from_peer(
  214. h->handshaker, GPR_SLICE_START_PTR(h->incoming.slices[i]),
  215. &consumed_slice_size);
  216. if (!tsi_handshaker_is_in_progress(h->handshaker)) break;
  217. }
  218. if (tsi_handshaker_is_in_progress(h->handshaker)) {
  219. /* We may need more data. */
  220. if (result == TSI_INCOMPLETE_DATA) {
  221. grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming,
  222. &h->on_handshake_data_received_from_peer);
  223. return;
  224. } else {
  225. send_handshake_bytes_to_peer(exec_ctx, h);
  226. return;
  227. }
  228. }
  229. if (result != TSI_OK) {
  230. security_handshake_done(exec_ctx, h,
  231. grpc_set_tsi_error_result(
  232. GRPC_ERROR_CREATE("Handshake failed"), result));
  233. return;
  234. }
  235. /* Handshake is done and successful this point. */
  236. has_left_overs_in_current_slice =
  237. (consumed_slice_size < GPR_SLICE_LENGTH(h->incoming.slices[i]));
  238. num_left_overs =
  239. (has_left_overs_in_current_slice ? 1 : 0) + h->incoming.count - i - 1;
  240. if (num_left_overs == 0) {
  241. check_peer(exec_ctx, h);
  242. return;
  243. }
  244. /* Put the leftovers in our buffer (ownership transfered). */
  245. if (has_left_overs_in_current_slice) {
  246. gpr_slice_buffer_add(
  247. &h->left_overs,
  248. gpr_slice_split_tail(&h->incoming.slices[i], consumed_slice_size));
  249. gpr_slice_unref(
  250. h->incoming.slices[i]); /* split_tail above increments refcount. */
  251. }
  252. gpr_slice_buffer_addn(
  253. &h->left_overs, &h->incoming.slices[i + 1],
  254. num_left_overs - (size_t)has_left_overs_in_current_slice);
  255. check_peer(exec_ctx, h);
  256. }
  257. /* If handshake is NULL, the handshake is done. */
  258. static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx,
  259. void *handshake, grpc_error *error) {
  260. grpc_security_handshake *h = handshake;
  261. /* Make sure that write is OK. */
  262. if (error != GRPC_ERROR_NONE) {
  263. if (handshake != NULL)
  264. security_handshake_done(
  265. exec_ctx, h,
  266. GRPC_ERROR_CREATE_REFERENCING("Handshake write failed", &error, 1));
  267. return;
  268. }
  269. /* We may be done. */
  270. if (tsi_handshaker_is_in_progress(h->handshaker)) {
  271. /* TODO(klempner,jboeuf): This should probably use the client setup
  272. deadline */
  273. grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming,
  274. &h->on_handshake_data_received_from_peer);
  275. } else {
  276. check_peer(exec_ctx, h);
  277. }
  278. }
  279. void grpc_do_security_handshake(grpc_exec_ctx *exec_ctx,
  280. tsi_handshaker *handshaker,
  281. grpc_security_connector *connector,
  282. bool is_client_side,
  283. grpc_endpoint *nonsecure_endpoint,
  284. grpc_security_handshake_done_cb cb,
  285. void *user_data) {
  286. grpc_security_connector_handshake_list *handshake_node;
  287. grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake));
  288. memset(h, 0, sizeof(grpc_security_handshake));
  289. h->handshaker = handshaker;
  290. h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake");
  291. h->is_client_side = is_client_side;
  292. h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE;
  293. h->handshake_buffer = gpr_malloc(h->handshake_buffer_size);
  294. h->wrapped_endpoint = nonsecure_endpoint;
  295. h->user_data = user_data;
  296. h->cb = cb;
  297. grpc_closure_init(&h->on_handshake_data_sent_to_peer,
  298. on_handshake_data_sent_to_peer, h);
  299. grpc_closure_init(&h->on_handshake_data_received_from_peer,
  300. on_handshake_data_received_from_peer, h);
  301. gpr_slice_buffer_init(&h->left_overs);
  302. gpr_slice_buffer_init(&h->outgoing);
  303. gpr_slice_buffer_init(&h->incoming);
  304. if (!is_client_side) {
  305. grpc_server_security_connector *server_connector =
  306. (grpc_server_security_connector *)connector;
  307. handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list));
  308. handshake_node->handshake = h;
  309. gpr_mu_lock(&server_connector->mu);
  310. handshake_node->next = server_connector->handshaking_handshakes;
  311. server_connector->handshaking_handshakes = handshake_node;
  312. gpr_mu_unlock(&server_connector->mu);
  313. }
  314. send_handshake_bytes_to_peer(exec_ctx, h);
  315. }
  316. void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx,
  317. void *handshake) {
  318. grpc_security_handshake *h = handshake;
  319. grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint);
  320. }