aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib
diff options
context:
space:
mode:
authorGravatar Julien Boeuf <jboeuf@google.com>2016-11-17 16:59:48 -0800
committerGravatar Julien Boeuf <jboeuf@google.com>2016-12-21 22:04:36 -0800
commit964d7bb4828461f4c4d51cfe7f774367fc162013 (patch)
treea633b1766d1e93e614dc0d5b420668260a489ff6 /src/core/lib
parentc3c1240ad5e2e7b3b25c28639ad8cf5152b19f33 (diff)
Fixing JWT verifier.
- Initializes grpc correctly in the JWT utils. - Make the email mapping work with the new service accounts produced by Google IAM. - Adding check for email issuers where the issuer has to be the subject as well. - Implementing portable version of memrchr.
Diffstat (limited to 'src/core/lib')
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_verifier.c38
-rw-r--r--src/core/lib/security/credentials/jwt/jwt_verifier.h5
-rw-r--r--src/core/lib/support/string.c11
-rw-r--r--src/core/lib/support/string.h2
4 files changed, 47 insertions, 9 deletions
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.c b/src/core/lib/security/credentials/jwt/jwt_verifier.c
index 42bd89dd0a..03097a57c0 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.c
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.c
@@ -39,6 +39,7 @@
#include "src/core/lib/http/httpcli.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/security/util/b64.h"
+#include "src/core/lib/support/string.h"
#include "src/core/lib/tsi/ssl_types.h"
#include <grpc/support/alloc.h>
@@ -305,6 +306,17 @@ grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
}
+ /* This should be probably up to the upper layer to decide but let's harcode
+ the 99% use case here for email issuers, where the JWT must be self
+ issued. */
+ if (grpc_jwt_issuer_email_domain(claims->iss) != NULL &&
+ claims->sub != NULL && strcmp(claims->iss, claims->sub) != 0) {
+ gpr_log(GPR_ERROR,
+ "Email issuer (%s) cannot assert another subject (%s) than itself.",
+ claims->iss, claims->sub);
+ return GRPC_JWT_VERIFIER_BAD_SUBJECT;
+ }
+
if (audience == NULL) {
audience_ok = claims->aud == NULL;
} else {
@@ -705,10 +717,26 @@ static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain,
GPR_ASSERT(v->num_mappings <= v->allocated_mappings);
}
+/* Very non-sophisticated way to detect an email address. Should be good
+ enough for now... */
+const char *grpc_jwt_issuer_email_domain(const char *issuer) {
+ const char *at_sign = strchr(issuer, '@');
+ if (at_sign == NULL) return NULL;
+ const char *email_domain = at_sign + 1;
+ if (*email_domain == '\0') return NULL;
+ const char *dot = strrchr(email_domain, '.');
+ if (dot == NULL || dot == email_domain) return email_domain;
+ GPR_ASSERT(dot > email_domain);
+ /* There may be a subdomain, we just want the domain. */
+ dot = gpr_memrchr(email_domain, '.', (size_t)(dot - email_domain));
+ if (dot == NULL) return email_domain;
+ return dot + 1;
+}
+
/* Takes ownership of ctx. */
static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
verifier_cb_ctx *ctx) {
- const char *at_sign;
+ const char *email_domain;
grpc_closure *http_cb;
char *path_prefix = NULL;
const char *iss;
@@ -733,13 +761,9 @@ static void retrieve_key_and_verify(grpc_exec_ctx *exec_ctx,
Nobody seems to implement the account/email/webfinger part 2. of the spec
so we will rely instead on email/url mappings if we detect such an issuer.
Part 4, on the other hand is implemented by both google and salesforce. */
-
- /* Very non-sophisticated way to detect an email address. Should be good
- enough for now... */
- at_sign = strchr(iss, '@');
- if (at_sign != NULL) {
+ email_domain = grpc_jwt_issuer_email_domain(iss);
+ if (email_domain != NULL) {
email_key_mapping *mapping;
- const char *email_domain = at_sign + 1;
GPR_ASSERT(ctx->verifier != NULL);
mapping = verifier_get_mapping(ctx->verifier, email_domain);
if (mapping == NULL) {
diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.h b/src/core/lib/security/credentials/jwt/jwt_verifier.h
index f09f9d5d47..54ff9b05e5 100644
--- a/src/core/lib/security/credentials/jwt/jwt_verifier.h
+++ b/src/core/lib/security/credentials/jwt/jwt_verifier.h
@@ -43,8 +43,7 @@
/* --- Constants. --- */
#define GRPC_OPENID_CONFIG_URL_SUFFIX "/.well-known/openid-configuration"
-#define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN \
- "developer.gserviceaccount.com"
+#define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN "gserviceaccount.com"
#define GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX \
"www.googleapis.com/robot/v1/metadata/x509"
@@ -57,6 +56,7 @@ typedef enum {
GRPC_JWT_VERIFIER_BAD_AUDIENCE,
GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR,
GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE,
+ GRPC_JWT_VERIFIER_BAD_SUBJECT,
GRPC_JWT_VERIFIER_GENERIC_ERROR
} grpc_jwt_verifier_status;
@@ -132,5 +132,6 @@ void grpc_jwt_verifier_verify(grpc_exec_ctx *exec_ctx,
grpc_jwt_claims *grpc_jwt_claims_from_json(grpc_json *json, grpc_slice buffer);
grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims,
const char *audience);
+const char *grpc_jwt_issuer_email_domain(const char *issuer);
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_JWT_JWT_VERIFIER_H */
diff --git a/src/core/lib/support/string.c b/src/core/lib/support/string.c
index f10a30f0fd..f263f82baf 100644
--- a/src/core/lib/support/string.c
+++ b/src/core/lib/support/string.c
@@ -275,3 +275,14 @@ int gpr_stricmp(const char *a, const char *b) {
} while (ca == cb && ca && cb);
return ca - cb;
}
+
+void *gpr_memrchr(const void *s, int c, size_t n) {
+ if (s == NULL) return NULL;
+ char *b = (char *)s;
+ for (size_t i = 0; i < n; i++) {
+ if (b[n - i - 1] == c) {
+ return &b[n - i - 1];
+ }
+ }
+ return NULL;
+}
diff --git a/src/core/lib/support/string.h b/src/core/lib/support/string.h
index e933e2eb46..6d1f7cc632 100644
--- a/src/core/lib/support/string.h
+++ b/src/core/lib/support/string.h
@@ -118,6 +118,8 @@ char *gpr_strvec_flatten(gpr_strvec *strs, size_t *total_length);
lower(a)==lower(b), >0 if lower(a)>lower(b) */
int gpr_stricmp(const char *a, const char *b);
+void *gpr_memrchr(const void *s, int c, size_t n);
+
#ifdef __cplusplus
}
#endif