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,118 @@
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_SECURITY_JSON_TOKEN_H
35
+ #define GRPC_INTERNAL_CORE_SECURITY_JSON_TOKEN_H
36
+
37
+ #include <grpc/support/slice.h>
38
+ #include <openssl/rsa.h>
39
+
40
+ #include "src/core/json/json.h"
41
+
42
+ /* --- Constants. --- */
43
+
44
+ #define GRPC_JWT_OAUTH2_AUDIENCE "https://www.googleapis.com/oauth2/v3/token"
45
+
46
+ #define GRPC_AUTH_JSON_TYPE_INVALID "invalid"
47
+ #define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
48
+ #define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
49
+
50
+ /* --- auth_json_key parsing. --- */
51
+
52
+ typedef struct {
53
+ const char *type;
54
+ char *private_key_id;
55
+ char *client_id;
56
+ char *client_email;
57
+ RSA *private_key;
58
+ } grpc_auth_json_key;
59
+
60
+ /* Returns 1 if the object is valid, 0 otherwise. */
61
+ int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key);
62
+
63
+ /* Creates a json_key object from string. Returns an invalid object if a parsing
64
+ error has been encountered. */
65
+ grpc_auth_json_key grpc_auth_json_key_create_from_string(
66
+ const char *json_string);
67
+
68
+ /* Creates a json_key object from parsed json. Returns an invalid object if a
69
+ parsing error has been encountered. */
70
+ grpc_auth_json_key grpc_auth_json_key_create_from_json(const grpc_json *json);
71
+
72
+ /* Destructs the object. */
73
+ void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key);
74
+
75
+ /* --- json token encoding and signing. --- */
76
+
77
+ /* Caller is responsible for calling gpr_free on the returned value. May return
78
+ NULL on invalid input. The scope parameter may be NULL. */
79
+ char *grpc_jwt_encode_and_sign(const grpc_auth_json_key *json_key,
80
+ const char *audience,
81
+ gpr_timespec token_lifetime, const char *scope);
82
+
83
+ /* Override encode_and_sign function for testing. */
84
+ typedef char *(*grpc_jwt_encode_and_sign_override)(
85
+ const grpc_auth_json_key *json_key, const char *audience,
86
+ gpr_timespec token_lifetime, const char *scope);
87
+
88
+ /* Set a custom encode_and_sign override for testing. */
89
+ void grpc_jwt_encode_and_sign_set_override(
90
+ grpc_jwt_encode_and_sign_override func);
91
+
92
+ /* --- auth_refresh_token parsing. --- */
93
+
94
+ typedef struct {
95
+ const char *type;
96
+ char *client_id;
97
+ char *client_secret;
98
+ char *refresh_token;
99
+ } grpc_auth_refresh_token;
100
+
101
+ /* Returns 1 if the object is valid, 0 otherwise. */
102
+ int grpc_auth_refresh_token_is_valid(
103
+ const grpc_auth_refresh_token *refresh_token);
104
+
105
+ /* Creates a refresh token object from string. Returns an invalid object if a
106
+ parsing error has been encountered. */
107
+ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
108
+ const char *json_string);
109
+
110
+ /* Creates a refresh token object from parsed json. Returns an invalid object if
111
+ a parsing error has been encountered. */
112
+ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json(
113
+ const grpc_json *json);
114
+
115
+ /* Destructs the object. */
116
+ void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token);
117
+
118
+ #endif /* GRPC_INTERNAL_CORE_SECURITY_JSON_TOKEN_H */
@@ -0,0 +1,842 @@
1
+ /*
2
+ *
3
+ * Copyright 2015-2016, 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/security/jwt_verifier.h"
35
+
36
+ #include <limits.h>
37
+ #include <string.h>
38
+
39
+ #include "src/core/httpcli/httpcli.h"
40
+ #include "src/core/security/base64.h"
41
+
42
+ #include <grpc/support/alloc.h>
43
+ #include <grpc/support/log.h>
44
+ #include <grpc/support/string_util.h>
45
+ #include <grpc/support/sync.h>
46
+ #include <openssl/pem.h>
47
+
48
+ /* --- Utils. --- */
49
+
50
+ const char *grpc_jwt_verifier_status_to_string(
51
+ grpc_jwt_verifier_status status) {
52
+ switch (status) {
53
+ case GRPC_JWT_VERIFIER_OK:
54
+ return "OK";
55
+ case GRPC_JWT_VERIFIER_BAD_SIGNATURE:
56
+ return "BAD_SIGNATURE";
57
+ case GRPC_JWT_VERIFIER_BAD_FORMAT:
58
+ return "BAD_FORMAT";
59
+ case GRPC_JWT_VERIFIER_BAD_AUDIENCE:
60
+ return "BAD_AUDIENCE";
61
+ case GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR:
62
+ return "KEY_RETRIEVAL_ERROR";
63
+ case GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE:
64
+ return "TIME_CONSTRAINT_FAILURE";
65
+ case GRPC_JWT_VERIFIER_GENERIC_ERROR:
66
+ return "GENERIC_ERROR";
67
+ default:
68
+ return "UNKNOWN";
69
+ }
70
+ }
71
+
72
+ static const EVP_MD *evp_md_from_alg(const char *alg) {
73
+ if (strcmp(alg, "RS256") == 0) {
74
+ return EVP_sha256();
75
+ } else if (strcmp(alg, "RS384") == 0) {
76
+ return EVP_sha384();
77
+ } else if (strcmp(alg, "RS512") == 0) {
78
+ return EVP_sha512();
79
+ } else {
80
+ return NULL;
81
+ }
82
+ }
83
+
84
+ static grpc_json *parse_json_part_from_jwt(const char *str, size_t len,
85
+ gpr_slice *buffer) {
86
+ grpc_json *json;
87
+
88
+ *buffer = grpc_base64_decode_with_len(str, len, 1);
89
+ if (GPR_SLICE_IS_EMPTY(*buffer)) {
90
+ gpr_log(GPR_ERROR, "Invalid base64.");
91
+ return NULL;
92
+ }
93
+ json = grpc_json_parse_string_with_len((char *)GPR_SLICE_START_PTR(*buffer),
94
+ GPR_SLICE_LENGTH(*buffer));
95
+ if (json == NULL) {
96
+ gpr_slice_unref(*buffer);
97
+ gpr_log(GPR_ERROR, "JSON parsing error.");
98
+ }
99
+ return json;
100
+ }
101
+
102
+ static const char *validate_string_field(const grpc_json *json,
103
+ const char *key) {
104
+ if (json->type != GRPC_JSON_STRING) {
105
+ gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value);
106
+ return NULL;
107
+ }
108
+ return json->value;
109
+ }
110
+
111
+ static gpr_timespec validate_time_field(const grpc_json *json,
112
+ const char *key) {
113
+ gpr_timespec result = gpr_time_0(GPR_CLOCK_REALTIME);
114
+ if (json->type != GRPC_JSON_NUMBER) {
115
+ gpr_log(GPR_ERROR, "Invalid %s field [%s]", key, json->value);
116
+ return result;
117
+ }
118
+ result.tv_sec = strtol(json->value, NULL, 10);
119
+ return result;
120
+ }
121
+
122
+ /* --- JOSE header. see http://tools.ietf.org/html/rfc7515#section-4 --- */
123
+
124
+ typedef struct {
125
+ const char *alg;
126
+ const char *kid;
127
+ const char *typ;
128
+ /* TODO(jboeuf): Add others as needed (jku, jwk, x5u, x5c and so on...). */
129
+ gpr_slice buffer;
130
+ } jose_header;
131
+
132
+ static void jose_header_destroy(jose_header *h) {
133
+ gpr_slice_unref(h->buffer);
134
+ gpr_free(h);
135
+ }
136
+
137
+ /* Takes ownership of json and buffer. */
138
+ static jose_header *jose_header_from_json(grpc_json *json, gpr_slice buffer) {
139
+ grpc_json *cur;
140
+ jose_header *h = gpr_malloc(sizeof(jose_header));
141
+ memset(h, 0, sizeof(jose_header));
142
+ h->buffer = buffer;
143
+ for (cur = json->child; cur != NULL; cur = cur->next) {
144
+ if (strcmp(cur->key, "alg") == 0) {
145
+ /* We only support RSA-1.5 signatures for now.
146
+ Beware of this if we add HMAC support:
147
+ https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
148
+ */
149
+ if (cur->type != GRPC_JSON_STRING || strncmp(cur->value, "RS", 2) ||
150
+ evp_md_from_alg(cur->value) == NULL) {
151
+ gpr_log(GPR_ERROR, "Invalid alg field [%s]", cur->value);
152
+ goto error;
153
+ }
154
+ h->alg = cur->value;
155
+ } else if (strcmp(cur->key, "typ") == 0) {
156
+ h->typ = validate_string_field(cur, "typ");
157
+ if (h->typ == NULL) goto error;
158
+ } else if (strcmp(cur->key, "kid") == 0) {
159
+ h->kid = validate_string_field(cur, "kid");
160
+ if (h->kid == NULL) goto error;
161
+ }
162
+ }
163
+ if (h->alg == NULL) {
164
+ gpr_log(GPR_ERROR, "Missing alg field.");
165
+ goto error;
166
+ }
167
+ grpc_json_destroy(json);
168
+ h->buffer = buffer;
169
+ return h;
170
+
171
+ error:
172
+ grpc_json_destroy(json);
173
+ jose_header_destroy(h);
174
+ return NULL;
175
+ }
176
+
177
+ /* --- JWT claims. see http://tools.ietf.org/html/rfc7519#section-4.1 */
178
+
179
+ struct grpc_jwt_claims {
180
+ /* Well known properties already parsed. */
181
+ const char *sub;
182
+ const char *iss;
183
+ const char *aud;
184
+ const char *jti;
185
+ gpr_timespec iat;
186
+ gpr_timespec exp;
187
+ gpr_timespec nbf;
188
+
189
+ grpc_json *json;
190
+ gpr_slice buffer;
191
+ };
192
+
193
+ void grpc_jwt_claims_destroy(grpc_jwt_claims *claims) {
194
+ grpc_json_destroy(claims->json);
195
+ gpr_slice_unref(claims->buffer);
196
+ gpr_free(claims);
197
+ }
198
+
199
+ const grpc_json *grpc_jwt_claims_json(const grpc_jwt_claims *claims) {
200
+ if (claims == NULL) return NULL;
201
+ return claims->json;
202
+ }
203
+
204
+ const char *grpc_jwt_claims_subject(const grpc_jwt_claims *claims) {
205
+ if (claims == NULL) return NULL;
206
+ return claims->sub;
207
+ }
208
+
209
+ const char *grpc_jwt_claims_issuer(const grpc_jwt_claims *claims) {
210
+ if (claims == NULL) return NULL;
211
+ return claims->iss;
212
+ }
213
+
214
+ const char *grpc_jwt_claims_id(const grpc_jwt_claims *claims) {
215
+ if (claims == NULL) return NULL;
216
+ return claims->jti;
217
+ }
218
+
219
+ const char *grpc_jwt_claims_audience(const grpc_jwt_claims *claims) {
220
+ if (claims == NULL) return NULL;
221
+ return claims->aud;
222
+ }
223
+
224
+ gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims) {
225
+ if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME);
226
+ return claims->iat;
227
+ }
228
+
229
+ gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims) {
230
+ if (claims == NULL) return gpr_inf_future(GPR_CLOCK_REALTIME);
231
+ return claims->exp;
232
+ }
233
+
234
+ gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims) {
235
+ if (claims == NULL) return gpr_inf_past(GPR_CLOCK_REALTIME);
236
+ return claims->nbf;
237
+ }
238
+
239
+ /* Takes ownership of json and buffer even in case of failure. */
240
+ grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, gpr_slice buffer) {
241
+ grpc_json *cur;
242
+ grpc_jwt_claims *claims = gpr_malloc(sizeof(grpc_jwt_claims));
243
+ memset(claims, 0, sizeof(grpc_jwt_claims));
244
+ claims->json = json;
245
+ claims->buffer = buffer;
246
+ claims->iat = gpr_inf_past(GPR_CLOCK_REALTIME);
247
+ claims->nbf = gpr_inf_past(GPR_CLOCK_REALTIME);
248
+ claims->exp = gpr_inf_future(GPR_CLOCK_REALTIME);
249
+
250
+ /* Per the spec, all fields are optional. */
251
+ for (cur = json->child; cur != NULL; cur = cur->next) {
252
+ if (strcmp(cur->key, "sub") == 0) {
253
+ claims->sub = validate_string_field(cur, "sub");
254
+ if (claims->sub == NULL) goto error;
255
+ } else if (strcmp(cur->key, "iss") == 0) {
256
+ claims->iss = validate_string_field(cur, "iss");
257
+ if (claims->iss == NULL) goto error;
258
+ } else if (strcmp(cur->key, "aud") == 0) {
259
+ claims->aud = validate_string_field(cur, "aud");
260
+ if (claims->aud == NULL) goto error;
261
+ } else if (strcmp(cur->key, "jti") == 0) {
262
+ claims->jti = validate_string_field(cur, "jti");
263
+ if (claims->jti == NULL) goto error;
264
+ } else if (strcmp(cur->key, "iat") == 0) {
265
+ claims->iat = validate_time_field(cur, "iat");
266
+ if (gpr_time_cmp(claims->iat, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
267
+ goto error;
268
+ } else if (strcmp(cur->key, "exp") == 0) {
269
+ claims->exp = validate_time_field(cur, "exp");
270
+ if (gpr_time_cmp(claims->exp, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
271
+ goto error;
272
+ } else if (strcmp(cur->key, "nbf") == 0) {
273
+ claims->nbf = validate_time_field(cur, "nbf");
274
+ if (gpr_time_cmp(claims->nbf, gpr_time_0(GPR_CLOCK_REALTIME)) == 0)
275
+ goto error;
276
+ }
277
+ }
278
+ return claims;
279
+
280
+ error:
281
+ grpc_jwt_claims_destroy(claims);
282
+ return NULL;
283
+ }
284
+
285
+ grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
286
+ const char *audience) {
287
+ gpr_timespec skewed_now;
288
+ int audience_ok;
289
+
290
+ GPR_ASSERT(claims != NULL);
291
+
292
+ skewed_now =
293
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
294
+ if (gpr_time_cmp(skewed_now, claims->nbf) < 0) {
295
+ gpr_log(GPR_ERROR, "JWT is not valid yet.");
296
+ return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
297
+ }
298
+ skewed_now =
299
+ gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
300
+ if (gpr_time_cmp(skewed_now, claims->exp) > 0) {
301
+ gpr_log(GPR_ERROR, "JWT is expired.");
302
+ return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
303
+ }
304
+
305
+ if (audience == NULL) {
306
+ audience_ok = claims->aud == NULL;
307
+ } else {
308
+ audience_ok = claims->aud != NULL && strcmp(audience, claims->aud) == 0;
309
+ }
310
+ if (!audience_ok) {
311
+ gpr_log(GPR_ERROR, "Audience mismatch: expected %s and found %s.",
312
+ audience == NULL ? "NULL" : audience,
313
+ claims->aud == NULL ? "NULL" : claims->aud);
314
+ return GRPC_JWT_VERIFIER_BAD_AUDIENCE;
315
+ }
316
+ return GRPC_JWT_VERIFIER_OK;
317
+ }
318
+
319
+ /* --- verifier_cb_ctx object. --- */
320
+
321
+ typedef struct {
322
+ grpc_jwt_verifier *verifier;
323
+ grpc_pollset *pollset;
324
+ jose_header *header;
325
+ grpc_jwt_claims *claims;
326
+ char *audience;
327
+ gpr_slice signature;
328
+ gpr_slice signed_data;
329
+ void *user_data;
330
+ grpc_jwt_verification_done_cb user_cb;
331
+ } verifier_cb_ctx;
332
+
333
+ /* Takes ownership of the header, claims and signature. */
334
+ static verifier_cb_ctx *verifier_cb_ctx_create(
335
+ grpc_jwt_verifier *verifier, grpc_pollset *pollset, jose_header *header,
336
+ grpc_jwt_claims *claims, const char *audience, gpr_slice signature,
337
+ const char *signed_jwt, size_t signed_jwt_len, void *user_data,
338
+ grpc_jwt_verification_done_cb cb) {
339
+ verifier_cb_ctx *ctx = gpr_malloc(sizeof(verifier_cb_ctx));
340
+ memset(ctx, 0, sizeof(verifier_cb_ctx));
341
+ ctx->verifier = verifier;
342
+ ctx->pollset = pollset;
343
+ ctx->header = header;
344
+ ctx->audience = gpr_strdup(audience);
345
+ ctx->claims = claims;
346
+ ctx->signature = signature;
347
+ ctx->signed_data = gpr_slice_from_copied_buffer(signed_jwt, signed_jwt_len);
348
+ ctx->user_data = user_data;
349
+ ctx->user_cb = cb;
350
+ return ctx;
351
+ }
352
+
353
+ void verifier_cb_ctx_destroy(verifier_cb_ctx *ctx) {
354
+ if (ctx->audience != NULL) gpr_free(ctx->audience);
355
+ if (ctx->claims != NULL) grpc_jwt_claims_destroy(ctx->claims);
356
+ gpr_slice_unref(ctx->signature);
357
+ gpr_slice_unref(ctx->signed_data);
358
+ jose_header_destroy(ctx->header);
359
+ /* TODO: see what to do with claims... */
360
+ gpr_free(ctx);
361
+ }
362
+
363
+ /* --- grpc_jwt_verifier object. --- */
364
+
365
+ /* Clock skew defaults to one minute. */
366
+ gpr_timespec grpc_jwt_verifier_clock_skew = {60, 0, GPR_TIMESPAN};
367
+
368
+ /* Max delay defaults to one minute. */
369
+ gpr_timespec grpc_jwt_verifier_max_delay = {60, 0, GPR_TIMESPAN};
370
+
371
+ typedef struct {
372
+ char *email_domain;
373
+ char *key_url_prefix;
374
+ } email_key_mapping;
375
+
376
+ struct grpc_jwt_verifier {
377
+ email_key_mapping *mappings;
378
+ size_t num_mappings; /* Should be very few, linear search ok. */
379
+ size_t allocated_mappings;
380
+ grpc_httpcli_context http_ctx;
381
+ };
382
+
383
+ static grpc_json *json_from_http(const grpc_httpcli_response *response) {
384
+ grpc_json *json = NULL;
385
+
386
+ if (response == NULL) {
387
+ gpr_log(GPR_ERROR, "HTTP response is NULL.");
388
+ return NULL;
389
+ }
390
+ if (response->status != 200) {
391
+ gpr_log(GPR_ERROR, "Call to http server failed with error %d.",
392
+ response->status);
393
+ return NULL;
394
+ }
395
+
396
+ json = grpc_json_parse_string_with_len(response->body, response->body_length);
397
+ if (json == NULL) {
398
+ gpr_log(GPR_ERROR, "Invalid JSON found in response.");
399
+ }
400
+ return json;
401
+ }
402
+
403
+ static const grpc_json *find_property_by_name(const grpc_json *json,
404
+ const char *name) {
405
+ const grpc_json *cur;
406
+ for (cur = json->child; cur != NULL; cur = cur->next) {
407
+ if (strcmp(cur->key, name) == 0) return cur;
408
+ }
409
+ return NULL;
410
+ }
411
+
412
+ static EVP_PKEY *extract_pkey_from_x509(const char *x509_str) {
413
+ X509 *x509 = NULL;
414
+ EVP_PKEY *result = NULL;
415
+ BIO *bio = BIO_new(BIO_s_mem());
416
+ size_t len = strlen(x509_str);
417
+ GPR_ASSERT(len < INT_MAX);
418
+ BIO_write(bio, x509_str, (int)len);
419
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
420
+ if (x509 == NULL) {
421
+ gpr_log(GPR_ERROR, "Unable to parse x509 cert.");
422
+ goto end;
423
+ }
424
+ result = X509_get_pubkey(x509);
425
+ if (result == NULL) {
426
+ gpr_log(GPR_ERROR, "Cannot find public key in X509 cert.");
427
+ }
428
+
429
+ end:
430
+ BIO_free(bio);
431
+ if (x509 != NULL) X509_free(x509);
432
+ return result;
433
+ }
434
+
435
+ static BIGNUM *bignum_from_base64(const char *b64) {
436
+ BIGNUM *result = NULL;
437
+ gpr_slice bin;
438
+
439
+ if (b64 == NULL) return NULL;
440
+ bin = grpc_base64_decode(b64, 1);
441
+ if (GPR_SLICE_IS_EMPTY(bin)) {
442
+ gpr_log(GPR_ERROR, "Invalid base64 for big num.");
443
+ return NULL;
444
+ }
445
+ result =
446
+ BN_bin2bn(GPR_SLICE_START_PTR(bin), (int)GPR_SLICE_LENGTH(bin), NULL);
447
+ gpr_slice_unref(bin);
448
+ return result;
449
+ }
450
+
451
+ static EVP_PKEY *pkey_from_jwk(const grpc_json *json, const char *kty) {
452
+ const grpc_json *key_prop;
453
+ RSA *rsa = NULL;
454
+ EVP_PKEY *result = NULL;
455
+
456
+ GPR_ASSERT(kty != NULL && json != NULL);
457
+ if (strcmp(kty, "RSA") != 0) {
458
+ gpr_log(GPR_ERROR, "Unsupported key type %s.", kty);
459
+ goto end;
460
+ }
461
+ rsa = RSA_new();
462
+ if (rsa == NULL) {
463
+ gpr_log(GPR_ERROR, "Could not create rsa key.");
464
+ goto end;
465
+ }
466
+ for (key_prop = json->child; key_prop != NULL; key_prop = key_prop->next) {
467
+ if (strcmp(key_prop->key, "n") == 0) {
468
+ rsa->n = bignum_from_base64(validate_string_field(key_prop, "n"));
469
+ if (rsa->n == NULL) goto end;
470
+ } else if (strcmp(key_prop->key, "e") == 0) {
471
+ rsa->e = bignum_from_base64(validate_string_field(key_prop, "e"));
472
+ if (rsa->e == NULL) goto end;
473
+ }
474
+ }
475
+ if (rsa->e == NULL || rsa->n == NULL) {
476
+ gpr_log(GPR_ERROR, "Missing RSA public key field.");
477
+ goto end;
478
+ }
479
+ result = EVP_PKEY_new();
480
+ EVP_PKEY_set1_RSA(result, rsa); /* uprefs rsa. */
481
+
482
+ end:
483
+ if (rsa != NULL) RSA_free(rsa);
484
+ return result;
485
+ }
486
+
487
+ static EVP_PKEY *find_verification_key(const grpc_json *json,
488
+ const char *header_alg,
489
+ const char *header_kid) {
490
+ const grpc_json *jkey;
491
+ const grpc_json *jwk_keys;
492
+ /* Try to parse the json as a JWK set:
493
+ https://tools.ietf.org/html/rfc7517#section-5. */
494
+ jwk_keys = find_property_by_name(json, "keys");
495
+ if (jwk_keys == NULL) {
496
+ /* Use the google proprietary format which is:
497
+ { <kid1>: <x5091>, <kid2>: <x5092>, ... } */
498
+ const grpc_json *cur = find_property_by_name(json, header_kid);
499
+ if (cur == NULL) return NULL;
500
+ return extract_pkey_from_x509(cur->value);
501
+ }
502
+
503
+ if (jwk_keys->type != GRPC_JSON_ARRAY) {
504
+ gpr_log(GPR_ERROR,
505
+ "Unexpected value type of keys property in jwks key set.");
506
+ return NULL;
507
+ }
508
+ /* Key format is specified in:
509
+ https://tools.ietf.org/html/rfc7518#section-6. */
510
+ for (jkey = jwk_keys->child; jkey != NULL; jkey = jkey->next) {
511
+ grpc_json *key_prop;
512
+ const char *alg = NULL;
513
+ const char *kid = NULL;
514
+ const char *kty = NULL;
515
+
516
+ if (jkey->type != GRPC_JSON_OBJECT) continue;
517
+ for (key_prop = jkey->child; key_prop != NULL; key_prop = key_prop->next) {
518
+ if (strcmp(key_prop->key, "alg") == 0 &&
519
+ key_prop->type == GRPC_JSON_STRING) {
520
+ alg = key_prop->value;
521
+ } else if (strcmp(key_prop->key, "kid") == 0 &&
522
+ key_prop->type == GRPC_JSON_STRING) {
523
+ kid = key_prop->value;
524
+ } else if (strcmp(key_prop->key, "kty") == 0 &&
525
+ key_prop->type == GRPC_JSON_STRING) {
526
+ kty = key_prop->value;
527
+ }
528
+ }
529
+ if (alg != NULL && kid != NULL && kty != NULL &&
530
+ strcmp(kid, header_kid) == 0 && strcmp(alg, header_alg) == 0) {
531
+ return pkey_from_jwk(jkey, kty);
532
+ }
533
+ }
534
+ gpr_log(GPR_ERROR,
535
+ "Could not find matching key in key set for kid=%s and alg=%s",
536
+ header_kid, header_alg);
537
+ return NULL;
538
+ }
539
+
540
+ static int verify_jwt_signature(EVP_PKEY *key, const char *alg,
541
+ gpr_slice signature, gpr_slice signed_data) {
542
+ EVP_MD_CTX *md_ctx = EVP_MD_CTX_create();
543
+ const EVP_MD *md = evp_md_from_alg(alg);
544
+ int result = 0;
545
+
546
+ GPR_ASSERT(md != NULL); /* Checked before. */
547
+ if (md_ctx == NULL) {
548
+ gpr_log(GPR_ERROR, "Could not create EVP_MD_CTX.");
549
+ goto end;
550
+ }
551
+ if (EVP_DigestVerifyInit(md_ctx, NULL, md, NULL, key) != 1) {
552
+ gpr_log(GPR_ERROR, "EVP_DigestVerifyInit failed.");
553
+ goto end;
554
+ }
555
+ if (EVP_DigestVerifyUpdate(md_ctx, GPR_SLICE_START_PTR(signed_data),
556
+ GPR_SLICE_LENGTH(signed_data)) != 1) {
557
+ gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed.");
558
+ goto end;
559
+ }
560
+ if (EVP_DigestVerifyFinal(md_ctx, GPR_SLICE_START_PTR(signature),
561
+ GPR_SLICE_LENGTH(signature)) != 1) {
562
+ gpr_log(GPR_ERROR, "JWT signature verification failed.");
563
+ goto end;
564
+ }
565
+ result = 1;
566
+
567
+ end:
568
+ if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx);
569
+ return result;
570
+ }
571
+
572
+ static void on_keys_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
573
+ const grpc_httpcli_response *response) {
574
+ grpc_json *json = json_from_http(response);
575
+ verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
576
+ EVP_PKEY *verification_key = NULL;
577
+ grpc_jwt_verifier_status status = GRPC_JWT_VERIFIER_GENERIC_ERROR;
578
+ grpc_jwt_claims *claims = NULL;
579
+
580
+ if (json == NULL) {
581
+ status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR;
582
+ goto end;
583
+ }
584
+ verification_key =
585
+ find_verification_key(json, ctx->header->alg, ctx->header->kid);
586
+ if (verification_key == NULL) {
587
+ gpr_log(GPR_ERROR, "Could not find verification key with kid %s.",
588
+ ctx->header->kid);
589
+ status = GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR;
590
+ goto end;
591
+ }
592
+
593
+ if (!verify_jwt_signature(verification_key, ctx->header->alg, ctx->signature,
594
+ ctx->signed_data)) {
595
+ status = GRPC_JWT_VERIFIER_BAD_SIGNATURE;
596
+ goto end;
597
+ }
598
+
599
+ status = grpc_jwt_claims_check(ctx->claims, ctx->audience);
600
+ if (status == GRPC_JWT_VERIFIER_OK) {
601
+ /* Pass ownership. */
602
+ claims = ctx->claims;
603
+ ctx->claims = NULL;
604
+ }
605
+
606
+ end:
607
+ if (json != NULL) grpc_json_destroy(json);
608
+ if (verification_key != NULL) EVP_PKEY_free(verification_key);
609
+ ctx->user_cb(ctx->user_data, status, claims);
610
+ verifier_cb_ctx_destroy(ctx);
611
+ }
612
+
613
+ static void on_openid_config_retrieved(grpc_exec_ctx *exec_ctx, void *user_data,
614
+ const grpc_httpcli_response *response) {
615
+ const grpc_json *cur;
616
+ grpc_json *json = json_from_http(response);
617
+ verifier_cb_ctx *ctx = (verifier_cb_ctx *)user_data;
618
+ grpc_httpcli_request req;
619
+ const char *jwks_uri;
620
+
621
+ /* TODO(jboeuf): Cache the jwks_uri in order to avoid this hop next time. */
622
+ if (json == NULL) goto error;
623
+ cur = find_property_by_name(json, "jwks_uri");
624
+ if (cur == NULL) {
625
+ gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config.");
626
+ goto error;
627
+ }
628
+ jwks_uri = validate_string_field(cur, "jwks_uri");
629
+ if (jwks_uri == NULL) goto error;
630
+ if (strstr(jwks_uri, "https://") != jwks_uri) {
631
+ gpr_log(GPR_ERROR, "Invalid non https jwks_uri: %s.", jwks_uri);
632
+ goto error;
633
+ }
634
+ jwks_uri += 8;
635
+ req.handshaker = &grpc_httpcli_ssl;
636
+ req.host = gpr_strdup(jwks_uri);
637
+ req.path = strchr(jwks_uri, '/');
638
+ if (req.path == NULL) {
639
+ req.path = "";
640
+ } else {
641
+ *(req.host + (req.path - jwks_uri)) = '\0';
642
+ }
643
+ grpc_httpcli_get(
644
+ exec_ctx, &ctx->verifier->http_ctx, ctx->pollset, &req,
645
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
646
+ on_keys_retrieved, ctx);
647
+ grpc_json_destroy(json);
648
+ gpr_free(req.host);
649
+ return;
650
+
651
+ error:
652
+ if (json != NULL) grpc_json_destroy(json);
653
+ ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
654
+ verifier_cb_ctx_destroy(ctx);
655
+ }
656
+
657
+ static email_key_mapping *verifier_get_mapping(grpc_jwt_verifier *v,
658
+ const char *email_domain) {
659
+ size_t i;
660
+ if (v->mappings == NULL) return NULL;
661
+ for (i = 0; i < v->num_mappings; i++) {
662
+ if (strcmp(email_domain, v->mappings[i].email_domain) == 0) {
663
+ return &v->mappings[i];
664
+ }
665
+ }
666
+ return NULL;
667
+ }
668
+
669
+ static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain,
670
+ const char *key_url_prefix) {
671
+ email_key_mapping *mapping = verifier_get_mapping(v, email_domain);
672
+ GPR_ASSERT(v->num_mappings < v->allocated_mappings);
673
+ if (mapping != NULL) {
674
+ gpr_free(mapping->key_url_prefix);
675
+ mapping->key_url_prefix = gpr_strdup(key_url_prefix);
676
+ return;
677
+ }
678
+ v->mappings[v->num_mappings].email_domain = gpr_strdup(email_domain);
679
+ v->mappings[v->num_mappings].key_url_prefix = gpr_strdup(key_url_prefix);
680
+ v->num_mappings++;
681
+ GPR_ASSERT(v->num_mappings <= v->allocated_mappings);
682
+ }
683
+
684
+ /* Takes ownership of ctx. */
685
+ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
686
+ verifier_cb_ctx *ctx) {
687
+ const char *at_sign;
688
+ grpc_httpcli_response_cb http_cb;
689
+ char *path_prefix = NULL;
690
+ const char *iss;
691
+ grpc_httpcli_request req;
692
+ memset(&req, 0, sizeof(grpc_httpcli_request));
693
+ req.handshaker = &grpc_httpcli_ssl;
694
+
695
+ GPR_ASSERT(ctx != NULL && ctx->header != NULL && ctx->claims != NULL);
696
+ iss = ctx->claims->iss;
697
+ if (ctx->header->kid == NULL) {
698
+ gpr_log(GPR_ERROR, "Missing kid in jose header.");
699
+ goto error;
700
+ }
701
+ if (iss == NULL) {
702
+ gpr_log(GPR_ERROR, "Missing iss in claims.");
703
+ goto error;
704
+ }
705
+
706
+ /* This code relies on:
707
+ https://openid.net/specs/openid-connect-discovery-1_0.html
708
+ Nobody seems to implement the account/email/webfinger part 2. of the spec
709
+ so we will rely instead on email/url mappings if we detect such an issuer.
710
+ Part 4, on the other hand is implemented by both google and salesforce. */
711
+
712
+ /* Very non-sophisticated way to detect an email address. Should be good
713
+ enough for now... */
714
+ at_sign = strchr(iss, '@');
715
+ if (at_sign != NULL) {
716
+ email_key_mapping *mapping;
717
+ const char *email_domain = at_sign + 1;
718
+ GPR_ASSERT(ctx->verifier != NULL);
719
+ mapping = verifier_get_mapping(ctx->verifier, email_domain);
720
+ if (mapping == NULL) {
721
+ gpr_log(GPR_ERROR, "Missing mapping for issuer email.");
722
+ goto error;
723
+ }
724
+ req.host = gpr_strdup(mapping->key_url_prefix);
725
+ path_prefix = strchr(req.host, '/');
726
+ if (path_prefix == NULL) {
727
+ gpr_asprintf(&req.path, "/%s", iss);
728
+ } else {
729
+ *(path_prefix++) = '\0';
730
+ gpr_asprintf(&req.path, "/%s/%s", path_prefix, iss);
731
+ }
732
+ http_cb = on_keys_retrieved;
733
+ } else {
734
+ req.host = gpr_strdup(strstr(iss, "https://") == iss ? iss + 8 : iss);
735
+ path_prefix = strchr(req.host, '/');
736
+ if (path_prefix == NULL) {
737
+ req.path = gpr_strdup(GRPC_OPENID_CONFIG_URL_SUFFIX);
738
+ } else {
739
+ *(path_prefix++) = 0;
740
+ gpr_asprintf(&req.path, "/%s%s", path_prefix,
741
+ GRPC_OPENID_CONFIG_URL_SUFFIX);
742
+ }
743
+ http_cb = on_openid_config_retrieved;
744
+ }
745
+
746
+ grpc_httpcli_get(
747
+ exec_ctx, &ctx->verifier->http_ctx, ctx->pollset, &req,
748
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_max_delay),
749
+ http_cb, ctx);
750
+ gpr_free(req.host);
751
+ gpr_free(req.path);
752
+ return;
753
+
754
+ error:
755
+ ctx->user_cb(ctx->user_data, GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR, NULL);
756
+ verifier_cb_ctx_destroy(ctx);
757
+ }
758
+
759
+ void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
760
+ grpc_jwt_verifier *verifier,
761
+ grpc_pollset *pollset, const char *jwt,
762
+ const char *audience,
763
+ grpc_jwt_verification_done_cb cb,
764
+ void *user_data) {
765
+ const char *dot = NULL;
766
+ grpc_json *json;
767
+ jose_header *header = NULL;
768
+ grpc_jwt_claims *claims = NULL;
769
+ gpr_slice header_buffer;
770
+ gpr_slice claims_buffer;
771
+ gpr_slice signature;
772
+ size_t signed_jwt_len;
773
+ const char *cur = jwt;
774
+
775
+ GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL);
776
+ dot = strchr(cur, '.');
777
+ if (dot == NULL) goto error;
778
+ json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &header_buffer);
779
+ if (json == NULL) goto error;
780
+ header = jose_header_from_json(json, header_buffer);
781
+ if (header == NULL) goto error;
782
+
783
+ cur = dot + 1;
784
+ dot = strchr(cur, '.');
785
+ if (dot == NULL) goto error;
786
+ json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer);
787
+ if (json == NULL) goto error;
788
+ claims = grpc_jwt_claims_from_json(json, claims_buffer);
789
+ if (claims == NULL) goto error;
790
+
791
+ signed_jwt_len = (size_t)(dot - jwt);
792
+ cur = dot + 1;
793
+ signature = grpc_base64_decode(cur, 1);
794
+ if (GPR_SLICE_IS_EMPTY(signature)) goto error;
795
+ retrieve_key_and_verify(
796
+ exec_ctx,
797
+ verifier_cb_ctx_create(verifier, pollset, header, claims, audience,
798
+ signature, jwt, signed_jwt_len, user_data, cb));
799
+ return;
800
+
801
+ error:
802
+ if (header != NULL) jose_header_destroy(header);
803
+ if (claims != NULL) grpc_jwt_claims_destroy(claims);
804
+ cb(user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL);
805
+ }
806
+
807
+ grpc_jwt_verifier *grpc_jwt_verifier_create(
808
+ const grpc_jwt_verifier_email_domain_key_url_mapping *mappings,
809
+ size_t num_mappings) {
810
+ grpc_jwt_verifier *v = gpr_malloc(sizeof(grpc_jwt_verifier));
811
+ memset(v, 0, sizeof(grpc_jwt_verifier));
812
+ grpc_httpcli_context_init(&v->http_ctx);
813
+
814
+ /* We know at least of one mapping. */
815
+ v->allocated_mappings = 1 + num_mappings;
816
+ v->mappings = gpr_malloc(v->allocated_mappings * sizeof(email_key_mapping));
817
+ verifier_put_mapping(v, GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN,
818
+ GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX);
819
+ /* User-Provided mappings. */
820
+ if (mappings != NULL) {
821
+ size_t i;
822
+ for (i = 0; i < num_mappings; i++) {
823
+ verifier_put_mapping(v, mappings[i].email_domain,
824
+ mappings[i].key_url_prefix);
825
+ }
826
+ }
827
+ return v;
828
+ }
829
+
830
+ void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v) {
831
+ size_t i;
832
+ if (v == NULL) return;
833
+ grpc_httpcli_context_destroy(&v->http_ctx);
834
+ if (v->mappings != NULL) {
835
+ for (i = 0; i < v->num_mappings; i++) {
836
+ gpr_free(v->mappings[i].email_domain);
837
+ gpr_free(v->mappings[i].key_url_prefix);
838
+ }
839
+ gpr_free(v->mappings);
840
+ }
841
+ gpr_free(v);
842
+ }