diff options
author | Kaushal M <kaushal@redhat.com> | 2015-04-02 23:06:18 +0530 |
---|---|---|
committer | Krishnan Parthasarathi <kparthas@redhat.com> | 2015-04-09 12:05:09 +0000 |
commit | e0de0cd9b24169b90c95e1f6a87f05c060185089 (patch) | |
tree | 557ab813c610f6f2f7ce1764ec1e4b9763e58d29 /xlators/mgmt/glusterd/src/glusterd-handshake.c | |
parent | 026d59f04b4226c646c6bd9ac1018863057b02c1 (diff) |
glusterd: Better GlusterD handshake request validation
To allow handshake requests to be validated correctly in a multi network
environment, the request validation process has been improved.
The handshake request initiator will add it's peer ID the request.
The handshake request reciever will allow a request (as before) if,
- it has no peers, or
- the request came from a known peer
Identifying the known peer is done as follows.
- If the request contains a peer ID, it is matched against the IDs in
the peer list. If a match is found, the request is allowed.
- The address of the incoming request is matched against the peer
addresses in the peer list. If a match is found, the request is
allowed.
- Otherwise, the request if disallowed
Change-Id: I9eabe2935d16276bb147dfeebf8c8beb08e01411
BUG: 1207611
Signed-off-by: Kaushal M <kaushal@redhat.com>
Reviewed-on: http://review.gluster.org/10122
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
Tested-by: Krishnan Parthasarathi <kparthas@redhat.com>
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-handshake.c')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handshake.c | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index 850427714c0..bc00e99b62f 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handshake.c +++ b/xlators/mgmt/glusterd/src/glusterd-handshake.c @@ -38,6 +38,7 @@ extern struct rpc_clnt_program gd_mgmt_v3_prog; #define TRUSTED_PREFIX "trusted-" +#define GD_PEER_ID_KEY "peer-id" typedef ssize_t (*gfs_serialize_t) (struct iovec outmsg, void *data); @@ -955,14 +956,20 @@ out: * Requests are allowed if, * - glusterd has no peers, or * - the request came from a known peer + * A known peer is identified using the following steps + * - the dict is checked for a peer uuid, which if present is matched with the + * peer list, else + * - the incoming request address is matched with the peer list */ gf_boolean_t -gd_validate_mgmt_hndsk_req (rpcsvc_request_t *req) +gd_validate_mgmt_hndsk_req (rpcsvc_request_t *req, dict_t *dict) { int ret = -1; char hostname[UNIX_PATH_MAX + 1] = {0,}; glusterd_peerinfo_t *peer = NULL; xlator_t *this = NULL; + char *uuid_str = NULL; + uuid_t peer_uuid = {0,}; this = THIS; GF_ASSERT (this); @@ -970,6 +977,19 @@ gd_validate_mgmt_hndsk_req (rpcsvc_request_t *req) if (!glusterd_have_peers ()) return _gf_true; + ret = dict_get_str (dict, GD_PEER_ID_KEY, &uuid_str); + /* Try to match uuid only if available, don't fail as older peers will + * not send a uuid + */ + if (!ret) { + gf_uuid_parse (uuid_str, peer_uuid); + rcu_read_lock (); + ret = (glusterd_peerinfo_find (peer_uuid, NULL) != NULL); + rcu_read_unlock (); + if (ret) + return _gf_true; + } + /* If you cannot get the hostname, you cannot authenticate */ ret = glusterd_remote_hostname_get (req, hostname, sizeof (hostname)); if (ret) @@ -999,16 +1019,11 @@ __glusterd_mgmt_hndsk_versions (rpcsvc_request_t *req) int op_errno = EINVAL; gf_mgmt_hndsk_req args = {{0,},}; gf_mgmt_hndsk_rsp rsp = {0,}; + dict_t *args_dict = NULL; this = THIS; conf = this->private; - /* Check if we can service the request */ - if (!gd_validate_mgmt_hndsk_req (req)) { - ret = -1; - goto out; - } - ret = xdr_to_generic (req->msg[0], &args, (xdrproc_t)xdr_gf_mgmt_hndsk_req); if (ret < 0) { @@ -1017,6 +1032,16 @@ __glusterd_mgmt_hndsk_versions (rpcsvc_request_t *req) goto out; } + GF_PROTOCOL_DICT_UNSERIALIZE (this, args_dict, args.hndsk.hndsk_val, + (args.hndsk.hndsk_len), ret, op_errno, + out); + + /* Check if we can service the request */ + if (!gd_validate_mgmt_hndsk_req (req, args_dict)) { + ret = -1; + goto out; + } + dict = dict_new (); if (!dict) goto out; @@ -1093,12 +1118,6 @@ __glusterd_mgmt_hndsk_versions_ack (rpcsvc_request_t *req) this = THIS; conf = this->private; - /* Check if we can service the request */ - if (!gd_validate_mgmt_hndsk_req (req)) { - ret = -1; - goto out; - } - ret = xdr_to_generic (req->msg[0], &args, (xdrproc_t)xdr_gf_mgmt_hndsk_req); if (ret < 0) { @@ -1813,7 +1832,9 @@ glusterd_mgmt_handshake (xlator_t *this, glusterd_peerctx_t *peerctx) call_frame_t *frame = NULL; gf_mgmt_hndsk_req req = {{0,},}; glusterd_peerinfo_t *peerinfo = NULL; + dict_t *req_dict = NULL; int ret = -1; + int op_errno = EINVAL; frame = create_frame (this, this->ctx->pool); if (!frame) @@ -1821,6 +1842,21 @@ glusterd_mgmt_handshake (xlator_t *this, glusterd_peerctx_t *peerctx) frame->local = peerctx; + req_dict = dict_new (); + if (!req_dict) + goto out; + + ret = dict_set_dynstr (req_dict, GD_PEER_ID_KEY, + gf_strdup (uuid_utoa (MY_UUID))); + if (ret) { + gf_log(this->name, GF_LOG_ERROR, + "failed to set peer ID in dict"); + goto out; + } + + GF_PROTOCOL_DICT_SERIALIZE (this, req_dict, (&req.hndsk.hndsk_val), + req.hndsk.hndsk_len, op_errno, out); + rcu_read_lock (); peerinfo = glusterd_peerinfo_find (peerctx->peerid, peerctx->peername); |