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 | |
| 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>
| -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);  | 
