static gpr_slice compute_default_pem_root_certs_once(void) { gpr_slice result = gpr_empty_slice(); /* First try to load the roots from the environment. */ char *default_root_certs_path = gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); if (default_root_certs_path != NULL) { result = gpr_load_file(default_root_certs_path, 0, NULL); gpr_free(default_root_certs_path); } /* Try overridden roots if needed. */ grpc_ssl_roots_override_result ovrd_res = GRPC_SSL_ROOTS_OVERRIDE_FAIL; if (GPR_SLICE_IS_EMPTY(result) && ssl_roots_override_cb != NULL) { char *pem_root_certs = NULL; ovrd_res = ssl_roots_override_cb(&pem_root_certs); if (ovrd_res == GRPC_SSL_ROOTS_OVERRIDE_OK) { GPR_ASSERT(pem_root_certs != NULL); result = gpr_slice_new(pem_root_certs, strlen(pem_root_certs), gpr_free); } } /* Fall back to installed certs if needed. */ if (GPR_SLICE_IS_EMPTY(result) && ovrd_res != GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY) { result = gpr_load_file(installed_roots_path, 0, NULL); } return result; }
static void connected(grpc_exec_ctx *exec_ctx, void *arg, int success) { connector *c = arg; grpc_closure *notify; grpc_endpoint *tcp = c->newly_connecting_endpoint; if (tcp != NULL) { gpr_mu_lock(&c->mu); GPR_ASSERT(c->connecting_endpoint == NULL); c->connecting_endpoint = tcp; gpr_mu_unlock(&c->mu); if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) { grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent, c); gpr_slice_buffer_init(&c->initial_string_buffer); gpr_slice_buffer_add(&c->initial_string_buffer, c->args.initial_connect_string); grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer, &c->initial_string_sent); } else { grpc_security_connector_do_handshake(exec_ctx, &c->security_connector->base, tcp, on_secure_handshake_done, c); } } else { memset(c->result, 0, sizeof(*c->result)); notify = c->notify; c->notify = NULL; notify->cb(exec_ctx, notify->cb_arg, 1); } }
static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { connector *c = arg; grpc_closure *notify; grpc_endpoint *tcp = c->newly_connecting_endpoint; if (tcp != NULL) { gpr_mu_lock(&c->mu); GPR_ASSERT(c->connecting_endpoint == NULL); c->connecting_endpoint = tcp; gpr_mu_unlock(&c->mu); if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) { grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent, c); gpr_slice_buffer_init(&c->initial_string_buffer); gpr_slice_buffer_add(&c->initial_string_buffer, c->args.initial_connect_string); grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer, &c->initial_string_sent); } else { grpc_channel_security_connector_do_handshake( exec_ctx, c->security_connector, tcp, c->args.deadline, on_secure_handshake_done, c); } } else { memset(c->result, 0, sizeof(*c->result)); notify = c->notify; c->notify = NULL; grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL); } }
static void connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) { connector *c = arg; grpc_closure *notify; grpc_endpoint *tcp = c->tcp; if (tcp != NULL) { if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) { grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent, c); gpr_slice_buffer_init(&c->initial_string_buffer); gpr_slice_buffer_add(&c->initial_string_buffer, c->args.initial_connect_string); connector_ref(arg); grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer, &c->initial_string_sent); } c->result->transport = grpc_create_chttp2_transport(exec_ctx, c->args.channel_args, tcp, 1); grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL, 0); GPR_ASSERT(c->result->transport); c->result->channel_args = c->args.channel_args; } else { memset(c->result, 0, sizeof(*c->result)); } notify = c->notify; c->notify = NULL; notify->cb(exec_ctx, notify->cb_arg, 1); }
static void connected(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { connector *c = arg; grpc_endpoint *tcp = c->tcp; if (tcp != NULL) { if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) { grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent, c); gpr_slice_buffer_init(&c->initial_string_buffer); gpr_slice_buffer_add(&c->initial_string_buffer, c->args.initial_connect_string); connector_ref(arg); grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer, &c->initial_string_sent); } else { grpc_handshake_manager_do_handshake( exec_ctx, c->handshake_mgr, tcp, c->args.channel_args, c->args.deadline, NULL /* acceptor */, on_handshake_done, c); } } else { memset(c->result, 0, sizeof(*c->result)); grpc_closure *notify = c->notify; c->notify = NULL; grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_REF(error), NULL); } }
static void test_url_safe_unsafe_mismtach_failure(void) { unsigned char orig[256]; size_t i; char *b64; gpr_slice orig_decoded; int url_safe = 1; for (i = 0; i < sizeof(orig); i++) orig[i] = (char)i; b64 = grpc_base64_encode(orig, sizeof(orig), url_safe, 0); orig_decoded = grpc_base64_decode(b64, !url_safe); GPR_ASSERT(GPR_SLICE_IS_EMPTY(orig_decoded)); gpr_free(b64); gpr_slice_unref(orig_decoded); b64 = grpc_base64_encode(orig, sizeof(orig), !url_safe, 0); orig_decoded = grpc_base64_decode(b64, url_safe); GPR_ASSERT(GPR_SLICE_IS_EMPTY(orig_decoded)); gpr_free(b64); gpr_slice_unref(orig_decoded); }
static BIGNUM *bignum_from_base64(const char *b64) { BIGNUM *result = NULL; gpr_slice bin; if (b64 == NULL) return NULL; bin = grpc_base64_decode(b64, 1); if (GPR_SLICE_IS_EMPTY(bin)) { gpr_log(GPR_ERROR, "Invalid base64 for big num."); return NULL; } result = BN_bin2bn(GPR_SLICE_START_PTR(bin), GPR_SLICE_LENGTH(bin), NULL); gpr_slice_unref(bin); return result; }
static void init_default_pem_root_certs(void) { /* First try to load the roots from the environment. */ char *default_root_certs_path = gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR); if (default_root_certs_path == NULL) { default_pem_root_certs = gpr_empty_slice(); } else { default_pem_root_certs = gpr_load_file(default_root_certs_path, 0, NULL); gpr_free(default_root_certs_path); } /* Fall back to installed certs if needed. */ if (GPR_SLICE_IS_EMPTY(default_pem_root_certs)) { default_pem_root_certs = gpr_load_file(installed_roots_path, 0, NULL); } }
static void corrupt_jwt_sig(char *jwt) { gpr_slice sig; char *bad_b64_sig; uint8_t *sig_bytes; char *last_dot = strrchr(jwt, '.'); GPR_ASSERT(last_dot != NULL); sig = grpc_base64_decode(last_dot + 1, 1); GPR_ASSERT(!GPR_SLICE_IS_EMPTY(sig)); sig_bytes = GPR_SLICE_START_PTR(sig); (*sig_bytes)++; /* Corrupt first byte. */ bad_b64_sig = grpc_base64_encode(GPR_SLICE_START_PTR(sig), GPR_SLICE_LENGTH(sig), 1, 0); memcpy(last_dot + 1, bad_b64_sig, strlen(bad_b64_sig)); gpr_free(bad_b64_sig); gpr_slice_unref(sig); }
void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx, grpc_jwt_verifier *verifier, grpc_pollset *pollset, const char *jwt, const char *audience, grpc_jwt_verification_done_cb cb, void *user_data) { const char *dot = NULL; grpc_json *json; jose_header *header = NULL; grpc_jwt_claims *claims = NULL; gpr_slice header_buffer; gpr_slice claims_buffer; gpr_slice signature; size_t signed_jwt_len; const char *cur = jwt; GPR_ASSERT(verifier != NULL && jwt != NULL && audience != NULL && cb != NULL); dot = strchr(cur, '.'); if (dot == NULL) goto error; json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &header_buffer); if (json == NULL) goto error; header = jose_header_from_json(json, header_buffer); if (header == NULL) goto error; cur = dot + 1; dot = strchr(cur, '.'); if (dot == NULL) goto error; json = parse_json_part_from_jwt(cur, (size_t)(dot - cur), &claims_buffer); if (json == NULL) goto error; claims = grpc_jwt_claims_from_json(json, claims_buffer); if (claims == NULL) goto error; signed_jwt_len = (size_t)(dot - jwt); cur = dot + 1; signature = grpc_base64_decode(cur, 1); if (GPR_SLICE_IS_EMPTY(signature)) goto error; retrieve_key_and_verify( exec_ctx, verifier_cb_ctx_create(verifier, pollset, header, claims, audience, signature, jwt, signed_jwt_len, user_data, cb)); return; error: if (header != NULL) jose_header_destroy(header); if (claims != NULL) grpc_jwt_claims_destroy(claims); cb(user_data, GRPC_JWT_VERIFIER_BAD_FORMAT, NULL); }
static void test_default_ssl_roots(void) { const char *roots_for_env_var = "roots for env var"; char *roots_env_var_file_path; FILE *roots_env_var_file = gpr_tmpfile("test_roots_for_env_var", &roots_env_var_file_path); fwrite(roots_for_env_var, 1, strlen(roots_for_env_var), roots_env_var_file); fclose(roots_env_var_file); /* First let's get the root through the override: set the env to an invalid value. */ gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, ""); grpc_set_ssl_roots_override_callback(override_roots_success); gpr_slice roots = grpc_get_default_ssl_roots_for_testing(); char *roots_contents = gpr_dump_slice(roots, GPR_DUMP_ASCII); gpr_slice_unref(roots); GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); gpr_free(roots_contents); /* Now let's set the env var: We should get the contents pointed value instead. */ gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_env_var_file_path); roots = grpc_get_default_ssl_roots_for_testing(); roots_contents = gpr_dump_slice(roots, GPR_DUMP_ASCII); gpr_slice_unref(roots); GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0); gpr_free(roots_contents); /* Now reset the env var. We should fall back to the value overridden using the api. */ gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, ""); roots = grpc_get_default_ssl_roots_for_testing(); roots_contents = gpr_dump_slice(roots, GPR_DUMP_ASCII); gpr_slice_unref(roots); GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0); gpr_free(roots_contents); /* Now setup a permanent failure for the overridden roots and we should get an empty slice. */ grpc_set_ssl_roots_override_callback(override_roots_permanent_failure); roots = grpc_get_default_ssl_roots_for_testing(); GPR_ASSERT(GPR_SLICE_IS_EMPTY(roots)); /* Cleanup. */ remove(roots_env_var_file_path); gpr_free(roots_env_var_file_path); }
static grpc_json *parse_json_part_from_jwt(const char *str, size_t len, gpr_slice *buffer) { grpc_json *json; *buffer = grpc_base64_decode_with_len(str, len, 1); if (GPR_SLICE_IS_EMPTY(*buffer)) { gpr_log(GPR_ERROR, "Invalid base64."); return NULL; } json = grpc_json_parse_string_with_len((char *)GPR_SLICE_START_PTR(*buffer), GPR_SLICE_LENGTH(*buffer)); if (json == NULL) { gpr_slice_unref(*buffer); gpr_log(GPR_ERROR, "JSON parsing error."); } return json; }
static grpc_json *parse_json_part_from_jwt(const char *str, size_t len, char **scratchpad) { char *b64; char *decoded; grpc_json *json; gpr_slice slice; b64 = gpr_malloc(len + 1); strncpy(b64, str, len); b64[len] = '\0'; slice = grpc_base64_decode(b64, 1); GPR_ASSERT(!GPR_SLICE_IS_EMPTY(slice)); decoded = gpr_malloc(GPR_SLICE_LENGTH(slice) + 1); strncpy(decoded, (const char *)GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice)); decoded[GPR_SLICE_LENGTH(slice)] = '\0'; json = grpc_json_parse_string(decoded); gpr_free(b64); *scratchpad = decoded; gpr_slice_unref(slice); return json; }
static void check_jwt_signature(const char *b64_signature, RSA *rsa_key, const char *signed_data, size_t signed_data_size) { EVP_MD_CTX *md_ctx = EVP_MD_CTX_create(); EVP_PKEY *key = EVP_PKEY_new(); gpr_slice sig = grpc_base64_decode(b64_signature, 1); GPR_ASSERT(!GPR_SLICE_IS_EMPTY(sig)); GPR_ASSERT(GPR_SLICE_LENGTH(sig) == 128); GPR_ASSERT(md_ctx != NULL); GPR_ASSERT(key != NULL); EVP_PKEY_set1_RSA(key, rsa_key); GPR_ASSERT(EVP_DigestVerifyInit(md_ctx, NULL, EVP_sha256(), NULL, key) == 1); GPR_ASSERT(EVP_DigestVerifyUpdate(md_ctx, signed_data, signed_data_size) == 1); GPR_ASSERT(EVP_DigestVerifyFinal(md_ctx, GPR_SLICE_START_PTR(sig), GPR_SLICE_LENGTH(sig)) == 1); gpr_slice_unref(sig); if (key != NULL) EVP_PKEY_free(key); if (md_ctx != NULL) EVP_MD_CTX_destroy(md_ctx); }