/** * @brief Validate export permissions * * @param[in] req Incoming request. * * @return NFS4_OK if successful, NFS4ERR_ACCESS or NFS4ERR_WRONGSEC otherwise. * */ nfsstat4 nfs4_export_check_access(struct svc_req *req) { xprt_type_t xprt_type = svc_get_xprt_type(req->rq_xprt); int port = get_port(op_ctx->caller_addr); LogMidDebugAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT, "nfs4_export_check_access about to call export_check_access"); export_check_access(); /* Check if any access at all */ if ((op_ctx->export_perms->options & EXPORT_OPTION_ACCESS_TYPE) == 0) { LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT, "Access not allowed on Export_Id %d %s for client %s", op_ctx->export->export_id, op_ctx->export->fullpath, op_ctx->client ? op_ctx->client->hostaddr_str : "unknown client"); return NFS4ERR_ACCESS; }
/** * @brief Validate export permissions * * @param[in] req Incoming request. * * @return NFS4_OK if successful, NFS4ERR_ACCESS or NFS4ERR_WRONGSEC otherwise. * */ nfsstat4 nfs4_export_check_access(struct svc_req *req) { xprt_type_t xprt_type = svc_get_xprt_type(req->rq_xprt); int port = get_port(op_ctx->caller_addr); LogMidDebugAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT, "nfs4_export_check_access about to call export_check_access"); export_check_access(); /* Check if any access at all */ if ((op_ctx->export_perms->options & EXPORT_OPTION_ACCESS_MASK) == 0) { LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT, "Access not allowed on Export_Id %d %s for client %s", op_ctx->ctx_export->export_id, op_ctx->ctx_export->fullpath, op_ctx->client ? op_ctx->client->hostaddr_str : "unknown client"); return NFS4ERR_ACCESS; } /* Check protocol version */ if ((op_ctx->export_perms->options & EXPORT_OPTION_NFSV4) == 0) { LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT, "NFS4 not allowed on Export_Id %d %s for client %s", op_ctx->ctx_export->export_id, op_ctx->ctx_export->fullpath, op_ctx->client ? op_ctx->client->hostaddr_str : "unknown client"); return NFS4ERR_ACCESS; } /* Check transport type */ if (((xprt_type == XPRT_UDP) && ((op_ctx->export_perms->options & EXPORT_OPTION_UDP) == 0)) || ((xprt_type == XPRT_TCP) && ((op_ctx->export_perms->options & EXPORT_OPTION_TCP) == 0))) { LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT, "NFS4 over %s not allowed on Export_Id %d %s for client %s", xprt_type_to_str(xprt_type), op_ctx->ctx_export->export_id, op_ctx->ctx_export->fullpath, op_ctx->client ? op_ctx->client->hostaddr_str : "unknown client"); return NFS4ERR_ACCESS; } /* Check if client is using a privileged port. */ if (((op_ctx->export_perms->options & EXPORT_OPTION_PRIVILEGED_PORT) != 0) && (port >= IPPORT_RESERVED)) { LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT, "Non-reserved Port %d is not allowed on Export_Id %d %s for client %s", port, op_ctx->ctx_export->export_id, op_ctx->ctx_export->fullpath, op_ctx->client ? op_ctx->client->hostaddr_str : "unknown client"); return NFS4ERR_ACCESS; } /* Test if export allows the authentication provided */ if (export_check_security(req) == false) { LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT, "NFS4 auth not allowed on Export_Id %d %s for client %s", op_ctx->ctx_export->export_id, op_ctx->ctx_export->fullpath, op_ctx->client ? op_ctx->client->hostaddr_str : "unknown client"); return NFS4ERR_WRONGSEC; } /* Get creds */ return nfs_req_creds(req); }
state_nlm_client_t *get_nlm_client(care_t care, SVCXPRT * xprt, state_nsm_client_t * pnsm_client, char * caller_name) { state_nlm_client_t key; state_nlm_client_t * pclient; char str[HASHTABLE_DISPLAY_STRLEN]; struct hash_latch latch; hash_error_t rc; hash_buffer_t buffkey; hash_buffer_t buffval; if(caller_name == NULL) return NULL; memset(&key, 0, sizeof(key)); key.slc_nsm_client = pnsm_client; key.slc_nlm_caller_name_len = strlen(caller_name); key.slc_client_type = svc_get_xprt_type(xprt); if(key.slc_nlm_caller_name_len > LM_MAXSTRLEN) return NULL; key.slc_nlm_caller_name = caller_name; if(isFullDebug(COMPONENT_STATE)) { display_nlm_client(&key, str); LogFullDebug(COMPONENT_STATE, "Find {%s}", str); } buffkey.pdata = &key; buffkey.len = sizeof(key); rc = HashTable_GetLatch(ht_nlm_client, &buffkey, &buffval, TRUE, &latch); /* If we found it, return it */ if(rc == HASHTABLE_SUCCESS) { pclient = buffval.pdata; /* Return the found NLM Client */ if(isFullDebug(COMPONENT_STATE)) { display_nlm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "Found {%s}", str); } /* Increment refcount under hash latch. * This prevents dec ref from removing this entry from hash if a race * occurs. */ inc_nlm_client_ref(pclient); HashTable_ReleaseLatched(ht_nlm_client, &latch); if(care == CARE_MONITOR && !nsm_monitor(pnsm_client)) { dec_nlm_client_ref(pclient); pclient = NULL; } return pclient; } /* An error occurred, return NULL */ if(rc != HASHTABLE_ERROR_NO_SUCH_KEY) { display_nlm_client(&key, str); LogCrit(COMPONENT_STATE, "Error %s, could not find {%s}", hash_table_err_to_str(rc), str); return NULL; } /* Not found, but we don't care, return NULL */ if(care == CARE_NOT) { /* Return the found NLM Client */ if(isFullDebug(COMPONENT_STATE)) { display_nlm_client(&key, str); LogFullDebug(COMPONENT_STATE, "Ignoring {%s}", str); } HashTable_ReleaseLatched(ht_nlm_client, &latch); return NULL; } pclient = gsh_malloc(sizeof(*pclient)); if(pclient == NULL) { display_nlm_client(&key, str); LogCrit(COMPONENT_STATE, "No memory for {%s}", str); return NULL; } /* Copy everything over */ memcpy(pclient, &key, sizeof(key)); pclient->slc_nlm_caller_name = gsh_strdup(key.slc_nlm_caller_name); /* Take a reference to the NSM Client */ inc_nsm_client_ref(pnsm_client); if(pclient->slc_nlm_caller_name == NULL) { /* Discard the created client */ free_nlm_client(pclient); return NULL; } pclient->slc_refcount = 1; if(isFullDebug(COMPONENT_STATE)) { display_nlm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "New {%s}", str); } buffkey.pdata = pclient; buffkey.len = sizeof(*pclient); buffval.pdata = pclient; buffval.len = sizeof(*pclient); rc = HashTable_SetLatched(ht_nlm_client, &buffval, &buffval, &latch, FALSE, NULL, NULL); /* An error occurred, return NULL */ if(rc != HASHTABLE_SUCCESS) { display_nlm_client(pclient, str); LogCrit(COMPONENT_STATE, "Error %s, inserting {%s}", hash_table_err_to_str(rc), str); free_nlm_client(pclient); return NULL; } if(care != CARE_MONITOR || nsm_monitor(pnsm_client)) return pclient; /* Failed to monitor, release client reference * and almost certainly remove it from the hash table. */ dec_nlm_client_ref(pclient); return NULL; }
/** * @brief Get an NLM client * * @param[in] care Care status * @param[in] xprt RPC transport * @param[in] nsm_client Related NSM client * @param[in] caller_name Caller name * * @return NLM client or NULL. */ state_nlm_client_t *get_nlm_client(care_t care, SVCXPRT *xprt, state_nsm_client_t *nsm_client, char *caller_name) { state_nlm_client_t key; state_nlm_client_t *pclient; char str[LOG_BUFF_LEN]; struct display_buffer dspbuf = {sizeof(str), str, str}; struct hash_latch latch; hash_error_t rc; struct gsh_buffdesc buffkey; struct gsh_buffdesc buffval; struct sockaddr_storage local_addr; socklen_t addr_len; if (caller_name == NULL) return NULL; memset(&key, 0, sizeof(key)); key.slc_nsm_client = nsm_client; key.slc_nlm_caller_name_len = strlen(caller_name); key.slc_client_type = svc_get_xprt_type(xprt); addr_len = sizeof(local_addr); if (getsockname(xprt->xp_fd, (struct sockaddr *)&local_addr, &addr_len) == -1) { LogEvent(COMPONENT_CLIENTID, "Failed to get local addr."); } else { memcpy(&(key.slc_server_addr), &local_addr, sizeof(struct sockaddr_storage)); } if (key.slc_nlm_caller_name_len > LM_MAXSTRLEN) return NULL; key.slc_nlm_caller_name = caller_name; if (isFullDebug(COMPONENT_STATE)) { display_nlm_client(&dspbuf, &key); LogFullDebug(COMPONENT_STATE, "Find {%s}", str); } buffkey.addr = &key; buffkey.len = sizeof(key); rc = hashtable_getlatch(ht_nlm_client, &buffkey, &buffval, true, &latch); /* If we found it, return it */ if (rc == HASHTABLE_SUCCESS) { pclient = buffval.addr; /* Return the found NLM Client */ if (isFullDebug(COMPONENT_STATE)) { display_nlm_client(&dspbuf, pclient); LogFullDebug(COMPONENT_STATE, "Found {%s}", str); } /* Increment refcount under hash latch. * This prevents dec ref from removing this entry from hash * if a race occurs. */ inc_nlm_client_ref(pclient); hashtable_releaselatched(ht_nlm_client, &latch); if (care == CARE_MONITOR && !nsm_monitor(nsm_client)) { dec_nlm_client_ref(pclient); pclient = NULL; } return pclient; } /* An error occurred, return NULL */ if (rc != HASHTABLE_ERROR_NO_SUCH_KEY) { display_nlm_client(&dspbuf, &key); LogCrit(COMPONENT_STATE, "Error %s, could not find {%s}", hash_table_err_to_str(rc), str); return NULL; } /* Not found, but we don't care, return NULL */ if (care == CARE_NOT) { /* Return the found NLM Client */ if (isFullDebug(COMPONENT_STATE)) { display_nlm_client(&dspbuf, &key); LogFullDebug(COMPONENT_STATE, "Ignoring {%s}", str); } hashtable_releaselatched(ht_nlm_client, &latch); return NULL; } pclient = gsh_malloc(sizeof(*pclient)); if (pclient == NULL) { display_nlm_client(&dspbuf, &key); LogCrit(COMPONENT_STATE, "No memory for {%s}", str); return NULL; } /* Copy everything over */ memcpy(pclient, &key, sizeof(key)); pclient->slc_nlm_caller_name = gsh_strdup(key.slc_nlm_caller_name); /* Take a reference to the NSM Client */ inc_nsm_client_ref(nsm_client); if (pclient->slc_nlm_caller_name == NULL) { /* Discard the created client */ free_nlm_client(pclient); return NULL; } pclient->slc_refcount = 1; if (isFullDebug(COMPONENT_STATE)) { display_nlm_client(&dspbuf, pclient); LogFullDebug(COMPONENT_STATE, "New {%s}", str); } buffkey.addr = pclient; buffkey.len = sizeof(*pclient); buffval.addr = pclient; buffval.len = sizeof(*pclient); rc = hashtable_setlatched(ht_nlm_client, &buffval, &buffval, &latch, false, NULL, NULL); /* An error occurred, return NULL */ if (rc != HASHTABLE_SUCCESS) { display_nlm_client(&dspbuf, pclient); LogCrit(COMPONENT_STATE, "Error %s, inserting {%s}", hash_table_err_to_str(rc), str); free_nlm_client(pclient); return NULL; } if (care != CARE_MONITOR || nsm_monitor(nsm_client)) return pclient; /* Failed to monitor, release client reference * and almost certainly remove it from the hash table. */ dec_nlm_client_ref(pclient); return NULL; }