awesome-grpc-that-works 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (453) hide show
  1. checksums.yaml +7 -0
  2. data/Makefile +29456 -0
  3. data/Rakefile +63 -0
  4. data/etc/roots.pem +5114 -0
  5. data/include/grpc/byte_buffer.h +120 -0
  6. data/include/grpc/byte_buffer_reader.h +58 -0
  7. data/include/grpc/census.h +488 -0
  8. data/include/grpc/compression.h +106 -0
  9. data/include/grpc/grpc.h +732 -0
  10. data/include/grpc/grpc_security.h +374 -0
  11. data/include/grpc/grpc_zookeeper.h +59 -0
  12. data/include/grpc/status.h +163 -0
  13. data/include/grpc/support/alloc.h +72 -0
  14. data/include/grpc/support/atm.h +92 -0
  15. data/include/grpc/support/atm_gcc_atomic.h +72 -0
  16. data/include/grpc/support/atm_gcc_sync.h +87 -0
  17. data/include/grpc/support/atm_win32.h +125 -0
  18. data/include/grpc/support/avl.h +91 -0
  19. data/include/grpc/support/cmdline.h +101 -0
  20. data/include/grpc/support/cpu.h +57 -0
  21. data/include/grpc/support/histogram.h +76 -0
  22. data/include/grpc/support/host_port.h +64 -0
  23. data/include/grpc/support/log.h +108 -0
  24. data/include/grpc/support/log_win32.h +51 -0
  25. data/include/grpc/support/port_platform.h +356 -0
  26. data/include/grpc/support/slice.h +182 -0
  27. data/include/grpc/support/slice_buffer.h +102 -0
  28. data/include/grpc/support/string_util.h +61 -0
  29. data/include/grpc/support/subprocess.h +57 -0
  30. data/include/grpc/support/sync.h +315 -0
  31. data/include/grpc/support/sync_generic.h +55 -0
  32. data/include/grpc/support/sync_posix.h +47 -0
  33. data/include/grpc/support/sync_win32.h +49 -0
  34. data/include/grpc/support/thd.h +91 -0
  35. data/include/grpc/support/time.h +128 -0
  36. data/include/grpc/support/tls.h +77 -0
  37. data/include/grpc/support/tls_gcc.h +56 -0
  38. data/include/grpc/support/tls_msvc.h +56 -0
  39. data/include/grpc/support/tls_pthread.h +60 -0
  40. data/include/grpc/support/useful.h +75 -0
  41. data/src/core/census/aggregation.h +66 -0
  42. data/src/core/census/context.c +46 -0
  43. data/src/core/census/context.h +47 -0
  44. data/src/core/census/grpc_context.c +53 -0
  45. data/src/core/census/grpc_filter.c +184 -0
  46. data/src/core/census/grpc_filter.h +44 -0
  47. data/src/core/census/initialize.c +57 -0
  48. data/src/core/census/operation.c +63 -0
  49. data/src/core/census/rpc_metric_id.h +51 -0
  50. data/src/core/census/tracing.c +45 -0
  51. data/src/core/channel/channel_args.c +209 -0
  52. data/src/core/channel/channel_args.h +88 -0
  53. data/src/core/channel/channel_stack.c +262 -0
  54. data/src/core/channel/channel_stack.h +260 -0
  55. data/src/core/channel/client_channel.c +524 -0
  56. data/src/core/channel/client_channel.h +63 -0
  57. data/src/core/channel/client_uchannel.c +243 -0
  58. data/src/core/channel/client_uchannel.h +60 -0
  59. data/src/core/channel/compress_filter.c +297 -0
  60. data/src/core/channel/compress_filter.h +65 -0
  61. data/src/core/channel/connected_channel.c +167 -0
  62. data/src/core/channel/connected_channel.h +51 -0
  63. data/src/core/channel/context.h +49 -0
  64. data/src/core/channel/http_client_filter.c +248 -0
  65. data/src/core/channel/http_client_filter.h +44 -0
  66. data/src/core/channel/http_server_filter.c +233 -0
  67. data/src/core/channel/http_server_filter.h +42 -0
  68. data/src/core/channel/subchannel_call_holder.c +259 -0
  69. data/src/core/channel/subchannel_call_holder.h +98 -0
  70. data/src/core/client_config/client_config.c +72 -0
  71. data/src/core/client_config/client_config.h +53 -0
  72. data/src/core/client_config/connector.c +54 -0
  73. data/src/core/client_config/connector.h +95 -0
  74. data/src/core/client_config/default_initial_connect_string.c +39 -0
  75. data/src/core/client_config/initial_connect_string.c +53 -0
  76. data/src/core/client_config/initial_connect_string.h +50 -0
  77. data/src/core/client_config/lb_policies/pick_first.c +398 -0
  78. data/src/core/client_config/lb_policies/pick_first.h +43 -0
  79. data/src/core/client_config/lb_policies/round_robin.c +537 -0
  80. data/src/core/client_config/lb_policies/round_robin.h +46 -0
  81. data/src/core/client_config/lb_policy.c +134 -0
  82. data/src/core/client_config/lb_policy.h +143 -0
  83. data/src/core/client_config/lb_policy_factory.c +48 -0
  84. data/src/core/client_config/lb_policy_factory.h +73 -0
  85. data/src/core/client_config/lb_policy_registry.c +88 -0
  86. data/src/core/client_config/lb_policy_registry.h +54 -0
  87. data/src/core/client_config/resolver.c +82 -0
  88. data/src/core/client_config/resolver.h +94 -0
  89. data/src/core/client_config/resolver_factory.c +55 -0
  90. data/src/core/client_config/resolver_factory.h +82 -0
  91. data/src/core/client_config/resolver_registry.c +137 -0
  92. data/src/core/client_config/resolver_registry.h +65 -0
  93. data/src/core/client_config/resolvers/dns_resolver.c +257 -0
  94. data/src/core/client_config/resolvers/dns_resolver.h +42 -0
  95. data/src/core/client_config/resolvers/sockaddr_resolver.c +391 -0
  96. data/src/core/client_config/resolvers/sockaddr_resolver.h +50 -0
  97. data/src/core/client_config/subchannel.c +697 -0
  98. data/src/core/client_config/subchannel.h +165 -0
  99. data/src/core/client_config/subchannel_factory.c +49 -0
  100. data/src/core/client_config/subchannel_factory.h +66 -0
  101. data/src/core/client_config/uri_parser.c +242 -0
  102. data/src/core/client_config/uri_parser.h +51 -0
  103. data/src/core/compression/algorithm.c +166 -0
  104. data/src/core/compression/algorithm_metadata.h +53 -0
  105. data/src/core/compression/message_compress.c +198 -0
  106. data/src/core/compression/message_compress.h +52 -0
  107. data/src/core/debug/trace.c +136 -0
  108. data/src/core/debug/trace.h +43 -0
  109. data/src/core/httpcli/format_request.c +120 -0
  110. data/src/core/httpcli/format_request.h +45 -0
  111. data/src/core/httpcli/httpcli.c +286 -0
  112. data/src/core/httpcli/httpcli.h +162 -0
  113. data/src/core/httpcli/httpcli_security_connector.c +189 -0
  114. data/src/core/httpcli/parser.c +211 -0
  115. data/src/core/httpcli/parser.h +64 -0
  116. data/src/core/iomgr/closure.c +98 -0
  117. data/src/core/iomgr/closure.h +97 -0
  118. data/src/core/iomgr/endpoint.c +67 -0
  119. data/src/core/iomgr/endpoint.h +102 -0
  120. data/src/core/iomgr/endpoint_pair.h +47 -0
  121. data/src/core/iomgr/endpoint_pair_posix.c +82 -0
  122. data/src/core/iomgr/endpoint_pair_windows.c +97 -0
  123. data/src/core/iomgr/exec_ctx.c +72 -0
  124. data/src/core/iomgr/exec_ctx.h +78 -0
  125. data/src/core/iomgr/executor.c +143 -0
  126. data/src/core/iomgr/executor.h +53 -0
  127. data/src/core/iomgr/fd_posix.c +438 -0
  128. data/src/core/iomgr/fd_posix.h +189 -0
  129. data/src/core/iomgr/iocp_windows.c +206 -0
  130. data/src/core/iomgr/iocp_windows.h +56 -0
  131. data/src/core/iomgr/iomgr.c +156 -0
  132. data/src/core/iomgr/iomgr.h +43 -0
  133. data/src/core/iomgr/iomgr_internal.h +58 -0
  134. data/src/core/iomgr/iomgr_posix.c +52 -0
  135. data/src/core/iomgr/iomgr_posix.h +39 -0
  136. data/src/core/iomgr/iomgr_windows.c +73 -0
  137. data/src/core/iomgr/pollset.h +95 -0
  138. data/src/core/iomgr/pollset_multipoller_with_epoll.c +258 -0
  139. data/src/core/iomgr/pollset_multipoller_with_poll_posix.c +227 -0
  140. data/src/core/iomgr/pollset_posix.c +638 -0
  141. data/src/core/iomgr/pollset_posix.h +147 -0
  142. data/src/core/iomgr/pollset_set.h +67 -0
  143. data/src/core/iomgr/pollset_set_posix.c +182 -0
  144. data/src/core/iomgr/pollset_set_posix.h +61 -0
  145. data/src/core/iomgr/pollset_set_windows.c +60 -0
  146. data/src/core/iomgr/pollset_set_windows.h +39 -0
  147. data/src/core/iomgr/pollset_windows.c +248 -0
  148. data/src/core/iomgr/pollset_windows.h +79 -0
  149. data/src/core/iomgr/resolve_address.h +72 -0
  150. data/src/core/iomgr/resolve_address_posix.c +183 -0
  151. data/src/core/iomgr/resolve_address_windows.c +166 -0
  152. data/src/core/iomgr/sockaddr.h +47 -0
  153. data/src/core/iomgr/sockaddr_posix.h +44 -0
  154. data/src/core/iomgr/sockaddr_utils.c +234 -0
  155. data/src/core/iomgr/sockaddr_utils.h +89 -0
  156. data/src/core/iomgr/sockaddr_win32.h +46 -0
  157. data/src/core/iomgr/socket_utils_common_posix.c +208 -0
  158. data/src/core/iomgr/socket_utils_linux.c +51 -0
  159. data/src/core/iomgr/socket_utils_posix.c +70 -0
  160. data/src/core/iomgr/socket_utils_posix.h +113 -0
  161. data/src/core/iomgr/socket_windows.c +98 -0
  162. data/src/core/iomgr/socket_windows.h +111 -0
  163. data/src/core/iomgr/tcp_client.h +53 -0
  164. data/src/core/iomgr/tcp_client_posix.c +304 -0
  165. data/src/core/iomgr/tcp_client_windows.c +221 -0
  166. data/src/core/iomgr/tcp_posix.c +485 -0
  167. data/src/core/iomgr/tcp_posix.h +65 -0
  168. data/src/core/iomgr/tcp_server.h +83 -0
  169. data/src/core/iomgr/tcp_server_posix.c +562 -0
  170. data/src/core/iomgr/tcp_server_windows.c +509 -0
  171. data/src/core/iomgr/tcp_windows.c +406 -0
  172. data/src/core/iomgr/tcp_windows.h +57 -0
  173. data/src/core/iomgr/time_averaged_stats.c +77 -0
  174. data/src/core/iomgr/time_averaged_stats.h +88 -0
  175. data/src/core/iomgr/timer.c +345 -0
  176. data/src/core/iomgr/timer.h +89 -0
  177. data/src/core/iomgr/timer_heap.c +148 -0
  178. data/src/core/iomgr/timer_heap.h +57 -0
  179. data/src/core/iomgr/timer_internal.h +61 -0
  180. data/src/core/iomgr/udp_server.c +439 -0
  181. data/src/core/iomgr/udp_server.h +83 -0
  182. data/src/core/iomgr/wakeup_fd_eventfd.c +85 -0
  183. data/src/core/iomgr/wakeup_fd_nospecial.c +51 -0
  184. data/src/core/iomgr/wakeup_fd_pipe.c +97 -0
  185. data/src/core/iomgr/wakeup_fd_pipe.h +41 -0
  186. data/src/core/iomgr/wakeup_fd_posix.c +72 -0
  187. data/src/core/iomgr/wakeup_fd_posix.h +101 -0
  188. data/src/core/iomgr/workqueue.h +85 -0
  189. data/src/core/iomgr/workqueue_posix.c +143 -0
  190. data/src/core/iomgr/workqueue_posix.h +51 -0
  191. data/src/core/iomgr/workqueue_windows.c +40 -0
  192. data/src/core/iomgr/workqueue_windows.h +37 -0
  193. data/src/core/json/json.c +64 -0
  194. data/src/core/json/json.h +88 -0
  195. data/src/core/json/json_common.h +49 -0
  196. data/src/core/json/json_reader.c +660 -0
  197. data/src/core/json/json_reader.h +160 -0
  198. data/src/core/json/json_string.c +379 -0
  199. data/src/core/json/json_writer.c +260 -0
  200. data/src/core/json/json_writer.h +97 -0
  201. data/src/core/profiling/basic_timers.c +274 -0
  202. data/src/core/profiling/stap_timers.c +65 -0
  203. data/src/core/profiling/timers.h +119 -0
  204. data/src/core/security/auth_filters.h +42 -0
  205. data/src/core/security/base64.c +233 -0
  206. data/src/core/security/base64.h +52 -0
  207. data/src/core/security/client_auth_filter.c +337 -0
  208. data/src/core/security/credentials.c +1273 -0
  209. data/src/core/security/credentials.h +376 -0
  210. data/src/core/security/credentials_metadata.c +101 -0
  211. data/src/core/security/credentials_posix.c +61 -0
  212. data/src/core/security/credentials_win32.c +61 -0
  213. data/src/core/security/google_default_credentials.c +260 -0
  214. data/src/core/security/handshake.c +327 -0
  215. data/src/core/security/handshake.h +50 -0
  216. data/src/core/security/json_token.c +405 -0
  217. data/src/core/security/json_token.h +118 -0
  218. data/src/core/security/jwt_verifier.c +842 -0
  219. data/src/core/security/jwt_verifier.h +136 -0
  220. data/src/core/security/secure_endpoint.c +383 -0
  221. data/src/core/security/secure_endpoint.h +49 -0
  222. data/src/core/security/security_connector.c +756 -0
  223. data/src/core/security/security_connector.h +246 -0
  224. data/src/core/security/security_context.c +342 -0
  225. data/src/core/security/security_context.h +114 -0
  226. data/src/core/security/server_auth_filter.c +264 -0
  227. data/src/core/security/server_secure_chttp2.c +268 -0
  228. data/src/core/statistics/census_interface.h +76 -0
  229. data/src/core/statistics/census_rpc_stats.h +101 -0
  230. data/src/core/support/alloc.c +90 -0
  231. data/src/core/support/avl.c +288 -0
  232. data/src/core/support/block_annotate.h +48 -0
  233. data/src/core/support/cmdline.c +347 -0
  234. data/src/core/support/cpu_iphone.c +49 -0
  235. data/src/core/support/cpu_linux.c +78 -0
  236. data/src/core/support/cpu_posix.c +77 -0
  237. data/src/core/support/cpu_windows.c +47 -0
  238. data/src/core/support/env.h +60 -0
  239. data/src/core/support/env_linux.c +62 -0
  240. data/src/core/support/env_posix.c +57 -0
  241. data/src/core/support/env_win32.c +65 -0
  242. data/src/core/support/file.c +91 -0
  243. data/src/core/support/file.h +63 -0
  244. data/src/core/support/file_posix.c +85 -0
  245. data/src/core/support/file_win32.c +84 -0
  246. data/src/core/support/histogram.c +244 -0
  247. data/src/core/support/host_port.c +110 -0
  248. data/src/core/support/log.c +66 -0
  249. data/src/core/support/log_android.c +87 -0
  250. data/src/core/support/log_linux.c +105 -0
  251. data/src/core/support/log_posix.c +102 -0
  252. data/src/core/support/log_win32.c +125 -0
  253. data/src/core/support/murmur_hash.c +96 -0
  254. data/src/core/support/murmur_hash.h +44 -0
  255. data/src/core/support/slice.c +343 -0
  256. data/src/core/support/slice_buffer.c +282 -0
  257. data/src/core/support/stack_lockfree.c +175 -0
  258. data/src/core/support/stack_lockfree.h +53 -0
  259. data/src/core/support/string.c +296 -0
  260. data/src/core/support/string.h +121 -0
  261. data/src/core/support/string_posix.c +86 -0
  262. data/src/core/support/string_win32.c +109 -0
  263. data/src/core/support/string_win32.h +47 -0
  264. data/src/core/support/subprocess_posix.c +112 -0
  265. data/src/core/support/sync.c +122 -0
  266. data/src/core/support/sync_posix.c +104 -0
  267. data/src/core/support/sync_win32.c +128 -0
  268. data/src/core/support/thd.c +64 -0
  269. data/src/core/support/thd_internal.h +39 -0
  270. data/src/core/support/thd_posix.c +94 -0
  271. data/src/core/support/thd_win32.c +117 -0
  272. data/src/core/support/time.c +304 -0
  273. data/src/core/support/time_posix.c +161 -0
  274. data/src/core/support/time_precise.c +89 -0
  275. data/src/core/support/time_precise.h +42 -0
  276. data/src/core/support/time_win32.c +101 -0
  277. data/src/core/support/tls_pthread.c +45 -0
  278. data/src/core/surface/api_trace.c +36 -0
  279. data/src/core/surface/api_trace.h +65 -0
  280. data/src/core/surface/byte_buffer.c +97 -0
  281. data/src/core/surface/byte_buffer_reader.c +123 -0
  282. data/src/core/surface/call.c +1424 -0
  283. data/src/core/surface/call.h +109 -0
  284. data/src/core/surface/call_details.c +50 -0
  285. data/src/core/surface/call_log_batch.c +118 -0
  286. data/src/core/surface/call_test_only.h +64 -0
  287. data/src/core/surface/channel.c +327 -0
  288. data/src/core/surface/channel.h +74 -0
  289. data/src/core/surface/channel_connectivity.c +220 -0
  290. data/src/core/surface/channel_create.c +235 -0
  291. data/src/core/surface/channel_ping.c +79 -0
  292. data/src/core/surface/completion_queue.c +481 -0
  293. data/src/core/surface/completion_queue.h +91 -0
  294. data/src/core/surface/event_string.c +81 -0
  295. data/src/core/surface/event_string.h +42 -0
  296. data/src/core/surface/init.c +168 -0
  297. data/src/core/surface/init.h +40 -0
  298. data/src/core/surface/init_secure.c +42 -0
  299. data/src/core/surface/lame_client.c +149 -0
  300. data/src/core/surface/metadata_array.c +49 -0
  301. data/src/core/surface/secure_channel_create.c +336 -0
  302. data/src/core/surface/server.c +1343 -0
  303. data/src/core/surface/server.h +67 -0
  304. data/src/core/surface/server_chttp2.c +149 -0
  305. data/src/core/surface/server_create.c +51 -0
  306. data/src/core/surface/surface_trace.h +48 -0
  307. data/src/core/surface/validate_metadata.c +73 -0
  308. data/src/core/surface/version.c +39 -0
  309. data/src/core/transport/byte_stream.c +76 -0
  310. data/src/core/transport/byte_stream.h +88 -0
  311. data/src/core/transport/chttp2/alpn.c +56 -0
  312. data/src/core/transport/chttp2/alpn.h +49 -0
  313. data/src/core/transport/chttp2/bin_encoder.c +285 -0
  314. data/src/core/transport/chttp2/bin_encoder.h +54 -0
  315. data/src/core/transport/chttp2/frame.h +69 -0
  316. data/src/core/transport/chttp2/frame_data.c +245 -0
  317. data/src/core/transport/chttp2/frame_data.h +101 -0
  318. data/src/core/transport/chttp2/frame_goaway.c +193 -0
  319. data/src/core/transport/chttp2/frame_goaway.h +77 -0
  320. data/src/core/transport/chttp2/frame_ping.c +97 -0
  321. data/src/core/transport/chttp2/frame_ping.h +56 -0
  322. data/src/core/transport/chttp2/frame_rst_stream.c +100 -0
  323. data/src/core/transport/chttp2/frame_rst_stream.h +55 -0
  324. data/src/core/transport/chttp2/frame_settings.c +259 -0
  325. data/src/core/transport/chttp2/frame_settings.h +103 -0
  326. data/src/core/transport/chttp2/frame_window_update.c +114 -0
  327. data/src/core/transport/chttp2/frame_window_update.h +58 -0
  328. data/src/core/transport/chttp2/hpack_encoder.c +572 -0
  329. data/src/core/transport/chttp2/hpack_encoder.h +95 -0
  330. data/src/core/transport/chttp2/hpack_parser.c +1449 -0
  331. data/src/core/transport/chttp2/hpack_parser.h +116 -0
  332. data/src/core/transport/chttp2/hpack_table.c +361 -0
  333. data/src/core/transport/chttp2/hpack_table.h +108 -0
  334. data/src/core/transport/chttp2/http2_errors.h +56 -0
  335. data/src/core/transport/chttp2/huffsyms.c +297 -0
  336. data/src/core/transport/chttp2/huffsyms.h +48 -0
  337. data/src/core/transport/chttp2/incoming_metadata.c +96 -0
  338. data/src/core/transport/chttp2/incoming_metadata.h +60 -0
  339. data/src/core/transport/chttp2/internal.h +757 -0
  340. data/src/core/transport/chttp2/parsing.c +866 -0
  341. data/src/core/transport/chttp2/status_conversion.c +109 -0
  342. data/src/core/transport/chttp2/status_conversion.h +50 -0
  343. data/src/core/transport/chttp2/stream_lists.c +401 -0
  344. data/src/core/transport/chttp2/stream_map.c +198 -0
  345. data/src/core/transport/chttp2/stream_map.h +85 -0
  346. data/src/core/transport/chttp2/timeout_encoding.c +185 -0
  347. data/src/core/transport/chttp2/timeout_encoding.h +47 -0
  348. data/src/core/transport/chttp2/varint.c +66 -0
  349. data/src/core/transport/chttp2/varint.h +76 -0
  350. data/src/core/transport/chttp2/writing.c +356 -0
  351. data/src/core/transport/chttp2_transport.c +1692 -0
  352. data/src/core/transport/chttp2_transport.h +51 -0
  353. data/src/core/transport/connectivity_state.c +164 -0
  354. data/src/core/transport/connectivity_state.h +85 -0
  355. data/src/core/transport/metadata.c +690 -0
  356. data/src/core/transport/metadata.h +156 -0
  357. data/src/core/transport/metadata_batch.c +194 -0
  358. data/src/core/transport/metadata_batch.h +125 -0
  359. data/src/core/transport/static_metadata.c +90 -0
  360. data/src/core/transport/static_metadata.h +408 -0
  361. data/src/core/transport/transport.c +183 -0
  362. data/src/core/transport/transport.h +222 -0
  363. data/src/core/transport/transport_impl.h +78 -0
  364. data/src/core/transport/transport_op_string.c +140 -0
  365. data/src/core/tsi/fake_transport_security.c +525 -0
  366. data/src/core/tsi/fake_transport_security.h +61 -0
  367. data/src/core/tsi/ssl_transport_security.c +1467 -0
  368. data/src/core/tsi/ssl_transport_security.h +173 -0
  369. data/src/core/tsi/transport_security.c +284 -0
  370. data/src/core/tsi/transport_security.h +111 -0
  371. data/src/core/tsi/transport_security_interface.h +344 -0
  372. data/src/ruby/bin/apis/google/protobuf/empty.rb +44 -0
  373. data/src/ruby/bin/apis/pubsub_demo.rb +256 -0
  374. data/src/ruby/bin/apis/tech/pubsub/proto/pubsub.rb +174 -0
  375. data/src/ruby/bin/apis/tech/pubsub/proto/pubsub_services.rb +103 -0
  376. data/src/ruby/bin/grpc_ruby_interop_client +33 -0
  377. data/src/ruby/bin/grpc_ruby_interop_server +33 -0
  378. data/src/ruby/bin/interop/interop_client.rb +51 -0
  379. data/src/ruby/bin/interop/interop_server.rb +50 -0
  380. data/src/ruby/bin/math.rb +32 -0
  381. data/src/ruby/bin/math_client.rb +147 -0
  382. data/src/ruby/bin/math_server.rb +206 -0
  383. data/src/ruby/bin/math_services.rb +27 -0
  384. data/src/ruby/bin/noproto_client.rb +108 -0
  385. data/src/ruby/bin/noproto_server.rb +112 -0
  386. data/src/ruby/ext/grpc/extconf.rb +92 -0
  387. data/src/ruby/ext/grpc/rb_byte_buffer.c +75 -0
  388. data/src/ruby/ext/grpc/rb_byte_buffer.h +47 -0
  389. data/src/ruby/ext/grpc/rb_call.c +915 -0
  390. data/src/ruby/ext/grpc/rb_call.h +66 -0
  391. data/src/ruby/ext/grpc/rb_call_credentials.c +315 -0
  392. data/src/ruby/ext/grpc/rb_call_credentials.h +46 -0
  393. data/src/ruby/ext/grpc/rb_channel.c +430 -0
  394. data/src/ruby/ext/grpc/rb_channel.h +47 -0
  395. data/src/ruby/ext/grpc/rb_channel_args.c +167 -0
  396. data/src/ruby/ext/grpc/rb_channel_args.h +53 -0
  397. data/src/ruby/ext/grpc/rb_channel_credentials.c +266 -0
  398. data/src/ruby/ext/grpc/rb_channel_credentials.h +47 -0
  399. data/src/ruby/ext/grpc/rb_completion_queue.c +181 -0
  400. data/src/ruby/ext/grpc/rb_completion_queue.h +55 -0
  401. data/src/ruby/ext/grpc/rb_event_thread.c +153 -0
  402. data/src/ruby/ext/grpc/rb_event_thread.h +37 -0
  403. data/src/ruby/ext/grpc/rb_grpc.c +328 -0
  404. data/src/ruby/ext/grpc/rb_grpc.h +85 -0
  405. data/src/ruby/ext/grpc/rb_server.c +398 -0
  406. data/src/ruby/ext/grpc/rb_server.h +47 -0
  407. data/src/ruby/ext/grpc/rb_server_credentials.c +282 -0
  408. data/src/ruby/ext/grpc/rb_server_credentials.h +47 -0
  409. data/src/ruby/lib/grpc/core/time_consts.rb +71 -0
  410. data/src/ruby/lib/grpc/errors.rb +62 -0
  411. data/src/ruby/lib/grpc/generic/active_call.rb +488 -0
  412. data/src/ruby/lib/grpc/generic/bidi_call.rb +218 -0
  413. data/src/ruby/lib/grpc/generic/client_stub.rb +471 -0
  414. data/src/ruby/lib/grpc/generic/rpc_desc.rb +147 -0
  415. data/src/ruby/lib/grpc/generic/rpc_server.rb +504 -0
  416. data/src/ruby/lib/grpc/generic/service.rb +234 -0
  417. data/src/ruby/lib/grpc/logconfig.rb +59 -0
  418. data/src/ruby/lib/grpc/notifier.rb +60 -0
  419. data/src/ruby/lib/grpc/version.rb +33 -0
  420. data/src/ruby/lib/grpc.rb +44 -0
  421. data/src/ruby/pb/README.md +42 -0
  422. data/src/ruby/pb/generate_proto_ruby.sh +51 -0
  423. data/src/ruby/pb/grpc/health/checker.rb +75 -0
  424. data/src/ruby/pb/grpc/health/v1alpha/health.rb +29 -0
  425. data/src/ruby/pb/grpc/health/v1alpha/health_services.rb +28 -0
  426. data/src/ruby/pb/test/client.rb +469 -0
  427. data/src/ruby/pb/test/proto/empty.rb +15 -0
  428. data/src/ruby/pb/test/proto/messages.rb +80 -0
  429. data/src/ruby/pb/test/proto/test.rb +14 -0
  430. data/src/ruby/pb/test/proto/test_services.rb +64 -0
  431. data/src/ruby/pb/test/server.rb +253 -0
  432. data/src/ruby/spec/call_credentials_spec.rb +57 -0
  433. data/src/ruby/spec/call_spec.rb +163 -0
  434. data/src/ruby/spec/channel_credentials_spec.rb +97 -0
  435. data/src/ruby/spec/channel_spec.rb +177 -0
  436. data/src/ruby/spec/client_server_spec.rb +475 -0
  437. data/src/ruby/spec/completion_queue_spec.rb +42 -0
  438. data/src/ruby/spec/generic/active_call_spec.rb +373 -0
  439. data/src/ruby/spec/generic/client_stub_spec.rb +476 -0
  440. data/src/ruby/spec/generic/rpc_desc_spec.rb +331 -0
  441. data/src/ruby/spec/generic/rpc_server_pool_spec.rb +138 -0
  442. data/src/ruby/spec/generic/rpc_server_spec.rb +576 -0
  443. data/src/ruby/spec/generic/service_spec.rb +345 -0
  444. data/src/ruby/spec/pb/health/checker_spec.rb +232 -0
  445. data/src/ruby/spec/server_credentials_spec.rb +94 -0
  446. data/src/ruby/spec/server_spec.rb +209 -0
  447. data/src/ruby/spec/spec_helper.rb +69 -0
  448. data/src/ruby/spec/testdata/README +1 -0
  449. data/src/ruby/spec/testdata/ca.pem +15 -0
  450. data/src/ruby/spec/testdata/server1.key +16 -0
  451. data/src/ruby/spec/testdata/server1.pem +16 -0
  452. data/src/ruby/spec/time_consts_spec.rb +89 -0
  453. metadata +665 -0
