grpc 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (459) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +29456 -0
  3. data/Rakefile +13 -8
  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/{bin → src/ruby/bin}/apis/google/protobuf/empty.rb +0 -0
  373. data/{bin → src/ruby/bin}/apis/pubsub_demo.rb +7 -15
  374. data/{bin → src/ruby/bin}/apis/tech/pubsub/proto/pubsub.rb +0 -0
  375. data/{bin → src/ruby/bin}/apis/tech/pubsub/proto/pubsub_services.rb +0 -0
  376. data/{bin → src/ruby/bin}/grpc_ruby_interop_client +0 -0
  377. data/{bin → src/ruby/bin}/grpc_ruby_interop_server +0 -0
  378. data/{bin → src/ruby/bin}/interop/interop_client.rb +0 -0
  379. data/{bin → src/ruby/bin}/interop/interop_server.rb +0 -0
  380. data/src/ruby/bin/math.rb +32 -0
  381. data/{bin → src/ruby/bin}/math_client.rb +1 -1
  382. data/{bin → src/ruby/bin}/math_server.rb +1 -1
  383. data/src/ruby/bin/math_services.rb +27 -0
  384. data/{bin → src/ruby/bin}/noproto_client.rb +1 -1
  385. data/{bin → src/ruby/bin}/noproto_server.rb +1 -1
  386. data/{ext → src/ruby/ext}/grpc/extconf.rb +24 -40
  387. data/{ext → src/ruby/ext}/grpc/rb_byte_buffer.c +0 -0
  388. data/{ext → src/ruby/ext}/grpc/rb_byte_buffer.h +0 -0
  389. data/{ext → src/ruby/ext}/grpc/rb_call.c +80 -18
  390. data/{ext → src/ruby/ext}/grpc/rb_call.h +6 -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/{ext → src/ruby/ext}/grpc/rb_channel.c +19 -7
  394. data/{ext → src/ruby/ext}/grpc/rb_channel.h +0 -0
  395. data/{ext → src/ruby/ext}/grpc/rb_channel_args.c +2 -0
  396. data/{ext → src/ruby/ext}/grpc/rb_channel_args.h +0 -0
  397. data/src/ruby/ext/grpc/rb_channel_credentials.c +266 -0
  398. data/{ext/grpc/rb_credentials.h → src/ruby/ext/grpc/rb_channel_credentials.h} +3 -3
  399. data/{ext → src/ruby/ext}/grpc/rb_completion_queue.c +3 -1
  400. data/{ext → src/ruby/ext}/grpc/rb_completion_queue.h +0 -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/{ext → src/ruby/ext}/grpc/rb_grpc.c +25 -5
  404. data/{ext → src/ruby/ext}/grpc/rb_grpc.h +0 -0
  405. data/{ext → src/ruby/ext}/grpc/rb_server.c +4 -1
  406. data/{ext → src/ruby/ext}/grpc/rb_server.h +0 -0
  407. data/{ext → src/ruby/ext}/grpc/rb_server_credentials.c +2 -0
  408. data/{ext → src/ruby/ext}/grpc/rb_server_credentials.h +0 -0
  409. data/{lib → src/ruby/lib}/grpc.rb +6 -1
  410. data/{lib → src/ruby/lib}/grpc/core/time_consts.rb +0 -0
  411. data/{lib → src/ruby/lib}/grpc/errors.rb +0 -0
  412. data/{lib → src/ruby/lib}/grpc/generic/active_call.rb +4 -6
  413. data/{lib → src/ruby/lib}/grpc/generic/bidi_call.rb +16 -4
  414. data/{lib → src/ruby/lib}/grpc/generic/client_stub.rb +42 -52
  415. data/{lib → src/ruby/lib}/grpc/generic/rpc_desc.rb +0 -0
  416. data/{lib → src/ruby/lib}/grpc/generic/rpc_server.rb +15 -8
  417. data/{lib → src/ruby/lib}/grpc/generic/service.rb +4 -2
  418. data/src/ruby/lib/grpc/grpc.so +0 -0
  419. data/{lib → src/ruby/lib}/grpc/logconfig.rb +0 -0
  420. data/{lib → src/ruby/lib}/grpc/notifier.rb +0 -0
  421. data/{lib → src/ruby/lib}/grpc/version.rb +2 -2
  422. data/src/ruby/pb/README.md +42 -0
  423. data/src/ruby/pb/generate_proto_ruby.sh +51 -0
  424. data/src/ruby/pb/grpc/health/checker.rb +75 -0
  425. data/src/ruby/pb/grpc/health/v1alpha/health.rb +29 -0
  426. data/src/ruby/pb/grpc/health/v1alpha/health_services.rb +28 -0
  427. data/src/ruby/pb/test/client.rb +469 -0
  428. data/src/ruby/pb/test/proto/empty.rb +15 -0
  429. data/src/ruby/pb/test/proto/messages.rb +80 -0
  430. data/src/ruby/pb/test/proto/test.rb +14 -0
  431. data/src/ruby/pb/test/proto/test_services.rb +64 -0
  432. data/src/ruby/pb/test/server.rb +253 -0
  433. data/{bin/math_services.rb → src/ruby/spec/call_credentials_spec.rb} +19 -18
  434. data/{spec → src/ruby/spec}/call_spec.rb +10 -1
  435. data/{spec/credentials_spec.rb → src/ruby/spec/channel_credentials_spec.rb} +38 -12
  436. data/{spec → src/ruby/spec}/channel_spec.rb +14 -9
  437. data/{spec → src/ruby/spec}/client_server_spec.rb +31 -2
  438. data/{spec → src/ruby/spec}/completion_queue_spec.rb +0 -0
  439. data/{spec → src/ruby/spec}/generic/active_call_spec.rb +2 -1
  440. data/{spec → src/ruby/spec}/generic/client_stub_spec.rb +27 -67
  441. data/{spec → src/ruby/spec}/generic/rpc_desc_spec.rb +0 -0
  442. data/{spec → src/ruby/spec}/generic/rpc_server_pool_spec.rb +0 -0
  443. data/{spec → src/ruby/spec}/generic/rpc_server_spec.rb +12 -46
  444. data/{spec → src/ruby/spec}/generic/service_spec.rb +6 -3
  445. data/{spec → src/ruby/spec}/pb/health/checker_spec.rb +8 -8
  446. data/{spec → src/ruby/spec}/server_credentials_spec.rb +0 -0
  447. data/{spec → src/ruby/spec}/server_spec.rb +0 -0
  448. data/{spec → src/ruby/spec}/spec_helper.rb +0 -0
  449. data/{spec → src/ruby/spec}/testdata/README +0 -0
  450. data/{spec → src/ruby/spec}/testdata/ca.pem +0 -0
  451. data/{spec → src/ruby/spec}/testdata/server1.key +0 -0
  452. data/src/ruby/spec/testdata/server1.pem +16 -0
  453. data/{spec → src/ruby/spec}/time_consts_spec.rb +0 -0
  454. metadata +496 -97
  455. data/bin/math.proto +0 -80
  456. data/bin/math.rb +0 -61
  457. data/ext/grpc/rb_credentials.c +0 -294
  458. data/lib/grpc/grpc.so +0 -0
  459. data/spec/testdata/server1.pem +0 -16
