diff options
Diffstat (limited to 'rpc/rpc-lib/src')
| -rw-r--r-- | rpc/rpc-lib/src/rpc-clnt.c | 22 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpc-common.c | 6 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpc-transport.c | 16 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpc-transport.h | 4 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc-auth.c | 91 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc-common.h | 2 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc.c | 617 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc.h | 25 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/xdr-common.h | 2 | 
9 files changed, 742 insertions, 43 deletions
diff --git a/rpc/rpc-lib/src/rpc-clnt.c b/rpc/rpc-lib/src/rpc-clnt.c index 819951c7e0d..09e676179d3 100644 --- a/rpc/rpc-lib/src/rpc-clnt.c +++ b/rpc/rpc-lib/src/rpc-clnt.c @@ -392,7 +392,8 @@ rpc_clnt_reconnect (void *trans_ptr)                          gf_log (trans->name, GF_LOG_TRACE,                                  "attempting reconnect"); -                        ret = rpc_transport_connect (trans, conn->config.remote_port); +                        ret = rpc_transport_connect (trans, +                                                     conn->config.remote_port);                          /* Every time there is a disconnection, processes                             should try to connect to 'glusterd' (ie, default                             port) or whichever port given as 'option remote-port' @@ -435,7 +436,8 @@ rpc_clnt_fill_request_info (struct rpc_clnt *clnt, rpc_request_info_t *info)          pthread_mutex_unlock (&clnt->conn.lock);          if (ret == -1) { -                gf_log (clnt->conn.trans->name, GF_LOG_CRITICAL, "cannot lookup the saved " +                gf_log (clnt->conn.trans->name, GF_LOG_CRITICAL, +                        "cannot lookup the saved "                          "frame corresponding to xid (%d)", info->xid);                  goto out;          } @@ -633,7 +635,8 @@ rpc_clnt_reply_init (rpc_clnt_connection_t *conn, rpc_transport_pollin_t *msg,                  goto out;          } -        gf_log (conn->trans->name, GF_LOG_TRACE, "received rpc message (RPC XID: 0x%ux" +        gf_log (conn->trans->name, GF_LOG_TRACE, +                "received rpc message (RPC XID: 0x%ux"                  " Program: %s, ProgVers: %d, Proc: %d) from rpc-transport (%s)",                  saved_frame->rpcreq->xid,                  saved_frame->rpcreq->prog->progname, @@ -831,8 +834,8 @@ rpc_clnt_notify (rpc_transport_t *trans, void *mydata,                  pthread_mutex_unlock (&conn->lock);                  if (clnt->notifyfn) -                        ret = clnt->notifyfn (clnt, clnt->mydata, RPC_CLNT_DISCONNECT, -                                              NULL); +                        ret = clnt->notifyfn (clnt, clnt->mydata, +                                              RPC_CLNT_DISCONNECT, NULL);                  break;          } @@ -878,7 +881,8 @@ rpc_clnt_notify (rpc_transport_t *trans, void *mydata,          case RPC_TRANSPORT_CONNECT:          {                  if (clnt->notifyfn) -                        ret = clnt->notifyfn (clnt, clnt->mydata, RPC_CLNT_CONNECT, NULL); +                        ret = clnt->notifyfn (clnt, clnt->mydata, +                                              RPC_CLNT_CONNECT, NULL);                  break;          } @@ -1051,7 +1055,8 @@ xdr_serialize_glusterfs_auth (char *dest, struct auth_glusterfs_parms *au)                         XDR_ENCODE);          if (!xdr_auth_glusterfs_parms (&xdr, au)) { -                gf_log (THIS->name, GF_LOG_WARNING, "failed to encode auth glusterfs elements"); +                gf_log (THIS->name, GF_LOG_WARNING, +                        "failed to encode auth glusterfs elements");                  ret = -1;                  goto ret;          } @@ -1145,7 +1150,8 @@ out:  struct iobuf *  rpc_clnt_record_build_record (struct rpc_clnt *clnt, int prognum, int progver,                                int procnum, size_t payload, uint64_t xid, -                              struct auth_glusterfs_parms *au, struct iovec *recbuf) +                              struct auth_glusterfs_parms *au, +                              struct iovec *recbuf)  {          struct rpc_msg           request                            = {0, };          struct iobuf            *request_iob                        = NULL; diff --git a/rpc/rpc-lib/src/rpc-common.c b/rpc/rpc-lib/src/rpc-common.c index db7b92834e7..d62ed42042a 100644 --- a/rpc/rpc-lib/src/rpc-common.c +++ b/rpc/rpc-lib/src/rpc-common.c @@ -89,7 +89,8 @@ xdr_gf_prog_detail (XDR *xdrs, gf_prog_detail *objp)  		 return FALSE;  	 if (!xdr_u_quad_t (xdrs, &objp->progver))  		 return FALSE; -	 if (!xdr_pointer (xdrs, (char **)&objp->next, sizeof (gf_prog_detail), (xdrproc_t) xdr_gf_prog_detail)) +	 if (!xdr_pointer (xdrs, (char **)&objp->next, sizeof (gf_prog_detail), +                           (xdrproc_t) xdr_gf_prog_detail))  		 return FALSE;  	return TRUE;  } @@ -103,7 +104,8 @@ xdr_gf_dump_rsp (XDR *xdrs, gf_dump_rsp *objp)  		 return FALSE;  	 if (!xdr_int (xdrs, &objp->op_errno))  		 return FALSE; -	 if (!xdr_pointer (xdrs, (char **)&objp->prog, sizeof (gf_prog_detail), (xdrproc_t) xdr_gf_prog_detail)) +	 if (!xdr_pointer (xdrs, (char **)&objp->prog, sizeof (gf_prog_detail), +                           (xdrproc_t) xdr_gf_prog_detail))  		 return FALSE;  	return TRUE;  } diff --git a/rpc/rpc-lib/src/rpc-transport.c b/rpc/rpc-lib/src/rpc-transport.c index 082ceec6e7b..b7245a8c9b8 100644 --- a/rpc/rpc-lib/src/rpc-transport.c +++ b/rpc/rpc-lib/src/rpc-transport.c @@ -525,7 +525,7 @@ rpc_transport_pollin_destroy (rpc_transport_pollin_t *pollin)          if (pollin->iobref) {                  iobref_unref (pollin->iobref);          } -  +          if (pollin->hdr_iobuf) {                  iobuf_unref (pollin->hdr_iobuf);          } @@ -909,7 +909,8 @@ rpc_transport_unref (rpc_transport_t *this)  	if (refcount == 0) {                  if (this->mydata) -                        this->notify (this, this->mydata, RPC_TRANSPORT_CLEANUP, NULL); +                        this->notify (this, this->mydata, RPC_TRANSPORT_CLEANUP, +                                      NULL);  		rpc_transport_destroy (this);  	} @@ -978,7 +979,8 @@ out:  }  int -rpc_transport_inet_options_build (dict_t **options, const char *hostname, int port) +rpc_transport_inet_options_build (dict_t **options, const char *hostname, +                                  int port)  {          dict_t          *dict = NULL;          char            *host = NULL; @@ -1000,15 +1002,15 @@ rpc_transport_inet_options_build (dict_t **options, const char *hostname, int po          ret = dict_set_dynstr (dict, "remote-host", host);          if (ret) { -                gf_log (THIS->name, GF_LOG_WARNING, "failed to set remote-host with %s", -                        host); +                gf_log (THIS->name, GF_LOG_WARNING, +                        "failed to set remote-host with %s", host);                  goto out;          }          ret = dict_set_int32 (dict, "remote-port", port);          if (ret) { -                gf_log (THIS->name, GF_LOG_WARNING, "failed to set remote-port with %d", -                        port); +                gf_log (THIS->name, GF_LOG_WARNING, +                        "failed to set remote-port with %d", port);                  goto out;          }          ret = dict_set_str (dict, "transport.address-family", "inet/inet6"); diff --git a/rpc/rpc-lib/src/rpc-transport.h b/rpc/rpc-lib/src/rpc-transport.h index f8396f572eb..5790b23f4f8 100644 --- a/rpc/rpc-lib/src/rpc-transport.h +++ b/rpc/rpc-lib/src/rpc-transport.h @@ -188,7 +188,7 @@ struct rpc_transport {                                                * transport came from. valid only                                                * on server process.                                                */ -         +  	void                      *private;          void                      *xl_private;          void                      *xl;       /* Used for THIS */ @@ -203,7 +203,7 @@ struct rpc_transport {  	data_t                    *buf;   	int32_t                  (*init)   (rpc_transport_t *this);  	void                     (*fini)   (rpc_transport_t *this); -        int32_t                  (*validate_options) (rpc_transport_t *this,  +        int32_t                  (*validate_options) (rpc_transport_t *this,                                                        char **op_errstr);          int                      (*reconfigure) (rpc_transport_t *this, dict_t *options);          rpc_transport_notify_t     notify; diff --git a/rpc/rpc-lib/src/rpcsvc-auth.c b/rpc/rpc-lib/src/rpcsvc-auth.c index fcf4617ca9b..558ada509f0 100644 --- a/rpc/rpc-lib/src/rpcsvc-auth.c +++ b/rpc/rpc-lib/src/rpcsvc-auth.c @@ -318,8 +318,8 @@ rpcsvc_authenticate (rpcsvc_request_t *req)          if (!req)                  return ret; -        //minauth = rpcsvc_request_prog_minauth (req); -        minauth = 1; +        /* FIXME use rpcsvc_request_prog_minauth() */ +        minauth = 0;          if (minauth > rpcsvc_request_cred_flavour (req)) {                  gf_log (GF_RPCSVC, GF_LOG_WARNING, "Auth too weak");                  rpcsvc_request_set_autherr (req, AUTH_TOOWEAK); @@ -339,6 +339,93 @@ err:          return ret;  } +int +rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen) +{ +        int             count = 0; +        int             gen = RPCSVC_AUTH_REJECT; +        int             spec = RPCSVC_AUTH_REJECT; +        int             final = RPCSVC_AUTH_REJECT; +        char            *srchstr = NULL; +        char            *valstr = NULL; +        gf_boolean_t    boolval = _gf_false; +        int             ret = 0; + +        struct rpcsvc_auth_list *auth = NULL; +        struct rpcsvc_auth_list *tmp = NULL; + +        if ((!svc) || (!autharr) || (!volname)) +                return -1; + +        memset (autharr, 0, arrlen * sizeof(int)); +        if (list_empty (&svc->authschemes)) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "No authentication!"); +                goto err; +        } + +        list_for_each_entry_safe (auth, tmp, &svc->authschemes, authlist) { +                if (count >= arrlen) +                        break; + +                gen = gf_asprintf (&srchstr, "rpc-auth.%s", auth->name); +                if (gen == -1) { +                        count = -1; +                        goto err; +                } + +                gen = RPCSVC_AUTH_REJECT; +                if (dict_get (svc->options, srchstr)) { +                        ret = dict_get_str (svc->options, srchstr, &valstr); +                        if (ret == 0) { +                                ret = gf_string2boolean (valstr, &boolval); +                                if (ret == 0) { +                                        if (boolval == _gf_true) +                                                gen = RPCSVC_AUTH_ACCEPT; +                                } else +                                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" +                                                "d to read auth val"); +                        } else +                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" +                                        "d to read auth val"); +                } + +                GF_FREE (srchstr); +                spec = gf_asprintf (&srchstr, "rpc-auth.%s.%s", auth->name, +                                    volname); +                if (spec == -1) { +                        count = -1; +                        goto err; +                } + +                spec = RPCSVC_AUTH_DONTCARE; +                if (dict_get (svc->options, srchstr)) { +                        ret = dict_get_str (svc->options, srchstr, &valstr); +                        if (ret == 0) { +                                ret = gf_string2boolean (valstr, &boolval); +                                if (ret == 0) { +                                        if (boolval == _gf_true) +                                                spec = RPCSVC_AUTH_ACCEPT; +                                        else +                                                spec = RPCSVC_AUTH_REJECT; +                                } else +                                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" +                                                "d to read auth val"); +                        } else +                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" +                                        "d to read auth val"); +                } + +                GF_FREE (srchstr); +                final = rpcsvc_combine_gen_spec_volume_checks (gen, spec); +                if (final == RPCSVC_AUTH_ACCEPT) { +                        autharr[count] = auth->auth->authnum; +                        ++count; +                } +        } + +err: +        return count; +}  gid_t *  rpcsvc_auth_unix_auxgids (rpcsvc_request_t *req, int *arrlen) diff --git a/rpc/rpc-lib/src/rpcsvc-common.h b/rpc/rpc-lib/src/rpcsvc-common.h index 442049433a7..233dac53c27 100644 --- a/rpc/rpc-lib/src/rpcsvc-common.h +++ b/rpc/rpc-lib/src/rpcsvc-common.h @@ -60,7 +60,7 @@ typedef struct rpcsvc_state {          /* Allow insecure ports. */          int                     allow_insecure; - +        gf_boolean_t            register_portmap;          glusterfs_ctx_t         *ctx;          /* list of connections which will listen for incoming connections */ diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c index 519d4e3466a..10198b0f35e 100644 --- a/rpc/rpc-lib/src/rpcsvc.c +++ b/rpc/rpc-lib/src/rpcsvc.c @@ -105,8 +105,33 @@ out:          return;  } +rpcsvc_vector_sizer +rpcsvc_get_program_vector_sizer (rpcsvc_t *svc, uint32_t prognum, +                                 uint32_t progver, uint32_t procnum) +{ +        rpcsvc_program_t        *program = NULL; +        char                    found    = 0; +        if (!svc) +                return NULL; +        pthread_mutex_lock (&svc->rpclock); +        { +                list_for_each_entry (program, &svc->programs, program) { +                        if ((program->prognum == prognum) +                            && (program->progver == progver)) { +                                found = 1; +                                break; +                        } +                } +        } +        pthread_mutex_unlock (&svc->rpclock); + +        if (found) +                return program->actors[procnum].vector_sizer; +        else +                return NULL; +}  /* This needs to change to returning errors, since   * we need to return RPC specific error messages when some @@ -442,8 +467,10 @@ rpcsvc_handle_rpc_call (rpcsvc_t *svc, rpc_transport_t *trans,                  gf_log ("rpcsvc", GF_LOG_TRACE, "Client port: %d", (int)port); -                if ((port > 1024) && (0 == svc->allow_insecure)) {  //Non-privileged user, fail request -                        gf_log ("glusterd", GF_LOG_ERROR, "Request received from non-" +                if ((port > 1024) && (0 == svc->allow_insecure)) { +                        /* Non-privileged user, fail request */ +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "Request received from non-"                                  "privileged port. Failing request");                          return -1;                  } @@ -505,10 +532,10 @@ rpcsvc_handle_disconnect (rpcsvc_t *svc, rpc_transport_t *trans)          rpcsvc_notify_wrapper_t *wrappers = NULL, *wrapper;          int32_t                  ret      = -1, i = 0, wrapper_count = 0;          rpcsvc_listener_t       *listener = NULL; -  +          event = (trans->listener == NULL) ? RPCSVC_EVENT_LISTENER_DEAD                  : RPCSVC_EVENT_DISCONNECT; -  +          pthread_mutex_lock (&svc->rpclock);          {                  wrappers = GF_CALLOC (svc->notify_count, sizeof (*wrapper), @@ -516,35 +543,35 @@ rpcsvc_handle_disconnect (rpcsvc_t *svc, rpc_transport_t *trans)                  if (!wrappers) {                          goto unlock;                  } -  +                  list_for_each_entry (wrapper, &svc->notify, list) {                          if (wrapper->notify) {                                  wrappers[i++] = *wrapper;                          }                  } -  +                  wrapper_count = i;          }  unlock:          pthread_mutex_unlock (&svc->rpclock); -  +          if (wrappers) {                  for (i = 0; i < wrapper_count; i++) {                          wrappers[i].notify (svc, wrappers[i].data,                                              event, trans);                  } -  +                  GF_FREE (wrappers);          } -  +          if (event == RPCSVC_EVENT_LISTENER_DEAD) {                  listener = rpcsvc_get_listener (svc, -1, trans->listener);                  rpcsvc_listener_destroy (listener);          } -  +          return ret;  } -  +  int  rpcsvc_notify (rpc_transport_t *trans, void *mydata, @@ -1114,6 +1141,11 @@ out:          return ret;  } +int +rpcsvc_register_portmap_enabled (rpcsvc_t *svc) +{ +        return svc->register_portmap; +}  int32_t  rpcsvc_get_listener_port (rpcsvc_listener_t *listener) @@ -1152,7 +1184,7 @@ rpcsvc_get_listener (rpcsvc_t *svc, uint16_t port, rpc_transport_t *trans)  {          rpcsvc_listener_t  *listener      = NULL;          char                found         = 0; -        uint32_t            listener_port = 0;  +        uint32_t            listener_port = 0;          if (!svc) {                  goto out; @@ -1343,7 +1375,7 @@ rpcsvc_create_listener (rpcsvc_t *svc, dict_t *options, char *name)  {          rpc_transport_t   *trans    = NULL;          rpcsvc_listener_t *listener = NULL; -        int32_t            ret      = -1;  +        int32_t            ret      = -1;          if (!svc || !options) {                  goto out; @@ -1577,7 +1609,6 @@ out:          return ret;  } -  static void  free_prog_details (gf_dump_rsp *rsp)  { @@ -1670,8 +1701,39 @@ fail:  int  rpcsvc_init_options (rpcsvc_t *svc, dict_t *options)  { +        char            *optstr = NULL; +        int             ret = -1; + +        if ((!svc) || (!options)) +                return -1; +          svc->memfactor = RPCSVC_DEFAULT_MEMFACTOR; -        return 0; + +        svc->register_portmap = _gf_true; +        if (dict_get (options, "rpc.register-with-portmap")) { +                ret = dict_get_str (options, "rpc.register-with-portmap", +                                    &optstr); +                if (ret < 0) { +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to parse " +                                "dict"); +                        goto out; +                } + +                ret = gf_string2boolean (optstr, &svc->register_portmap); +                if (ret < 0) { +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to parse bool " +                                "string"); +                        goto out; +                } +        } + +        if (!svc->register_portmap) +                gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Portmap registration " +                        "disabled"); + +        ret = 0; +out: +        return ret;  }  int @@ -1789,6 +1851,531 @@ free_svc:  } +int +rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, char *clstr) +{ +        int                     ret = -1; +        char                    *addrtok = NULL; +        char                    *addrstr = NULL; +        char                    *svptr = NULL; + +        if ((!options) || (!clstr)) +                return -1; + +        if (!dict_get (options, pattern)) +                return -1; + +        ret = dict_get_str (options, pattern, &addrstr); +        if (ret < 0) { +                ret = -1; +                goto err; +        } + +        if (!addrstr) { +                ret = -1; +                goto err; +        } + +        addrtok = strtok_r (addrstr, ",", &svptr); +        while (addrtok) { + +                /* CASEFOLD not present on Solaris */ +#ifdef FNM_CASEFOLD +                ret = fnmatch (addrtok, clstr, FNM_CASEFOLD); +#else +                ret = fnmatch (addrtok, clstr, 0); +#endif +                if (ret == 0) +                        goto err; + +                addrtok = strtok_r (NULL, ",", &svptr); +        } + +        ret = -1; +err: + +        return ret; +} + + +int +rpcsvc_transport_peer_check_allow (dict_t *options, char *volname, char *clstr) +{ +        int     ret = RPCSVC_AUTH_DONTCARE; +        char    *srchstr = NULL; +        char    globalrule[] = "rpc-auth.addr.allow"; + +        if ((!options) || (!clstr)) +                return ret; + +        /* If volname is NULL, then we're searching for the general rule to +         * determine the current address in clstr is allowed or not for all +         * subvolumes. +         */ +        if (volname) { +                ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.allow", volname); +                if (ret == -1) { +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); +                        ret = RPCSVC_AUTH_DONTCARE; +                        goto out; +                } +        } else +                srchstr = globalrule; + +        ret = rpcsvc_transport_peer_check_search (options, srchstr, clstr); +        if (volname) +                GF_FREE (srchstr); + +        if (ret == 0) +                ret = RPCSVC_AUTH_ACCEPT; +        else +                ret = RPCSVC_AUTH_DONTCARE; +out: +        return ret; +} + +int +rpcsvc_transport_peer_check_reject (dict_t *options, char *volname, char *clstr) +{ +        int     ret = RPCSVC_AUTH_DONTCARE; +        char    *srchstr = NULL; +        char    generalrule[] = "rpc-auth.addr.reject"; + +        if ((!options) || (!clstr)) +                return ret; + +        if (volname) { +                ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.reject", +                                   volname); +                if (ret == -1) { +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); +                        ret = RPCSVC_AUTH_REJECT; +                        goto out; +                } +        } else +                srchstr = generalrule; + +        ret = rpcsvc_transport_peer_check_search (options, srchstr, clstr); +        if (volname) +                GF_FREE (srchstr); + +        if (ret == 0) +                ret = RPCSVC_AUTH_REJECT; +        else +                ret = RPCSVC_AUTH_DONTCARE; +out: +        return ret; +} + + +/* This function tests the results of the allow rule and the reject rule to + * combine them into a single result that can be used to determine if the + * connection should be allowed to proceed. + * Heres the test matrix we need to follow in this function. + * + * A -  Allow, the result of the allow test. Never returns R. + * R - Reject, result of the reject test. Never returns A. + * Both can return D or dont care if no rule was given. + * + * | @allow | @reject | Result | + * |    A   |   R     | R      | + * |    D   |   D     | D      | + * |    A   |   D     | A      | + * |    D   |   R     | R      | + */ +int +rpcsvc_combine_allow_reject_volume_check (int allow, int reject) +{ +        int     final = RPCSVC_AUTH_REJECT; + +        /* If allowed rule allows but reject rule rejects, we stay cautious +         * and reject. */ +        if ((allow == RPCSVC_AUTH_ACCEPT) && (reject == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; +        /* if both are dont care, that is user did not specify for either allow +         * or reject, we leave it up to the general rule to apply, in the hope +         * that there is one. +         */ +        else if ((allow == RPCSVC_AUTH_DONTCARE) && +                 (reject == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_DONTCARE; +        /* If one is dont care, the other one applies. */ +        else if ((allow == RPCSVC_AUTH_ACCEPT) && +                 (reject == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((allow == RPCSVC_AUTH_DONTCARE) && +                 (reject == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; + +        return final; +} + + +/* Combines the result of the general rule test against, the specific rule + * to determine final permission for the client's address. + * + * | @gen   | @spec   | Result | + * |    A   |   A     | A      | + * |    A   |   R     | R      | + * |    A   |   D     | A      | + * |    D   |   A     | A      | + * |    D   |   R     | R      | + * |    D   |   D     | D      | + * |    R   |   A     | A      | + * |    R   |   D     | R      | + * |    R   |   R     | R      | + */ +int +rpcsvc_combine_gen_spec_addr_checks (int gen, int spec) +{ +        int     final = RPCSVC_AUTH_REJECT; + +        if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec== RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_DONTCARE; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; + +        return final; +} + + + +/* Combines the result of the general rule test against, the specific rule + * to determine final test for the connection coming in for a given volume. + * + * | @gen   | @spec   | Result | + * |    A   |   A     | A      | + * |    A   |   R     | R      | + * |    A   |   D     | A      | + * |    D   |   A     | A      | + * |    D   |   R     | R      | + * |    D   |   D     | R      |, special case, we intentionally disallow this. + * |    R   |   A     | A      | + * |    R   |   D     | R      | + * |    R   |   R     | R      | + */ +int +rpcsvc_combine_gen_spec_volume_checks (int gen, int spec) +{ +        int     final = RPCSVC_AUTH_REJECT; + +        if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; +        /* On no rule, we reject. */ +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec== RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; + +        return final; +} + + +int +rpcsvc_transport_peer_check_name (dict_t *options, char *volname, +                                  rpc_transport_t *trans) +{ +        int     ret = RPCSVC_AUTH_REJECT; +        int     aret = RPCSVC_AUTH_REJECT; +        int     rjret = RPCSVC_AUTH_REJECT; +        char    clstr[RPCSVC_PEER_STRLEN]; + +        if (!trans) +                return ret; + +        ret = rpcsvc_transport_peername (trans, clstr, RPCSVC_PEER_STRLEN); +        if (ret != 0) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get remote addr: " +                        "%s", gai_strerror (ret)); +                ret = RPCSVC_AUTH_REJECT; +                goto err; +        } + +        aret = rpcsvc_transport_peer_check_allow (options, volname, clstr); +        rjret = rpcsvc_transport_peer_check_reject (options, volname, clstr); + +        ret = rpcsvc_combine_allow_reject_volume_check (aret, rjret); + +err: +        return ret; +} + + +int +rpcsvc_transport_peer_check_addr (dict_t *options, char *volname, +                                  rpc_transport_t *trans) +{ +        int     ret = RPCSVC_AUTH_REJECT; +        int     aret = RPCSVC_AUTH_DONTCARE; +        int     rjret = RPCSVC_AUTH_REJECT; +        char    clstr[RPCSVC_PEER_STRLEN]; +        struct sockaddr_storage sastorage = {0,}; + +        if (!trans) +                return ret; + +        ret = rpcsvc_transport_peeraddr (trans, clstr, RPCSVC_PEER_STRLEN, +                                         &sastorage, sizeof (sastorage)); +        if (ret != 0) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get remote addr: " +                        "%s", gai_strerror (ret)); +                ret = RPCSVC_AUTH_REJECT; +                goto err; +        } + +        aret = rpcsvc_transport_peer_check_allow (options, volname, clstr); +        rjret = rpcsvc_transport_peer_check_reject (options, volname, clstr); + +        ret = rpcsvc_combine_allow_reject_volume_check (aret, rjret); +err: +        return ret; +} + + +int +rpcsvc_transport_check_volume_specific (dict_t *options, char *volname, +                                        rpc_transport_t *trans) +{ +        int             namechk = RPCSVC_AUTH_REJECT; +        int             addrchk = RPCSVC_AUTH_REJECT; +        gf_boolean_t    namelookup = _gf_true; +        char            *namestr = NULL; +        int             ret = 0; + +        if ((!options) || (!volname) || (!trans)) +                return RPCSVC_AUTH_REJECT; + +        /* Enabled by default */ +        if ((dict_get (options, "rpc-auth.addr.namelookup"))) { +                ret = dict_get_str (options, "rpc-auth.addr.namelookup" +                                    , &namestr); +                if (ret == 0) +                        ret = gf_string2boolean (namestr, &namelookup); +        } + +        /* We need two separate checks because the rules with addresses in them +         * can be network addresses which can be general and names can be +         * specific which will over-ride the network address rules. +         */ +        if (namelookup) +                namechk = rpcsvc_transport_peer_check_name (options, volname, +                                                            trans); +        addrchk = rpcsvc_transport_peer_check_addr (options, volname, trans); + +        if (namelookup) +                ret = rpcsvc_combine_gen_spec_addr_checks (addrchk, +                                                               namechk); +        else +                ret = addrchk; + +        return ret; +} + + +int +rpcsvc_transport_check_volume_general (dict_t *options, rpc_transport_t *trans) +{ +        int             addrchk = RPCSVC_AUTH_REJECT; +        int             namechk = RPCSVC_AUTH_REJECT; +        gf_boolean_t    namelookup = _gf_true; +        char            *namestr = NULL; +        int             ret = 0; + +        if ((!options) || (!trans)) +                return RPCSVC_AUTH_REJECT; + +        /* Enabled by default */ +        if ((dict_get (options, "rpc-auth.addr.namelookup"))) { +                ret = dict_get_str (options, "rpc-auth.addr.namelookup" +                                    , &namestr); +                if (ret == 0) +                        ret = gf_string2boolean (namestr, &namelookup); +        } + +        /* We need two separate checks because the rules with addresses in them +         * can be network addresses which can be general and names can be +         * specific which will over-ride the network address rules. +         */ +        if (namelookup) +                namechk = rpcsvc_transport_peer_check_name (options, NULL, trans); +        addrchk = rpcsvc_transport_peer_check_addr (options, NULL, trans); + +        if (namelookup) +                ret = rpcsvc_combine_gen_spec_addr_checks (addrchk, +                                                               namechk); +        else +                ret = addrchk; + +        return ret; +} + +int +rpcsvc_transport_peer_check (dict_t *options, char *volname, +                             rpc_transport_t *trans) +{ +        int     general_chk = RPCSVC_AUTH_REJECT; +        int     specific_chk = RPCSVC_AUTH_REJECT; + +        if ((!options) || (!volname) || (!trans)) +                return RPCSVC_AUTH_REJECT; + +        general_chk = rpcsvc_transport_check_volume_general (options, trans); +        specific_chk = rpcsvc_transport_check_volume_specific (options, volname, +                                                               trans); + +        return rpcsvc_combine_gen_spec_volume_checks (general_chk, +                                                      specific_chk); +} + + +int +rpcsvc_transport_privport_check (rpcsvc_t *svc, char *volname, +                                 rpc_transport_t *trans) +{ +        struct sockaddr_storage sastorage = {0,}; +        struct sockaddr_in     *sa = NULL; +        int                     ret = RPCSVC_AUTH_REJECT; +        socklen_t               sasize = sizeof (sa); +        char                    *srchstr = NULL; +        char                    *valstr = NULL; +        int                     globalinsecure = RPCSVC_AUTH_REJECT; +        int                     exportinsecure = RPCSVC_AUTH_DONTCARE; +        uint16_t                port = 0; +        gf_boolean_t            insecure = _gf_false; + +        if ((!svc) || (!volname) || (!trans)) +                return ret; + +        sa = (struct sockaddr_in*) &sastorage; +        ret = rpcsvc_transport_peeraddr (trans, NULL, 0, &sastorage, +                                         sasize); +        if (ret != 0) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get peer addr: %s", +                        gai_strerror (ret)); +                ret = RPCSVC_AUTH_REJECT; +                goto err; +        } + +        port = ntohs (sa->sin_port); +        gf_log (GF_RPCSVC, GF_LOG_TRACE, "Client port: %d", (int)port); +        /* If the port is already a privileged one, dont bother with checking +         * options. +         */ +        if (port <= 1024) { +                ret = RPCSVC_AUTH_ACCEPT; +                goto err; +        } + +        /* Disabled by default */ +        if ((dict_get (svc->options, "rpc-auth.ports.insecure"))) { +                ret = dict_get_str (svc->options, "rpc-auth.ports.insecure" +                                    , &srchstr); +                if (ret == 0) { +                        ret = gf_string2boolean (srchstr, &insecure); +                        if (ret == 0) { +                                if (insecure == _gf_true) +                                        globalinsecure = RPCSVC_AUTH_ACCEPT; +                        } else +                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" +                                        " read rpc-auth.ports.insecure value"); +                } else +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" +                                " read rpc-auth.ports.insecure value"); +        } + +        /* Disabled by default */ +        ret = gf_asprintf (&srchstr, "rpc-auth.ports.%s.insecure", volname); +        if (ret == -1) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); +                ret = RPCSVC_AUTH_REJECT; +                goto err; +        } + +        if (dict_get (svc->options, srchstr)) { +                ret = dict_get_str (svc->options, srchstr, &valstr); +                if (ret == 0) { +                        ret = gf_string2boolean (srchstr, &insecure); +                        if (ret == 0) { +                                if (insecure == _gf_true) +                                       exportinsecure = RPCSVC_AUTH_ACCEPT; +                                else +                                        exportinsecure = RPCSVC_AUTH_REJECT; +                        } else +                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" +                                        " read rpc-auth.ports.insecure value"); +                } else +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" +                                " read rpc-auth.ports.insecure value"); +        } + +        ret = rpcsvc_combine_gen_spec_volume_checks (globalinsecure, +                                                         exportinsecure); +        if (ret == RPCSVC_AUTH_ACCEPT) +                gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Unprivileged port allowed"); +        else +                gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Unprivileged port not" +                        " allowed"); + +err: +        return ret; +} + + +char * +rpcsvc_volume_allowed (dict_t *options, char *volname) +{ +        char    globalrule[] = "rpc-auth.addr.allow"; +        char    *srchstr = NULL; +        char    *addrstr = NULL; +        int     ret = -1; + +        if ((!options) || (!volname)) +                return NULL; + +        ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.allow", volname); +        if (ret == -1) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); +                goto out; +        } + +        if (!dict_get (options, srchstr)) { +                GF_FREE (srchstr); +                srchstr = globalrule; +                ret = dict_get_str (options, srchstr, &addrstr); +        } else +                ret = dict_get_str (options, srchstr, &addrstr); + +out: +        return addrstr; +} + +  rpcsvc_actor_t gluster_dump_actors[] = {          [GF_DUMP_NULL] = {"NULL", GF_DUMP_NULL, NULL, NULL, NULL },          [GF_DUMP_DUMP] = {"DUMP", GF_DUMP_DUMP, rpcsvc_dump, NULL, NULL }, diff --git a/rpc/rpc-lib/src/rpcsvc.h b/rpc/rpc-lib/src/rpcsvc.h index 17da800fa9c..7ef6e580c22 100644 --- a/rpc/rpc-lib/src/rpcsvc.h +++ b/rpc/rpc-lib/src/rpcsvc.h @@ -249,7 +249,8 @@ struct rpcsvc_request {  };  #define rpcsvc_request_program(req) ((rpcsvc_program_t *)((req)->prog)) -#define rpcsvc_request_program_private(req) (((rpcsvc_program_t *)((req)->program))->private) +#define rpcsvc_request_procnum(req) (((req)->procnum)) +#define rpcsvc_request_program_private(req) (((rpcsvc_program_t *)((req)->prog))->private)  #define rpcsvc_request_accepted(req)    ((req)->rpc_status == MSG_ACCEPTED)  #define rpcsvc_request_accepted_success(req) ((req)->rpc_err == SUCCESS)  #define rpcsvc_request_uid(req)         ((req)->uid) @@ -257,18 +258,24 @@ struct rpcsvc_request {  #define rpcsvc_request_prog_minauth(req) (rpcsvc_request_program(req)->min_auth)  #define rpcsvc_request_cred_flavour(req) (rpcsvc_auth_flavour(req->cred))  #define rpcsvc_request_verf_flavour(req) (rpcsvc_auth_flavour(req->verf)) - +#define rpcsvc_request_service(req)      ((req)->svc)  #define rpcsvc_request_uid(req)         ((req)->uid)  #define rpcsvc_request_gid(req)         ((req)->gid)  #define rpcsvc_request_private(req)     ((req)->private)  #define rpcsvc_request_xid(req)         ((req)->xid)  #define rpcsvc_request_set_private(req,prv)  (req)->private = (void *)(prv) +#define rpcsvc_request_iobref_ref(req)  (iobref_ref ((req)->iobref))  #define rpcsvc_request_record_ref(req)  (iobuf_ref ((req)->recordiob))  #define rpcsvc_request_record_unref(req) (iobuf_unref ((req)->recordiob)) +#define rpcsvc_request_record_iob(req)   ((req)->recordiob) +#define rpcsvc_request_set_vecstate(req, state)  ((req)->vecstate = state) +#define rpcsvc_request_vecstate(req) ((req)->vecstate) +#define rpcsvc_request_transport(req) ((req)->trans)  #define RPCSVC_ACTOR_SUCCESS    0  #define RPCSVC_ACTOR_ERROR      (-1) +#define RPCSVC_ACTOR_IGNORE     (-2)  /* Functor for every type of protocol actor   * must be defined like this. @@ -285,8 +292,7 @@ struct rpcsvc_request {  typedef int (*rpcsvc_actor) (rpcsvc_request_t *req);  typedef int (*rpcsvc_vector_actor) (rpcsvc_request_t *req, struct iovec *vec,                                      int count, struct iobref *iobref); -typedef int (*rpcsvc_vector_sizer) (rpcsvc_request_t *req, ssize_t *readsize, -                                    int *newiob); +typedef int (*rpcsvc_vector_sizer) (int state, ssize_t *readsize, char *addr);  /* Every protocol actor will also need to specify the function the RPC layer   * will use to serialize or encode the message into XDR format just before @@ -410,6 +416,9 @@ rpcsvc_listener_destroy (rpcsvc_listener_t *listener);  extern int  rpcsvc_program_register_portmap (rpcsvc_program_t *newprog, uint32_t port); +extern int +rpcsvc_register_portmap_enabled (rpcsvc_t *svc); +  /* Inits the global RPC service data structures.   * Called in main.   */ @@ -542,4 +551,12 @@ int  rpcsvc_transport_unix_options_build (dict_t **options, char *filepath);  int  rpcsvc_set_allow_insecure (rpcsvc_t *svc, dict_t *options); +int +rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen); +char * +rpcsvc_volume_allowed (dict_t *options, char *volname); +rpcsvc_vector_sizer +rpcsvc_get_program_vector_sizer (rpcsvc_t *svc, uint32_t prognum, +                                 uint32_t progver, uint32_t procnum); +  #endif diff --git a/rpc/rpc-lib/src/xdr-common.h b/rpc/rpc-lib/src/xdr-common.h index c69bfa834fb..0014e46ac1a 100644 --- a/rpc/rpc-lib/src/xdr-common.h +++ b/rpc/rpc-lib/src/xdr-common.h @@ -113,8 +113,6 @@ xdr_from_dump_req (struct iovec outmsg, void *rsp);  ssize_t  xdr_to_dump_rsp (struct iovec inmsg, void *args); -#define XDR_BYTES_PER_UNIT      4 -  /* Returns the address of the byte that follows the   * last byte used for decoding the previous xdr component.   * For eg, once the RPC call for NFS has been decoded, thie macro will return  | 