@@ -0,0 +1,1467 @@
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
+
34
+ #include "src/core/tsi/ssl_transport_security.h"
35
+
36
+ #include <limits.h>
37
+ #include <string.h>
38
+
39
+ #include <grpc/support/log.h>
40
+ #include <grpc/support/sync.h>
41
+ #include <grpc/support/thd.h>
42
+ #include <grpc/support/useful.h>
43
+ #include "src/core/tsi/transport_security.h"
44
+
45
+ #include <openssl/bio.h>
46
+ #include <openssl/crypto.h> /* For OPENSSL_free */
47
+ #include <openssl/err.h>
48
+ #include <openssl/ssl.h>
49
+ #include <openssl/x509.h>
50
+ #include <openssl/x509v3.h>
51
+
52
+ /* --- Constants. ---*/
53
+
54
+ #define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND 16384
55
+ #define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND 1024
56
+
57
+ /* Putting a macro like this and littering the source file with #if is really
58
+ bad practice.
59
+ TODO(jboeuf): refactor all the #if / #endif in a separate module. */
60
+ #ifndef TSI_OPENSSL_ALPN_SUPPORT
61
+ #define TSI_OPENSSL_ALPN_SUPPORT 1
62
+ #endif
63
+
64
+ /* TODO(jboeuf): I have not found a way to get this number dynamically from the
65
+ SSL structure. This is what we would ultimately want though... */
66
+ #define TSI_SSL_MAX_PROTECTION_OVERHEAD 100
67
+
68
+ /* --- Structure definitions. ---*/
69
+
70
+ struct tsi_ssl_handshaker_factory {
71
+ tsi_result (*create_handshaker)(tsi_ssl_handshaker_factory *self,
72
+ const char *server_name_indication,
73
+ tsi_handshaker **handshaker);
74
+ void (*destroy)(tsi_ssl_handshaker_factory *self);
75
+ };
76
+
77
+ typedef struct {
78
+ tsi_ssl_handshaker_factory base;
79
+ SSL_CTX *ssl_context;
80
+ unsigned char *alpn_protocol_list;
81
+ size_t alpn_protocol_list_length;
82
+ } tsi_ssl_client_handshaker_factory;
83
+
84
+ typedef struct {
85
+ tsi_ssl_handshaker_factory base;
86
+
87
+ /* Several contexts to support SNI.
88
+ The tsi_peer array contains the subject names of the server certificates
89
+ associated with the contexts at the same index. */
90
+ SSL_CTX **ssl_contexts;
91
+ tsi_peer *ssl_context_x509_subject_names;
92
+ size_t ssl_context_count;
93
+ unsigned char *alpn_protocol_list;
94
+ size_t alpn_protocol_list_length;
95
+ } tsi_ssl_server_handshaker_factory;
96
+
97
+ typedef struct {
98
+ tsi_handshaker base;
99
+ SSL *ssl;
100
+ BIO *into_ssl;
101
+ BIO *from_ssl;
102
+ tsi_result result;
103
+ } tsi_ssl_handshaker;
104
+
105
+ typedef struct {
106
+ tsi_frame_protector base;
107
+ SSL *ssl;
108
+ BIO *into_ssl;
109
+ BIO *from_ssl;
110
+ unsigned char *buffer;
111
+ size_t buffer_size;
112
+ size_t buffer_offset;
113
+ } tsi_ssl_frame_protector;
114
+
115
+ /* --- Library Initialization. ---*/
116
+
117
+ static gpr_once init_openssl_once = GPR_ONCE_INIT;
118
+ static gpr_mu *openssl_mutexes = NULL;
119
+
120
+ static void openssl_locking_cb(int mode, int type, const char *file, int line) {
121
+ if (mode & CRYPTO_LOCK) {
122
+ gpr_mu_lock(&openssl_mutexes[type]);
123
+ } else {
124
+ gpr_mu_unlock(&openssl_mutexes[type]);
125
+ }
126
+ }
127
+
128
+ static unsigned long openssl_thread_id_cb(void) {
129
+ return (unsigned long)gpr_thd_currentid();
130
+ }
131
+
132
+ static void init_openssl(void) {
133
+ int i;
134
+ int num_locks;
135
+ SSL_library_init();
136
+ SSL_load_error_strings();
137
+ OpenSSL_add_all_algorithms();
138
+ num_locks = CRYPTO_num_locks();
139
+ GPR_ASSERT(num_locks > 0);
140
+ openssl_mutexes = malloc((size_t)num_locks * sizeof(gpr_mu));
141
+ GPR_ASSERT(openssl_mutexes != NULL);
142
+ for (i = 0; i < CRYPTO_num_locks(); i++) {
143
+ gpr_mu_init(&openssl_mutexes[i]);
144
+ }
145
+ CRYPTO_set_locking_callback(openssl_locking_cb);
146
+ CRYPTO_set_id_callback(openssl_thread_id_cb);
147
+ }
148
+
149
+ /* --- Ssl utils. ---*/
150
+
151
+ static const char *ssl_error_string(int error) {
152
+ switch (error) {
153
+ case SSL_ERROR_NONE:
154
+ return "SSL_ERROR_NONE";
155
+ case SSL_ERROR_ZERO_RETURN:
156
+ return "SSL_ERROR_ZERO_RETURN";
157
+ case SSL_ERROR_WANT_READ:
158
+ return "SSL_ERROR_WANT_READ";
159
+ case SSL_ERROR_WANT_WRITE:
160
+ return "SSL_ERROR_WANT_WRITE";
161
+ case SSL_ERROR_WANT_CONNECT:
162
+ return "SSL_ERROR_WANT_CONNECT";
163
+ case SSL_ERROR_WANT_ACCEPT:
164
+ return "SSL_ERROR_WANT_ACCEPT";
165
+ case SSL_ERROR_WANT_X509_LOOKUP:
166
+ return "SSL_ERROR_WANT_X509_LOOKUP";
167
+ case SSL_ERROR_SYSCALL:
168
+ return "SSL_ERROR_SYSCALL";
169
+ case SSL_ERROR_SSL:
170
+ return "SSL_ERROR_SSL";
171
+ default:
172
+ return "Unknown error";
173
+ }
174
+ }
175
+
176
+ /* TODO(jboeuf): Remove when we are past the debugging phase with this code. */
177
+ static void ssl_log_where_info(const SSL *ssl, int where, int flag,
178
+ const char *msg) {
179
+ if ((where & flag) && tsi_tracing_enabled) {
180
+ gpr_log(GPR_INFO, "%20.20s - %30.30s - %5.10s", msg,
181
+ SSL_state_string_long(ssl), SSL_state_string(ssl));
182
+ }
183
+ }
184
+
185
+ /* Used for debugging. TODO(jboeuf): Remove when code is mature enough. */
186
+ static void ssl_info_callback(const SSL *ssl, int where, int ret) {
187
+ if (ret == 0) {
188
+ gpr_log(GPR_ERROR, "ssl_info_callback: error occured.\n");
189
+ return;
190
+ }
191
+
192
+ ssl_log_where_info(ssl, where, SSL_CB_LOOP, "LOOP");
193
+ ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START");
194
+ ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE");
195
+ }
196
+
197
+ /* Returns 1 if name looks like an IP address, 0 otherwise.
198
+ This is a very rough heuristic as it does not handle IPV6 or things like:
199
+ 0300.0250.00.01, 0xC0.0Xa8.0x0.0x1, 000030052000001, 0xc0.052000001 */
200
+ static int looks_like_ip_address(const char *name) {
201
+ size_t i;
202
+ size_t dot_count = 0;
203
+ size_t num_size = 0;
204
+ for (i = 0; i < strlen(name); i++) {
205
+ if (name[i] >= '0' && name[i] <= '9') {
206
+ if (num_size > 3) return 0;
207
+ num_size++;
208
+ } else if (name[i] == '.') {
209
+ if (dot_count > 3 || num_size == 0) return 0;
210
+ dot_count++;
211
+ num_size = 0;
212
+ } else {
213
+ return 0;
214
+ }
215
+ }
216
+ if (dot_count < 3 || num_size == 0) return 0;
217
+ return 1;
218
+ }
219
+
220
+ /* Gets the subject CN from an X509 cert. */
221
+ static tsi_result ssl_get_x509_common_name(X509 *cert, unsigned char **utf8,
222
+ size_t *utf8_size) {
223
+ int common_name_index = -1;
224
+ X509_NAME_ENTRY *common_name_entry = NULL;
225
+ ASN1_STRING *common_name_asn1 = NULL;
226
+ X509_NAME *subject_name = X509_get_subject_name(cert);
227
+ int utf8_returned_size = 0;
228
+ if (subject_name == NULL) {
229
+ gpr_log(GPR_ERROR, "Could not get subject name from certificate.");
230
+ return TSI_NOT_FOUND;
231
+ }
232
+ common_name_index =
233
+ X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
234
+ if (common_name_index == -1) {
235
+ gpr_log(GPR_ERROR,
236
+ "Could not get common name of subject from certificate.");
237
+ return TSI_NOT_FOUND;
238
+ }
239
+ common_name_entry = X509_NAME_get_entry(subject_name, common_name_index);
240
+ if (common_name_entry == NULL) {
241
+ gpr_log(GPR_ERROR, "Could not get common name entry from certificate.");
242
+ return TSI_INTERNAL_ERROR;
243
+ }
244
+ common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
245
+ if (common_name_asn1 == NULL) {
246
+ gpr_log(GPR_ERROR,
247
+ "Could not get common name entry asn1 from certificate.");
248
+ return TSI_INTERNAL_ERROR;
249
+ }
250
+ utf8_returned_size = ASN1_STRING_to_UTF8(utf8, common_name_asn1);
251
+ if (utf8_returned_size < 0) {
252
+ gpr_log(GPR_ERROR, "Could not extract utf8 from asn1 string.");
253
+ return TSI_OUT_OF_RESOURCES;
254
+ }
255
+ *utf8_size = (size_t)utf8_returned_size;
256
+ return TSI_OK;
257
+ }
258
+
259
+ /* Gets the subject CN of an X509 cert as a tsi_peer_property. */
260
+ static tsi_result peer_property_from_x509_common_name(
261
+ X509 *cert, tsi_peer_property *property) {
262
+ unsigned char *common_name;
263
+ size_t common_name_size;
264
+ tsi_result result =
265
+ ssl_get_x509_common_name(cert, &common_name, &common_name_size);
266
+ if (result != TSI_OK) {
267
+ if (result == TSI_NOT_FOUND) {
268
+ common_name = NULL;
269
+ common_name_size = 0;
270
+ } else {
271
+ return result;
272
+ }
273
+ }
274
+ result = tsi_construct_string_peer_property(
275
+ TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY,
276
+ common_name == NULL ? "" : (const char *)common_name, common_name_size,
277
+ property);
278
+ OPENSSL_free(common_name);
279
+ return result;
280
+ }
281
+
282
+ /* Gets the subject SANs from an X509 cert as a tsi_peer_property. */
283
+ static tsi_result add_subject_alt_names_properties_to_peer(
284
+ tsi_peer *peer, GENERAL_NAMES *subject_alt_names,
285
+ size_t subject_alt_name_count) {
286
+ size_t i;
287
+ tsi_result result = TSI_OK;
288
+
289
+ /* Reset for DNS entries filtering. */
290
+ peer->property_count -= subject_alt_name_count;
291
+
292
+ for (i = 0; i < subject_alt_name_count; i++) {
293
+ GENERAL_NAME *subject_alt_name =
294
+ sk_GENERAL_NAME_value(subject_alt_names, (int)i);
295
+ /* Filter out the non-dns entries names. */
296
+ if (subject_alt_name->type == GEN_DNS) {
297
+ unsigned char *dns_name = NULL;
298
+ int dns_name_size =
299
+ ASN1_STRING_to_UTF8(&dns_name, subject_alt_name->d.dNSName);
300
+ if (dns_name_size < 0) {
301
+ gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string.");
302
+ result = TSI_INTERNAL_ERROR;
303
+ break;
304
+ }
305
+ result = tsi_construct_string_peer_property(
306
+ TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
307
+ (const char *)dns_name, (size_t)dns_name_size,
308
+ &peer->properties[peer->property_count++]);
309
+ OPENSSL_free(dns_name);
310
+ if (result != TSI_OK) break;
311
+ }
312
+ }
313
+ return result;
314
+ }
315
+
316
+ /* Gets information about the peer's X509 cert as a tsi_peer object. */
317
+ static tsi_result peer_from_x509(X509 *cert, int include_certificate_type,
318
+ tsi_peer *peer) {
319
+ /* TODO(jboeuf): Maybe add more properties. */
320
+ GENERAL_NAMES *subject_alt_names =
321
+ X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
322
+ int subject_alt_name_count = (subject_alt_names != NULL)
323
+ ? (int)sk_GENERAL_NAME_num(subject_alt_names)
324
+ : 0;
325
+ size_t property_count;
326
+ tsi_result result;
327
+ GPR_ASSERT(subject_alt_name_count >= 0);
328
+ property_count = (include_certificate_type ? (size_t)1 : 0) +
329
+ 1 /* common name */ + (size_t)subject_alt_name_count;
330
+ result = tsi_construct_peer(property_count, peer);
331
+ if (result != TSI_OK) return result;
332
+ do {
333
+ if (include_certificate_type) {
334
+ result = tsi_construct_string_peer_property_from_cstring(
335
+ TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
336
+ &peer->properties[0]);
337
+ if (result != TSI_OK) break;
338
+ }
339
+ result = peer_property_from_x509_common_name(
340
+ cert, &peer->properties[include_certificate_type ? 1 : 0]);
341
+ if (result != TSI_OK) break;
342
+
343
+ if (subject_alt_name_count != 0) {
344
+ result = add_subject_alt_names_properties_to_peer(
345
+ peer, subject_alt_names, (size_t)subject_alt_name_count);
346
+ if (result != TSI_OK) break;
347
+ }
348
+ } while (0);
349
+
350
+ if (subject_alt_names != NULL) {
351
+ sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free);
352
+ }
353
+ if (result != TSI_OK) tsi_peer_destruct(peer);
354
+ return result;
355
+ }
356
+
357
+ /* Logs the SSL error stack. */
358
+ static void log_ssl_error_stack(void) {
359
+ unsigned long err;
360
+ while ((err = ERR_get_error()) != 0) {
361
+ char details[256];
362
+ ERR_error_string_n((uint32_t)err, details, sizeof(details));
363
+ gpr_log(GPR_ERROR, "%s", details);
364
+ }
365
+ }
366
+
367
+ /* Performs an SSL_read and handle errors. */
368
+ static tsi_result do_ssl_read(SSL *ssl, unsigned char *unprotected_bytes,
369
+ size_t *unprotected_bytes_size) {
370
+ int read_from_ssl;
371
+ GPR_ASSERT(*unprotected_bytes_size <= INT_MAX);
372
+ read_from_ssl =
373
+ SSL_read(ssl, unprotected_bytes, (int)*unprotected_bytes_size);
374
+ if (read_from_ssl == 0) {
375
+ gpr_log(GPR_ERROR, "SSL_read returned 0 unexpectedly.");
376
+ return TSI_INTERNAL_ERROR;
377
+ }
378
+ if (read_from_ssl < 0) {
379
+ read_from_ssl = SSL_get_error(ssl, read_from_ssl);
380
+ switch (read_from_ssl) {
381
+ case SSL_ERROR_WANT_READ:
382
+ /* We need more data to finish the frame. */
383
+ *unprotected_bytes_size = 0;
384
+ return TSI_OK;
385
+ case SSL_ERROR_WANT_WRITE:
386
+ gpr_log(
387
+ GPR_ERROR,
388
+ "Peer tried to renegotiate SSL connection. This is unsupported.");
389
+ return TSI_UNIMPLEMENTED;
390
+ case SSL_ERROR_SSL:
391
+ gpr_log(GPR_ERROR, "Corruption detected.");
392
+ log_ssl_error_stack();
393
+ return TSI_DATA_CORRUPTED;
394
+ default:
395
+ gpr_log(GPR_ERROR, "SSL_read failed with error %s.",
396
+ ssl_error_string(read_from_ssl));
397
+ return TSI_PROTOCOL_FAILURE;
398
+ }
399
+ }
400
+ *unprotected_bytes_size = (size_t)read_from_ssl;
401
+ return TSI_OK;
402
+ }
403
+
404
+ /* Performs an SSL_write and handle errors. */
405
+ static tsi_result do_ssl_write(SSL *ssl, unsigned char *unprotected_bytes,
406
+ size_t unprotected_bytes_size) {
407
+ int ssl_write_result;
408
+ GPR_ASSERT(unprotected_bytes_size <= INT_MAX);
409
+ ssl_write_result =
410
+ SSL_write(ssl, unprotected_bytes, (int)unprotected_bytes_size);
411
+ if (ssl_write_result < 0) {
412
+ ssl_write_result = SSL_get_error(ssl, ssl_write_result);
413
+ if (ssl_write_result == SSL_ERROR_WANT_READ) {
414
+ gpr_log(GPR_ERROR,
415
+ "Peer tried to renegotiate SSL connection. This is unsupported.");
416
+ return TSI_UNIMPLEMENTED;
417
+ } else {
418
+ gpr_log(GPR_ERROR, "SSL_write failed with error %s.",
419
+ ssl_error_string(ssl_write_result));
420
+ return TSI_INTERNAL_ERROR;
421
+ }
422
+ }
423
+ return TSI_OK;
424
+ }
425
+
426
+ /* Loads an in-memory PEM certificate chain into the SSL context. */
427
+ static tsi_result ssl_ctx_use_certificate_chain(
428
+ SSL_CTX *context, const unsigned char *pem_cert_chain,
429
+ size_t pem_cert_chain_size) {
430
+ tsi_result result = TSI_OK;
431
+ X509 *certificate = NULL;
432
+ BIO *pem;
433
+ GPR_ASSERT(pem_cert_chain_size <= INT_MAX);
434
+ pem = BIO_new_mem_buf((void *)pem_cert_chain, (int)pem_cert_chain_size);
435
+ if (pem == NULL) return TSI_OUT_OF_RESOURCES;
436
+
437
+ do {
438
+ certificate = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
439
+ if (certificate == NULL) {
440
+ result = TSI_INVALID_ARGUMENT;
441
+ break;
442
+ }
443
+ if (!SSL_CTX_use_certificate(context, certificate)) {
444
+ result = TSI_INVALID_ARGUMENT;
445
+ break;
446
+ }
447
+ while (1) {
448
+ X509 *certificate_authority = PEM_read_bio_X509(pem, NULL, NULL, "");
449
+ if (certificate_authority == NULL) {
450
+ ERR_clear_error();
451
+ break; /* Done reading. */
452
+ }
453
+ if (!SSL_CTX_add_extra_chain_cert(context, certificate_authority)) {
454
+ X509_free(certificate_authority);
455
+ result = TSI_INVALID_ARGUMENT;
456
+ break;
457
+ }
458
+ /* We don't need to free certificate_authority as its ownership has been
459
+ transfered to the context. That is not the case for certificate though.
460
+ */
461
+ }
462
+ } while (0);
463
+
464
+ if (certificate != NULL) X509_free(certificate);
465
+ BIO_free(pem);
466
+ return result;
467
+ }
468
+
469
+ /* Loads an in-memory PEM private key into the SSL context. */
470
+ static tsi_result ssl_ctx_use_private_key(SSL_CTX *context,
471
+ const unsigned char *pem_key,
472
+ size_t pem_key_size) {
473
+ tsi_result result = TSI_OK;
474
+ EVP_PKEY *private_key = NULL;
475
+ BIO *pem;
476
+ GPR_ASSERT(pem_key_size <= INT_MAX);
477
+ pem = BIO_new_mem_buf((void *)pem_key, (int)pem_key_size);
478
+ if (pem == NULL) return TSI_OUT_OF_RESOURCES;
479
+ do {
480
+ private_key = PEM_read_bio_PrivateKey(pem, NULL, NULL, "");
481
+ if (private_key == NULL) {
482
+ result = TSI_INVALID_ARGUMENT;
483
+ break;
484
+ }
485
+ if (!SSL_CTX_use_PrivateKey(context, private_key)) {
486
+ result = TSI_INVALID_ARGUMENT;
487
+ break;
488
+ }
489
+ } while (0);
490
+ if (private_key != NULL) EVP_PKEY_free(private_key);
491
+ BIO_free(pem);
492
+ return result;
493
+ }
494
+
495
+ /* Loads in-memory PEM verification certs into the SSL context and optionally
496
+ returns the verification cert names (root_names can be NULL). */
497
+ static tsi_result ssl_ctx_load_verification_certs(
498
+ SSL_CTX *context, const unsigned char *pem_roots, size_t pem_roots_size,
499
+ STACK_OF(X509_NAME) * *root_names) {
500
+ tsi_result result = TSI_OK;
501
+ size_t num_roots = 0;
502
+ X509 *root = NULL;
503
+ X509_NAME *root_name = NULL;
504
+ BIO *pem;
505
+ X509_STORE *root_store;
506
+ GPR_ASSERT(pem_roots_size <= INT_MAX);
507
+ pem = BIO_new_mem_buf((void *)pem_roots, (int)pem_roots_size);
508
+ root_store = SSL_CTX_get_cert_store(context);
509
+ if (root_store == NULL) return TSI_INVALID_ARGUMENT;
510
+ if (pem == NULL) return TSI_OUT_OF_RESOURCES;
511
+ if (root_names != NULL) {
512
+ *root_names = sk_X509_NAME_new_null();
513
+ if (*root_names == NULL) return TSI_OUT_OF_RESOURCES;
514
+ }
515
+
516
+ while (1) {
517
+ root = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
518
+ if (root == NULL) {
519
+ ERR_clear_error();
520
+ break; /* We're at the end of stream. */
521
+ }
522
+ if (root_names != NULL) {
523
+ root_name = X509_get_subject_name(root);
524
+ if (root_name == NULL) {
525
+ gpr_log(GPR_ERROR, "Could not get name from root certificate.");
526
+ result = TSI_INVALID_ARGUMENT;
527
+ break;
528
+ }
529
+ root_name = X509_NAME_dup(root_name);
530
+ if (root_name == NULL) {
531
+ result = TSI_OUT_OF_RESOURCES;
532
+ break;
533
+ }
534
+ sk_X509_NAME_push(*root_names, root_name);
535
+ root_name = NULL;
536
+ }
537
+ if (!X509_STORE_add_cert(root_store, root)) {
538
+ gpr_log(GPR_ERROR, "Could not add root certificate to ssl context.");
539
+ result = TSI_INTERNAL_ERROR;
540
+ break;
541
+ }
542
+ X509_free(root);
543
+ num_roots++;
544
+ }
545
+
546
+ if (num_roots == 0) {
547
+ gpr_log(GPR_ERROR, "Could not load any root certificate.");
548
+ result = TSI_INVALID_ARGUMENT;
549
+ }
550
+
551
+ if (result != TSI_OK) {
552
+ if (root != NULL) X509_free(root);
553
+ if (root_names != NULL) {
554
+ sk_X509_NAME_pop_free(*root_names, X509_NAME_free);
555
+ *root_names = NULL;
556
+ if (root_name != NULL) X509_NAME_free(root_name);
557
+ }
558
+ }
559
+ BIO_free(pem);
560
+ return result;
561
+ }
562
+
563
+ /* Populates the SSL context with a private key and a cert chain, and sets the
564
+ cipher list and the ephemeral ECDH key. */
565
+ static tsi_result populate_ssl_context(
566
+ SSL_CTX *context, const unsigned char *pem_private_key,
567
+ size_t pem_private_key_size, const unsigned char *pem_certificate_chain,
568
+ size_t pem_certificate_chain_size, const char *cipher_list) {
569
+ tsi_result result = TSI_OK;
570
+ if (pem_certificate_chain != NULL) {
571
+ result = ssl_ctx_use_certificate_chain(context, pem_certificate_chain,
572
+ pem_certificate_chain_size);
573
+ if (result != TSI_OK) {
574
+ gpr_log(GPR_ERROR, "Invalid cert chain file.");
575
+ return result;
576
+ }
577
+ }
578
+ if (pem_private_key != NULL) {
579
+ result =
580
+ ssl_ctx_use_private_key(context, pem_private_key, pem_private_key_size);
581
+ if (result != TSI_OK || !SSL_CTX_check_private_key(context)) {
582
+ gpr_log(GPR_ERROR, "Invalid private key.");
583
+ return result != TSI_OK ? result : TSI_INVALID_ARGUMENT;
584
+ }
585
+ }
586
+ if ((cipher_list != NULL) && !SSL_CTX_set_cipher_list(context, cipher_list)) {
587
+ gpr_log(GPR_ERROR, "Invalid cipher list: %s.", cipher_list);
588
+ return TSI_INVALID_ARGUMENT;
589
+ }
590
+ {
591
+ EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
592
+ if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) {
593
+ gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key.");
594
+ EC_KEY_free(ecdh);
595
+ return TSI_INTERNAL_ERROR;
596
+ }
597
+ SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
598
+ EC_KEY_free(ecdh);
599
+ }
600
+ return TSI_OK;
601
+ }
602
+
603
+ /* Extracts the CN and the SANs from an X509 cert as a peer object. */
604
+ static tsi_result extract_x509_subject_names_from_pem_cert(
605
+ const unsigned char *pem_cert, size_t pem_cert_size, tsi_peer *peer) {
606
+ tsi_result result = TSI_OK;
607
+ X509 *cert = NULL;
608
+ BIO *pem;
609
+ GPR_ASSERT(pem_cert_size <= INT_MAX);
610
+ pem = BIO_new_mem_buf((void *)pem_cert, (int)pem_cert_size);
611
+ if (pem == NULL) return TSI_OUT_OF_RESOURCES;
612
+
613
+ cert = PEM_read_bio_X509(pem, NULL, NULL, "");
614
+ if (cert == NULL) {
615
+ gpr_log(GPR_ERROR, "Invalid certificate");
616
+ result = TSI_INVALID_ARGUMENT;
617
+ } else {
618
+ result = peer_from_x509(cert, 0, peer);
619
+ }
620
+ if (cert != NULL) X509_free(cert);
621
+ BIO_free(pem);
622
+ return result;
623
+ }
624
+
625
+ /* Builds the alpn protocol name list according to rfc 7301. */
626
+ static tsi_result build_alpn_protocol_name_list(
627
+ const unsigned char **alpn_protocols,
628
+ const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
629
+ unsigned char **protocol_name_list, size_t *protocol_name_list_length) {
630
+ uint16_t i;
631
+ unsigned char *current;
632
+ *protocol_name_list = NULL;
633
+ *protocol_name_list_length = 0;
634
+ if (num_alpn_protocols == 0) return TSI_INVALID_ARGUMENT;
635
+ for (i = 0; i < num_alpn_protocols; i++) {
636
+ if (alpn_protocols_lengths[i] == 0) {
637
+ gpr_log(GPR_ERROR, "Invalid 0-length protocol name.");
638
+ return TSI_INVALID_ARGUMENT;
639
+ }
640
+ *protocol_name_list_length += (size_t)alpn_protocols_lengths[i] + 1;
641
+ }
642
+ *protocol_name_list = malloc(*protocol_name_list_length);
643
+ if (*protocol_name_list == NULL) return TSI_OUT_OF_RESOURCES;
644
+ current = *protocol_name_list;
645
+ for (i = 0; i < num_alpn_protocols; i++) {
646
+ *(current++) = alpn_protocols_lengths[i];
647
+ memcpy(current, alpn_protocols[i], alpn_protocols_lengths[i]);
648
+ current += alpn_protocols_lengths[i];
649
+ }
650
+ /* Safety check. */
651
+ if ((current < *protocol_name_list) ||
652
+ ((gpr_uintptr)(current - *protocol_name_list) !=
653
+ *protocol_name_list_length)) {
654
+ return TSI_INTERNAL_ERROR;
655
+ }
656
+ return TSI_OK;
657
+ }
658
+
659
+ /* --- tsi_frame_protector methods implementation. ---*/
660
+
661
+ static tsi_result ssl_protector_protect(tsi_frame_protector *self,
662
+ const unsigned char *unprotected_bytes,
663
+ size_t *unprotected_bytes_size,
664
+ unsigned char *protected_output_frames,
665
+ size_t *protected_output_frames_size) {
666
+ tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
667
+ int read_from_ssl;
668
+ size_t available;
669
+ tsi_result result = TSI_OK;
670
+
671
+ /* First see if we have some pending data in the SSL BIO. */
672
+ int pending_in_ssl = (int)BIO_pending(impl->from_ssl);
673
+ if (pending_in_ssl > 0) {
674
+ *unprotected_bytes_size = 0;
675
+ GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
676
+ read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
677
+ (int)*protected_output_frames_size);
678
+ if (read_from_ssl < 0) {
679
+ gpr_log(GPR_ERROR,
680
+ "Could not read from BIO even though some data is pending");
681
+ return TSI_INTERNAL_ERROR;
682
+ }
683
+ *protected_output_frames_size = (size_t)read_from_ssl;
684
+ return TSI_OK;
685
+ }
686
+
687
+ /* Now see if we can send a complete frame. */
688
+ available = impl->buffer_size - impl->buffer_offset;
689
+ if (available > *unprotected_bytes_size) {
690
+ /* If we cannot, just copy the data in our internal buffer. */
691
+ memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes,
692
+ *unprotected_bytes_size);
693
+ impl->buffer_offset += *unprotected_bytes_size;
694
+ *protected_output_frames_size = 0;
695
+ return TSI_OK;
696
+ }
697
+
698
+ /* If we can, prepare the buffer, send it to SSL_write and read. */
699
+ memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes, available);
700
+ result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_size);
701
+ if (result != TSI_OK) return result;
702
+
703
+ GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
704
+ read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
705
+ (int)*protected_output_frames_size);
706
+ if (read_from_ssl < 0) {
707
+ gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
708
+ return TSI_INTERNAL_ERROR;
709
+ }
710
+ *protected_output_frames_size = (size_t)read_from_ssl;
711
+ *unprotected_bytes_size = available;
712
+ impl->buffer_offset = 0;
713
+ return TSI_OK;
714
+ }
715
+
716
+ static tsi_result ssl_protector_protect_flush(
717
+ tsi_frame_protector *self, unsigned char *protected_output_frames,
718
+ size_t *protected_output_frames_size, size_t *still_pending_size) {
719
+ tsi_result result = TSI_OK;
720
+ tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
721
+ int read_from_ssl = 0;
722
+ int pending;
723
+
724
+ if (impl->buffer_offset != 0) {
725
+ result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_offset);
726
+ if (result != TSI_OK) return result;
727
+ impl->buffer_offset = 0;
728
+ }
729
+
730
+ pending = (int)BIO_pending(impl->from_ssl);
731
+ GPR_ASSERT(pending >= 0);
732
+ *still_pending_size = (size_t)pending;
733
+ if (*still_pending_size == 0) return TSI_OK;
734
+
735
+ GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
736
+ read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
737
+ (int)*protected_output_frames_size);
738
+ if (read_from_ssl <= 0) {
739
+ gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
740
+ return TSI_INTERNAL_ERROR;
741
+ }
742
+ *protected_output_frames_size = (size_t)read_from_ssl;
743
+ pending = (int)BIO_pending(impl->from_ssl);
744
+ GPR_ASSERT(pending >= 0);
745
+ *still_pending_size = (size_t)pending;
746
+ return TSI_OK;
747
+ }
748
+
749
+ static tsi_result ssl_protector_unprotect(
750
+ tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
751
+ size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
752
+ size_t *unprotected_bytes_size) {
753
+ tsi_result result = TSI_OK;
754
+ int written_into_ssl = 0;
755
+ size_t output_bytes_size = *unprotected_bytes_size;
756
+ size_t output_bytes_offset = 0;
757
+ tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
758
+
759
+ /* First, try to read remaining data from ssl. */
760
+ result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
761
+ if (result != TSI_OK) return result;
762
+ if (*unprotected_bytes_size == output_bytes_size) {
763
+ /* We have read everything we could and cannot process any more input. */
764
+ *protected_frames_bytes_size = 0;
765
+ return TSI_OK;
766
+ }
767
+ output_bytes_offset = *unprotected_bytes_size;
768
+ unprotected_bytes += output_bytes_offset;
769
+ *unprotected_bytes_size = output_bytes_size - output_bytes_offset;
770
+
771
+ /* Then, try to write some data to ssl. */
772
+ GPR_ASSERT(*protected_frames_bytes_size <= INT_MAX);
773
+ written_into_ssl = BIO_write(impl->into_ssl, protected_frames_bytes,
774
+ (int)*protected_frames_bytes_size);
775
+ if (written_into_ssl < 0) {
776
+ gpr_log(GPR_ERROR, "Sending protected frame to ssl failed with %d",
777
+ written_into_ssl);
778
+ return TSI_INTERNAL_ERROR;
779
+ }
780
+ *protected_frames_bytes_size = (size_t)written_into_ssl;
781
+
782
+ /* Now try to read some data again. */
783
+ result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
784
+ if (result == TSI_OK) {
785
+ /* Don't forget to output the total number of bytes read. */
786
+ *unprotected_bytes_size += output_bytes_offset;
787
+ }
788
+ return result;
789
+ }
790
+
791
+ static void ssl_protector_destroy(tsi_frame_protector *self) {
792
+ tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
793
+ if (impl->buffer != NULL) free(impl->buffer);
794
+ if (impl->ssl != NULL) SSL_free(impl->ssl);
795
+ free(self);
796
+ }
797
+
798
+ static const tsi_frame_protector_vtable frame_protector_vtable = {
799
+ ssl_protector_protect, ssl_protector_protect_flush, ssl_protector_unprotect,
800
+ ssl_protector_destroy,
801
+ };
802
+
803
+ /* --- tsi_handshaker methods implementation. ---*/
804
+
805
+ static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
806
+ unsigned char *bytes,
807
+ size_t *bytes_size) {
808
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
809
+ int bytes_read_from_ssl = 0;
810
+ if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 ||
811
+ *bytes_size > INT_MAX) {
812
+ return TSI_INVALID_ARGUMENT;
813
+ }
814
+ GPR_ASSERT(*bytes_size <= INT_MAX);
815
+ bytes_read_from_ssl = BIO_read(impl->from_ssl, bytes, (int)*bytes_size);
816
+ if (bytes_read_from_ssl < 0) {
817
+ *bytes_size = 0;
818
+ if (!BIO_should_retry(impl->from_ssl)) {
819
+ impl->result = TSI_INTERNAL_ERROR;
820
+ return impl->result;
821
+ } else {
822
+ return TSI_OK;
823
+ }
824
+ }
825
+ *bytes_size = (size_t)bytes_read_from_ssl;
826
+ return BIO_pending(impl->from_ssl) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
827
+ }
828
+
829
+ static tsi_result ssl_handshaker_get_result(tsi_handshaker *self) {
830
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
831
+ if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
832
+ SSL_is_init_finished(impl->ssl)) {
833
+ impl->result = TSI_OK;
834
+ }
835
+ return impl->result;
836
+ }
837
+
838
+ static tsi_result ssl_handshaker_process_bytes_from_peer(
839
+ tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) {
840
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
841
+ int bytes_written_into_ssl_size = 0;
842
+ if (bytes == NULL || bytes_size == 0 || *bytes_size > INT_MAX) {
843
+ return TSI_INVALID_ARGUMENT;
844
+ }
845
+ GPR_ASSERT(*bytes_size <= INT_MAX);
846
+ bytes_written_into_ssl_size =
847
+ BIO_write(impl->into_ssl, bytes, (int)*bytes_size);
848
+ if (bytes_written_into_ssl_size < 0) {
849
+ gpr_log(GPR_ERROR, "Could not write to memory BIO.");
850
+ impl->result = TSI_INTERNAL_ERROR;
851
+ return impl->result;
852
+ }
853
+ *bytes_size = (size_t)bytes_written_into_ssl_size;
854
+
855
+ if (!tsi_handshaker_is_in_progress(self)) {
856
+ impl->result = TSI_OK;
857
+ return impl->result;
858
+ } else {
859
+ /* Get ready to get some bytes from SSL. */
860
+ int ssl_result = SSL_do_handshake(impl->ssl);
861
+ ssl_result = SSL_get_error(impl->ssl, ssl_result);
862
+ switch (ssl_result) {
863
+ case SSL_ERROR_WANT_READ:
864
+ if (BIO_pending(impl->from_ssl) == 0) {
865
+ /* We need more data. */
866
+ return TSI_INCOMPLETE_DATA;
867
+ } else {
868
+ return TSI_OK;
869
+ }
870
+ case SSL_ERROR_NONE:
871
+ return TSI_OK;
872
+ default: {
873
+ char err_str[256];
874
+ ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
875
+ gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
876
+ ssl_error_string(ssl_result), err_str);
877
+ impl->result = TSI_PROTOCOL_FAILURE;
878
+ return impl->result;
879
+ }
880
+ }
881
+ }
882
+ }
883
+
884
+ static tsi_result ssl_handshaker_extract_peer(tsi_handshaker *self,
885
+ tsi_peer *peer) {
886
+ tsi_result result = TSI_OK;
887
+ const unsigned char *alpn_selected = NULL;
888
+ unsigned int alpn_selected_len;
889
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
890
+ X509 *peer_cert = SSL_get_peer_certificate(impl->ssl);
891
+ if (peer_cert != NULL) {
892
+ result = peer_from_x509(peer_cert, 1, peer);
893
+ X509_free(peer_cert);
894
+ if (result != TSI_OK) return result;
895
+ }
896
+ #if TSI_OPENSSL_ALPN_SUPPORT
897
+ SSL_get0_alpn_selected(impl->ssl, &alpn_selected, &alpn_selected_len);
898
+ #endif /* TSI_OPENSSL_ALPN_SUPPORT */
899
+ if (alpn_selected == NULL) {
900
+ /* Try npn. */
901
+ SSL_get0_next_proto_negotiated(impl->ssl, &alpn_selected,
902
+ &alpn_selected_len);
903
+ }
904
+ if (alpn_selected != NULL) {
905
+ size_t i;
906
+ tsi_peer_property *new_properties =
907
+ calloc(1, sizeof(tsi_peer_property) * (peer->property_count + 1));
908
+ if (new_properties == NULL) return TSI_OUT_OF_RESOURCES;
909
+ for (i = 0; i < peer->property_count; i++) {
910
+ new_properties[i] = peer->properties[i];
911
+ }
912
+ result = tsi_construct_string_peer_property(
913
+ TSI_SSL_ALPN_SELECTED_PROTOCOL, (const char *)alpn_selected,
914
+ alpn_selected_len, &new_properties[peer->property_count]);
915
+ if (result != TSI_OK) {
916
+ free(new_properties);
917
+ return result;
918
+ }
919
+ if (peer->properties != NULL) free(peer->properties);
920
+ peer->property_count++;
921
+ peer->properties = new_properties;
922
+ }
923
+ return result;
924
+ }
925
+
926
+ static tsi_result ssl_handshaker_create_frame_protector(
927
+ tsi_handshaker *self, size_t *max_output_protected_frame_size,
928
+ tsi_frame_protector **protector) {
929
+ size_t actual_max_output_protected_frame_size =
930
+ TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
931
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
932
+ tsi_ssl_frame_protector *protector_impl =
933
+ calloc(1, sizeof(tsi_ssl_frame_protector));
934
+ if (protector_impl == NULL) {
935
+ return TSI_OUT_OF_RESOURCES;
936
+ }
937
+
938
+ if (max_output_protected_frame_size != NULL) {
939
+ if (*max_output_protected_frame_size >
940
+ TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND) {
941
+ *max_output_protected_frame_size =
942
+ TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
943
+ } else if (*max_output_protected_frame_size <
944
+ TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND) {
945
+ *max_output_protected_frame_size =
946
+ TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND;
947
+ }
948
+ actual_max_output_protected_frame_size = *max_output_protected_frame_size;
949
+ }
950
+ protector_impl->buffer_size =
951
+ actual_max_output_protected_frame_size - TSI_SSL_MAX_PROTECTION_OVERHEAD;
952
+ protector_impl->buffer = malloc(protector_impl->buffer_size);
953
+ if (protector_impl->buffer == NULL) {
954
+ gpr_log(GPR_ERROR,
955
+ "Could not allocated buffer for tsi_ssl_frame_protector.");
956
+ free(protector_impl);
957
+ return TSI_INTERNAL_ERROR;
958
+ }
959
+
960
+ /* Transfer ownership of ssl to the frame protector. It is OK as the caller
961
+ * cannot call anything else but destroy on the handshaker after this call. */
962
+ protector_impl->ssl = impl->ssl;
963
+ impl->ssl = NULL;
964
+ protector_impl->into_ssl = impl->into_ssl;
965
+ protector_impl->from_ssl = impl->from_ssl;
966
+
967
+ protector_impl->base.vtable = &frame_protector_vtable;
968
+ *protector = &protector_impl->base;
969
+ return TSI_OK;
970
+ }
971
+
972
+ static void ssl_handshaker_destroy(tsi_handshaker *self) {
973
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
974
+ SSL_free(impl->ssl); /* The BIO objects are owned by ssl */
975
+ free(impl);
976
+ }
977
+
978
+ static const tsi_handshaker_vtable handshaker_vtable = {
979
+ ssl_handshaker_get_bytes_to_send_to_peer,
980
+ ssl_handshaker_process_bytes_from_peer, ssl_handshaker_get_result,
981
+ ssl_handshaker_extract_peer, ssl_handshaker_create_frame_protector,
982
+ ssl_handshaker_destroy,
983
+ };
984
+
985
+ /* --- tsi_ssl_handshaker_factory common methods. --- */
986
+
987
+ tsi_result tsi_ssl_handshaker_factory_create_handshaker(
988
+ tsi_ssl_handshaker_factory *self, const char *server_name_indication,
989
+ tsi_handshaker **handshaker) {
990
+ if (self == NULL || handshaker == NULL) return TSI_INVALID_ARGUMENT;
991
+ return self->create_handshaker(self, server_name_indication, handshaker);
992
+ }
993
+
994
+ void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self) {
995
+ if (self == NULL) return;
996
+ self->destroy(self);
997
+ }
998
+
999
+ static tsi_result create_tsi_ssl_handshaker(SSL_CTX *ctx, int is_client,
1000
+ const char *server_name_indication,
1001
+ tsi_handshaker **handshaker) {
1002
+ SSL *ssl = SSL_new(ctx);
1003
+ BIO *into_ssl = NULL;
1004
+ BIO *from_ssl = NULL;
1005
+ tsi_ssl_handshaker *impl = NULL;
1006
+ *handshaker = NULL;
1007
+ if (ctx == NULL) {
1008
+ gpr_log(GPR_ERROR, "SSL Context is null. Should never happen.");
1009
+ return TSI_INTERNAL_ERROR;
1010
+ }
1011
+ if (ssl == NULL) {
1012
+ return TSI_OUT_OF_RESOURCES;
1013
+ }
1014
+ SSL_set_info_callback(ssl, ssl_info_callback);
1015
+
1016
+ into_ssl = BIO_new(BIO_s_mem());
1017
+ from_ssl = BIO_new(BIO_s_mem());
1018
+ if (into_ssl == NULL || from_ssl == NULL) {
1019
+ gpr_log(GPR_ERROR, "BIO_new failed.");
1020
+ SSL_free(ssl);
1021
+ if (into_ssl != NULL) BIO_free(into_ssl);
1022
+ if (from_ssl != NULL) BIO_free(into_ssl);
1023
+ return TSI_OUT_OF_RESOURCES;
1024
+ }
1025
+ SSL_set_bio(ssl, into_ssl, from_ssl);
1026
+ if (is_client) {
1027
+ int ssl_result;
1028
+ SSL_set_connect_state(ssl);
1029
+ if (server_name_indication != NULL) {
1030
+ if (!SSL_set_tlsext_host_name(ssl, server_name_indication)) {
1031
+ gpr_log(GPR_ERROR, "Invalid server name indication %s.",
1032
+ server_name_indication);
1033
+ SSL_free(ssl);
1034
+ return TSI_INTERNAL_ERROR;
1035
+ }
1036
+ }
1037
+ ssl_result = SSL_do_handshake(ssl);
1038
+ ssl_result = SSL_get_error(ssl, ssl_result);
1039
+ if (ssl_result != SSL_ERROR_WANT_READ) {
1040
+ gpr_log(GPR_ERROR,
1041
+ "Unexpected error received from first SSL_do_handshake call: %s",
1042
+ ssl_error_string(ssl_result));
1043
+ SSL_free(ssl);
1044
+ return TSI_INTERNAL_ERROR;
1045
+ }
1046
+ } else {
1047
+ SSL_set_accept_state(ssl);
1048
+ }
1049
+
1050
+ impl = calloc(1, sizeof(tsi_ssl_handshaker));
1051
+ if (impl == NULL) {
1052
+ SSL_free(ssl);
1053
+ return TSI_OUT_OF_RESOURCES;
1054
+ }
1055
+ impl->ssl = ssl;
1056
+ impl->into_ssl = into_ssl;
1057
+ impl->from_ssl = from_ssl;
1058
+ impl->result = TSI_HANDSHAKE_IN_PROGRESS;
1059
+ impl->base.vtable = &handshaker_vtable;
1060
+ *handshaker = &impl->base;
1061
+ return TSI_OK;
1062
+ }
1063
+
1064
+ static int select_protocol_list(const unsigned char **out,
1065
+ unsigned char *outlen,
1066
+ const unsigned char *client_list,
1067
+ size_t client_list_len,
1068
+ const unsigned char *server_list,
1069
+ size_t server_list_len) {
1070
+ const unsigned char *client_current = client_list;
1071
+ while ((unsigned int)(client_current - client_list) < client_list_len) {
1072
+ unsigned char client_current_len = *(client_current++);
1073
+ const unsigned char *server_current = server_list;
1074
+ while ((server_current >= server_list) &&
1075
+ (gpr_uintptr)(server_current - server_list) < server_list_len) {
1076
+ unsigned char server_current_len = *(server_current++);
1077
+ if ((client_current_len == server_current_len) &&
1078
+ !memcmp(client_current, server_current, server_current_len)) {
1079
+ *out = server_current;
1080
+ *outlen = server_current_len;
1081
+ return SSL_TLSEXT_ERR_OK;
1082
+ }
1083
+ server_current += server_current_len;
1084
+ }
1085
+ client_current += client_current_len;
1086
+ }
1087
+ return SSL_TLSEXT_ERR_NOACK;
1088
+ }
1089
+
1090
+ /* --- tsi_ssl__client_handshaker_factory methods implementation. --- */
1091
+
1092
+ static tsi_result ssl_client_handshaker_factory_create_handshaker(
1093
+ tsi_ssl_handshaker_factory *self, const char *server_name_indication,
1094
+ tsi_handshaker **handshaker) {
1095
+ tsi_ssl_client_handshaker_factory *impl =
1096
+ (tsi_ssl_client_handshaker_factory *)self;
1097
+ return create_tsi_ssl_handshaker(impl->ssl_context, 1, server_name_indication,
1098
+ handshaker);
1099
+ }
1100
+
1101
+ static void ssl_client_handshaker_factory_destroy(
1102
+ tsi_ssl_handshaker_factory *self) {
1103
+ tsi_ssl_client_handshaker_factory *impl =
1104
+ (tsi_ssl_client_handshaker_factory *)self;
1105
+ if (impl->ssl_context != NULL) SSL_CTX_free(impl->ssl_context);
1106
+ if (impl->alpn_protocol_list != NULL) free(impl->alpn_protocol_list);
1107
+ free(impl);
1108
+ }
1109
+
1110
+ static int client_handshaker_factory_npn_callback(SSL *ssl, unsigned char **out,
1111
+ unsigned char *outlen,
1112
+ const unsigned char *in,
1113
+ unsigned int inlen,
1114
+ void *arg) {
1115
+ tsi_ssl_client_handshaker_factory *factory =
1116
+ (tsi_ssl_client_handshaker_factory *)arg;
1117
+ return select_protocol_list((const unsigned char **)out, outlen,
1118
+ factory->alpn_protocol_list,
1119
+ factory->alpn_protocol_list_length, in, inlen);
1120
+ }
1121
+
1122
+ /* --- tsi_ssl_server_handshaker_factory methods implementation. --- */
1123
+
1124
+ static tsi_result ssl_server_handshaker_factory_create_handshaker(
1125
+ tsi_ssl_handshaker_factory *self, const char *server_name_indication,
1126
+ tsi_handshaker **handshaker) {
1127
+ tsi_ssl_server_handshaker_factory *impl =
1128
+ (tsi_ssl_server_handshaker_factory *)self;
1129
+ if (impl->ssl_context_count == 0 || server_name_indication != NULL) {
1130
+ return TSI_INVALID_ARGUMENT;
1131
+ }
1132
+ /* Create the handshaker with the first context. We will switch if needed
1133
+ because of SNI in ssl_server_handshaker_factory_servername_callback. */
1134
+ return create_tsi_ssl_handshaker(impl->ssl_contexts[0], 0, NULL, handshaker);
1135
+ }
1136
+
1137
+ static void ssl_server_handshaker_factory_destroy(
1138
+ tsi_ssl_handshaker_factory *self) {
1139
+ tsi_ssl_server_handshaker_factory *impl =
1140
+ (tsi_ssl_server_handshaker_factory *)self;
1141
+ size_t i;
1142
+ for (i = 0; i < impl->ssl_context_count; i++) {
1143
+ if (impl->ssl_contexts[i] != NULL) {
1144
+ SSL_CTX_free(impl->ssl_contexts[i]);
1145
+ tsi_peer_destruct(&impl->ssl_context_x509_subject_names[i]);
1146
+ }
1147
+ }
1148
+ if (impl->ssl_contexts != NULL) free(impl->ssl_contexts);
1149
+ if (impl->ssl_context_x509_subject_names != NULL) {
1150
+ free(impl->ssl_context_x509_subject_names);
1151
+ }
1152
+ if (impl->alpn_protocol_list != NULL) free(impl->alpn_protocol_list);
1153
+ free(impl);
1154
+ }
1155
+
1156
+ static int does_entry_match_name(const char *entry, size_t entry_length,
1157
+ const char *name) {
1158
+ const char *dot;
1159
+ const char *name_subdomain = NULL;
1160
+ size_t name_length = strlen(name);
1161
+ size_t name_subdomain_length;
1162
+ if (entry_length == 0) return 0;
1163
+
1164
+ /* Take care of '.' terminations. */
1165
+ if (name[name_length - 1] == '.') {
1166
+ name_length--;
1167
+ }
1168
+ if (entry[entry_length - 1] == '.') {
1169
+ entry_length--;
1170
+ if (entry_length == 0) return 0;
1171
+ }
1172
+
1173
+ if ((name_length == entry_length) &&
1174
+ strncmp(name, entry, entry_length) == 0) {
1175
+ return 1; /* Perfect match. */
1176
+ }
1177
+ if (entry[0] != '*') return 0;
1178
+
1179
+ /* Wildchar subdomain matching. */
1180
+ if (entry_length < 3 || entry[1] != '.') { /* At least *.x */
1181
+ gpr_log(GPR_ERROR, "Invalid wildchar entry.");
1182
+ return 0;
1183
+ }
1184
+ name_subdomain = strchr(name, '.');
1185
+ if (name_subdomain == NULL) return 0;
1186
+ name_subdomain_length = strlen(name_subdomain);
1187
+ if (name_subdomain_length < 2) return 0;
1188
+ name_subdomain++; /* Starts after the dot. */
1189
+ name_subdomain_length--;
1190
+ entry += 2; /* Remove *. */
1191
+ entry_length -= 2;
1192
+ dot = strchr(name_subdomain, '.');
1193
+ if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) {
1194
+ gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain);
1195
+ return 0;
1196
+ }
1197
+ if (name_subdomain[name_subdomain_length - 1] == '.') {
1198
+ name_subdomain_length--;
1199
+ }
1200
+ return ((entry_length > 0) && (name_subdomain_length == entry_length) &&
1201
+ strncmp(entry, name_subdomain, entry_length) == 0);
1202
+ }
1203
+
1204
+ static int ssl_server_handshaker_factory_servername_callback(SSL *ssl, int *ap,
1205
+ void *arg) {
1206
+ tsi_ssl_server_handshaker_factory *impl =
1207
+ (tsi_ssl_server_handshaker_factory *)arg;
1208
+ size_t i = 0;
1209
+ const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
1210
+ if (servername == NULL || strlen(servername) == 0) {
1211
+ return SSL_TLSEXT_ERR_NOACK;
1212
+ }
1213
+
1214
+ for (i = 0; i < impl->ssl_context_count; i++) {
1215
+ if (tsi_ssl_peer_matches_name(&impl->ssl_context_x509_subject_names[i],
1216
+ servername)) {
1217
+ SSL_set_SSL_CTX(ssl, impl->ssl_contexts[i]);
1218
+ return SSL_TLSEXT_ERR_OK;
1219
+ }
1220
+ }
1221
+ gpr_log(GPR_ERROR, "No match found for server name: %s.", servername);
1222
+ return SSL_TLSEXT_ERR_ALERT_WARNING;
1223
+ }
1224
+
1225
+ #if TSI_OPENSSL_ALPN_SUPPORT
1226
+ static int server_handshaker_factory_alpn_callback(
1227
+ SSL *ssl, const unsigned char **out, unsigned char *outlen,
1228
+ const unsigned char *in, unsigned int inlen, void *arg) {
1229
+ tsi_ssl_server_handshaker_factory *factory =
1230
+ (tsi_ssl_server_handshaker_factory *)arg;
1231
+ return select_protocol_list(out, outlen, in, inlen,
1232
+ factory->alpn_protocol_list,
1233
+ factory->alpn_protocol_list_length);
1234
+ }
1235
+ #endif /* TSI_OPENSSL_ALPN_SUPPORT */
1236
+
1237
+ static int server_handshaker_factory_npn_advertised_callback(
1238
+ SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) {
1239
+ tsi_ssl_server_handshaker_factory *factory =
1240
+ (tsi_ssl_server_handshaker_factory *)arg;
1241
+ *out = factory->alpn_protocol_list;
1242
+ GPR_ASSERT(factory->alpn_protocol_list_length <= UINT_MAX);
1243
+ *outlen = (unsigned int)factory->alpn_protocol_list_length;
1244
+ return SSL_TLSEXT_ERR_OK;
1245
+ }
1246
+
1247
+ /* --- tsi_ssl_handshaker_factory constructors. --- */
1248
+
1249
+ tsi_result tsi_create_ssl_client_handshaker_factory(
1250
+ const unsigned char *pem_private_key, size_t pem_private_key_size,
1251
+ const unsigned char *pem_cert_chain, size_t pem_cert_chain_size,
1252
+ const unsigned char *pem_root_certs, size_t pem_root_certs_size,
1253
+ const char *cipher_list, const unsigned char **alpn_protocols,
1254
+ const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
1255
+ tsi_ssl_handshaker_factory **factory) {
1256
+ SSL_CTX *ssl_context = NULL;
1257
+ tsi_ssl_client_handshaker_factory *impl = NULL;
1258
+ tsi_result result = TSI_OK;
1259
+
1260
+ gpr_once_init(&init_openssl_once, init_openssl);
1261
+
1262
+ if (factory == NULL) return TSI_INVALID_ARGUMENT;
1263
+ *factory = NULL;
1264
+ if (pem_root_certs == NULL) return TSI_INVALID_ARGUMENT;
1265
+
1266
+ ssl_context = SSL_CTX_new(TLSv1_2_method());
1267
+ if (ssl_context == NULL) {
1268
+ gpr_log(GPR_ERROR, "Could not create ssl context.");
1269
+ return TSI_INVALID_ARGUMENT;
1270
+ }
1271
+
1272
+ impl = calloc(1, sizeof(tsi_ssl_client_handshaker_factory));
1273
+ if (impl == NULL) {
1274
+ SSL_CTX_free(ssl_context);
1275
+ return TSI_OUT_OF_RESOURCES;
1276
+ }
1277
+ impl->ssl_context = ssl_context;
1278
+
1279
+ do {
1280
+ result =
1281
+ populate_ssl_context(ssl_context, pem_private_key, pem_private_key_size,
1282
+ pem_cert_chain, pem_cert_chain_size, cipher_list);
1283
+ if (result != TSI_OK) break;
1284
+ result = ssl_ctx_load_verification_certs(ssl_context, pem_root_certs,
1285
+ pem_root_certs_size, NULL);
1286
+ if (result != TSI_OK) {
1287
+ gpr_log(GPR_ERROR, "Cannot load server root certificates.");
1288
+ break;
1289
+ }
1290
+
1291
+ if (num_alpn_protocols != 0) {
1292
+ result = build_alpn_protocol_name_list(
1293
+ alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
1294
+ &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
1295
+ if (result != TSI_OK) {
1296
+ gpr_log(GPR_ERROR, "Building alpn list failed with error %s.",
1297
+ tsi_result_to_string(result));
1298
+ break;
1299
+ }
1300
+ #if TSI_OPENSSL_ALPN_SUPPORT
1301
+ GPR_ASSERT(impl->alpn_protocol_list_length < UINT_MAX);
1302
+ if (SSL_CTX_set_alpn_protos(
1303
+ ssl_context, impl->alpn_protocol_list,
1304
+ (unsigned int)impl->alpn_protocol_list_length)) {
1305
+ gpr_log(GPR_ERROR, "Could not set alpn protocol list to context.");
1306
+ result = TSI_INVALID_ARGUMENT;
1307
+ break;
1308
+ }
1309
+ #endif /* TSI_OPENSSL_ALPN_SUPPORT */
1310
+ SSL_CTX_set_next_proto_select_cb(
1311
+ ssl_context, client_handshaker_factory_npn_callback, impl);
1312
+ }
1313
+ } while (0);
1314
+ if (result != TSI_OK) {
1315
+ ssl_client_handshaker_factory_destroy(&impl->base);
1316
+ return result;
1317
+ }
1318
+ SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL);
1319
+ /* TODO(jboeuf): Add revocation verification. */
1320
+
1321
+ impl->base.create_handshaker =
1322
+ ssl_client_handshaker_factory_create_handshaker;
1323
+ impl->base.destroy = ssl_client_handshaker_factory_destroy;
1324
+ *factory = &impl->base;
1325
+ return TSI_OK;
1326
+ }
1327
+
1328
+ tsi_result tsi_create_ssl_server_handshaker_factory(
1329
+ const unsigned char **pem_private_keys,
1330
+ const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
1331
+ const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
1332
+ const unsigned char *pem_client_root_certs,
1333
+ size_t pem_client_root_certs_size, int force_client_auth,
1334
+ const char *cipher_list, const unsigned char **alpn_protocols,
1335
+ const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
1336
+ tsi_ssl_handshaker_factory **factory) {
1337
+ tsi_ssl_server_handshaker_factory *impl = NULL;
1338
+ tsi_result result = TSI_OK;
1339
+ size_t i = 0;
1340
+
1341
+ gpr_once_init(&init_openssl_once, init_openssl);
1342
+
1343
+ if (factory == NULL) return TSI_INVALID_ARGUMENT;
1344
+ *factory = NULL;
1345
+ if (key_cert_pair_count == 0 || pem_private_keys == NULL ||
1346
+ pem_cert_chains == NULL) {
1347
+ return TSI_INVALID_ARGUMENT;
1348
+ }
1349
+
1350
+ impl = calloc(1, sizeof(tsi_ssl_server_handshaker_factory));
1351
+ if (impl == NULL) return TSI_OUT_OF_RESOURCES;
1352
+ impl->base.create_handshaker =
1353
+ ssl_server_handshaker_factory_create_handshaker;
1354
+ impl->base.destroy = ssl_server_handshaker_factory_destroy;
1355
+ impl->ssl_contexts = calloc(key_cert_pair_count, sizeof(SSL_CTX *));
1356
+ impl->ssl_context_x509_subject_names =
1357
+ calloc(key_cert_pair_count, sizeof(tsi_peer));
1358
+ if (impl->ssl_contexts == NULL ||
1359
+ impl->ssl_context_x509_subject_names == NULL) {
1360
+ tsi_ssl_handshaker_factory_destroy(&impl->base);
1361
+ return TSI_OUT_OF_RESOURCES;
1362
+ }
1363
+ impl->ssl_context_count = key_cert_pair_count;
1364
+
1365
+ if (num_alpn_protocols > 0) {
1366
+ result = build_alpn_protocol_name_list(
1367
+ alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
1368
+ &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
1369
+ if (result != TSI_OK) {
1370
+ tsi_ssl_handshaker_factory_destroy(&impl->base);
1371
+ return result;
1372
+ }
1373
+ }
1374
+
1375
+ for (i = 0; i < key_cert_pair_count; i++) {
1376
+ do {
1377
+ impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
1378
+ if (impl->ssl_contexts[i] == NULL) {
1379
+ gpr_log(GPR_ERROR, "Could not create ssl context.");
1380
+ result = TSI_OUT_OF_RESOURCES;
1381
+ break;
1382
+ }
1383
+ result = populate_ssl_context(
1384
+ impl->ssl_contexts[i], pem_private_keys[i], pem_private_keys_sizes[i],
1385
+ pem_cert_chains[i], pem_cert_chains_sizes[i], cipher_list);
1386
+ if (result != TSI_OK) break;
1387
+
1388
+ if (pem_client_root_certs != NULL) {
1389
+ int flags = SSL_VERIFY_PEER;
1390
+ STACK_OF(X509_NAME) *root_names = NULL;
1391
+ result = ssl_ctx_load_verification_certs(
1392
+ impl->ssl_contexts[i], pem_client_root_certs,
1393
+ pem_client_root_certs_size, &root_names);
1394
+ if (result != TSI_OK) {
1395
+ gpr_log(GPR_ERROR, "Invalid verification certs.");
1396
+ break;
1397
+ }
1398
+ SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names);
1399
+ if (force_client_auth) flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1400
+ SSL_CTX_set_verify(impl->ssl_contexts[i], flags, NULL);
1401
+ /* TODO(jboeuf): Add revocation verification. */
1402
+ }
1403
+
1404
+ result = extract_x509_subject_names_from_pem_cert(
1405
+ pem_cert_chains[i], pem_cert_chains_sizes[i],
1406
+ &impl->ssl_context_x509_subject_names[i]);
1407
+ if (result != TSI_OK) break;
1408
+
1409
+ SSL_CTX_set_tlsext_servername_callback(
1410
+ impl->ssl_contexts[i],
1411
+ ssl_server_handshaker_factory_servername_callback);
1412
+ SSL_CTX_set_tlsext_servername_arg(impl->ssl_contexts[i], impl);
1413
+ #if TSI_OPENSSL_ALPN_SUPPORT
1414
+ SSL_CTX_set_alpn_select_cb(impl->ssl_contexts[i],
1415
+ server_handshaker_factory_alpn_callback, impl);
1416
+ #endif /* TSI_OPENSSL_ALPN_SUPPORT */
1417
+ SSL_CTX_set_next_protos_advertised_cb(
1418
+ impl->ssl_contexts[i],
1419
+ server_handshaker_factory_npn_advertised_callback, impl);
1420
+ } while (0);
1421
+
1422
+ if (result != TSI_OK) {
1423
+ tsi_ssl_handshaker_factory_destroy(&impl->base);
1424
+ return result;
1425
+ }
1426
+ }
1427
+ *factory = &impl->base;
1428
+ return TSI_OK;
1429
+ }
1430
+
1431
+ /* --- tsi_ssl utils. --- */
1432
+
1433
+ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
1434
+ size_t i = 0;
1435
+ size_t san_count = 0;
1436
+ const tsi_peer_property *cn_property = NULL;
1437
+
1438
+ /* For now reject what looks like an IP address. */
1439
+ if (looks_like_ip_address(name)) return 0;
1440
+
1441
+ /* Check the SAN first. */
1442
+ for (i = 0; i < peer->property_count; i++) {
1443
+ const tsi_peer_property *property = &peer->properties[i];
1444
+ if (property->name == NULL) continue;
1445
+ if (strcmp(property->name,
1446
+ TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
1447
+ san_count++;
1448
+ if (does_entry_match_name(property->value.data, property->value.length,
1449
+ name)) {
1450
+ return 1;
1451
+ }
1452
+ } else if (strcmp(property->name,
1453
+ TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
1454
+ cn_property = property;
1455
+ }
1456
+ }
1457
+
1458
+ /* If there's no SAN, try the CN. */
1459
+ if (san_count == 0 && cn_property != NULL) {
1460
+ if (does_entry_match_name(cn_property->value.data,
1461
+ cn_property->value.length, name)) {
1462
+ return 1;
1463
+ }
1464
+ }
1465
+
1466
+ return 0; /* Not found. */
1467
+ }