From 30735395bf0192beeafb173e2497e96396c7bd96 Mon Sep 17 00:00:00 2001 From: Justin Azoff Date: Thu, 20 Jul 2017 22:50:08 -0400 Subject: [PATCH 1/3] problem: User-Id field in zap response is not populated. According to ZAP spec: user id: this MAY provide the user identity in case of a 200 status, for use by applications. For other statuses, it SHALL be empty. Solution: This adds a char pointer in the zap request struct that can point to the the username, client_key, or principal fields. With this change zframe_meta(frame, "User-Id") returns the public key for a connection. This enables a use case where you have a long lived connection authenticated by a key or password and want to verify that the user/key still exists. zframe_t *frame = zframe_recv(server); const char *user_id = zframe_meta(frame, "User-Id"); if(user_id!=NULL) { zcert_t *c = zcertstore_lookup(store, user_id); if(!c) //Certificate no longer exists in store! } --- src/zauth.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/zauth.c b/src/zauth.c index 0d002f27c..ae570b498 100644 --- a/src/zauth.c +++ b/src/zauth.c @@ -195,6 +195,7 @@ typedef struct { char *password; // PLAIN password, in clear text char *client_key; // CURVE client public key in ASCII char *principal; // GSSAPI client principal + char *user_id; // User-Id to return in the ZAP Response } zap_request_t; @@ -214,6 +215,7 @@ s_zap_request_destroy (zap_request_t **self_p) freen (self->password); freen (self->client_key); freen (self->principal); + // self->user_id is a pointer to one of the above fields freen (self); *self_p = NULL; } @@ -293,7 +295,7 @@ s_zap_request_reply (zap_request_t *self, char *status_code, char *status_text, assert (rc == 0); rc = zmsg_addstr(msg, status_text); assert (rc == 0); - rc = zmsg_addstr(msg, ""); + rc = zmsg_addstr(msg, self->user_id ? self->user_id : ""); assert (rc == 0); rc = zmsg_addmem(msg, metadata, metasize); assert (rc == 0); @@ -348,6 +350,7 @@ s_authenticate_plain (self_t *self, zap_request_t *request) if (self->verbose) zsys_info ("zauth: - allowed (PLAIN) username=%s password=%s", request->username, request->password); + request->user_id = request->username; return true; } else { @@ -395,6 +398,7 @@ s_authenticate_curve (self_t *self, zap_request_t *request, unsigned char **meta if (self->verbose) zsys_info ("zauth: - allowed (CURVE) client_key=%s", request->client_key); + request->user_id = request->client_key; return true; } } @@ -410,6 +414,7 @@ s_authenticate_gssapi (self_t *self, zap_request_t *request) if (self->verbose) zsys_info ("zauth: - allowed (GSSAPI) principal=%s identity=%s", request->principal, request->identity); + request->user_id = request->principal; return true; } From aac840032b20e2d48f2a8d6a5ba3e85072620be3 Mon Sep 17 00:00:00 2001 From: Justin Azoff Date: Fri, 21 Jul 2017 08:37:59 -0400 Subject: [PATCH 2/3] problem: zauth tests do not check User-Id metadata Solution: update the PLAIN and CURVE tests to fetch and verify the User-Id metadata set by ZAP --- src/zauth.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/zauth.c b/src/zauth.c index ae570b498..9dc86522a 100644 --- a/src/zauth.c +++ b/src/zauth.c @@ -654,9 +654,18 @@ zauth_test (bool verbose) zsock_set_plain_password (client, "Password"); zstr_sendx (auth, "PLAIN", TESTDIR "/password-file", NULL); zsock_wait (auth); - success = s_can_connect (&server, &client, true); + success = s_can_connect (&server, &client, false); assert (success); + // Test that the User-Id metadata is present + zframe_t *frame = zframe_recv (server); + assert (frame != NULL); + const char *user_id = zframe_meta (frame, "User-Id"); + assert (user_id != NULL); + assert (streq (user_id, "admin")); + zframe_destroy (&frame); + s_renew_sockets(&server, &client); + zsock_set_plain_server (server, 1); zsock_set_plain_username (client, "admin"); zsock_set_plain_password (client, "Bogus"); @@ -711,6 +720,9 @@ zauth_test (bool verbose) const char *meta = zframe_meta (frame, "Hello"); assert (meta != NULL); assert (streq (meta, "World!")); + const char *user_id = zframe_meta (frame, "User-Id"); + assert (user_id != NULL); + assert (streq (user_id, zcert_public_txt(client_cert))); zframe_destroy (&frame); s_renew_sockets(&server, &client); #endif From 69ee323fccd3e91b76f093be46caa41d7d860295 Mon Sep 17 00:00:00 2001 From: Justin Azoff Date: Fri, 21 Jul 2017 09:49:46 -0400 Subject: [PATCH 3/3] problem: Older ZAP does not populate User-Id metadata solution: Only run this test on newer versions of zmq --- src/zauth.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/zauth.c b/src/zauth.c index 9dc86522a..3cc051d26 100644 --- a/src/zauth.c +++ b/src/zauth.c @@ -657,6 +657,7 @@ zauth_test (bool verbose) success = s_can_connect (&server, &client, false); assert (success); +#if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (4, 1, 0)) // Test that the User-Id metadata is present zframe_t *frame = zframe_recv (server); assert (frame != NULL); @@ -664,6 +665,7 @@ zauth_test (bool verbose) assert (user_id != NULL); assert (streq (user_id, "admin")); zframe_destroy (&frame); +#endif s_renew_sockets(&server, &client); zsock_set_plain_server (server, 1);