@@ -0,0 +1,61 @@
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
+ #ifndef GRPC_INTERNAL_CORE_TSI_FAKE_TRANSPORT_SECURITY_H
35
+ #define GRPC_INTERNAL_CORE_TSI_FAKE_TRANSPORT_SECURITY_H
36
+
37
+ #include "src/core/tsi/transport_security_interface.h"
38
+
39
+ #ifdef __cplusplus
40
+ extern "C" {
41
+ #endif
42
+
43
+ /* Value for the TSI_CERTIFICATE_TYPE_PEER_PROPERTY property for FAKE certs. */
44
+ #define TSI_FAKE_CERTIFICATE_TYPE "FAKE"
45
+
46
+ /* Creates a fake handshaker that will create a fake frame protector.
47
+
48
+ No cryptography is performed in these objects. They just simulate handshake
49
+ messages going back and forth for the handshaker and do some framing on
50
+ cleartext data for the protector. */
51
+ tsi_handshaker *tsi_create_fake_handshaker(int is_client);
52
+
53
+ /* Creates a protector directly without going through the handshake phase. */
54
+ tsi_frame_protector *tsi_create_fake_protector(
55
+ size_t *max_protected_frame_size);
56
+
57
+ #ifdef __cplusplus
58
+ }
59
+ #endif
60
+
61
+ #endif /* GRPC_INTERNAL_CORE_TSI_FAKE_TRANSPORT_SECURITY_H */
@@ -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
+ }