Пример #1
0
/**
 * @brief Get numeric credentials from request
 *
 * @todo This MUST be refactored to not use TI-RPC private structures.
 * Instead, export appropriate functions from lib(n)tirpc.
 *
 * fills out creds in op_ctx
 *
 * @param[in]  req              Incoming request.
 *
 * @return NFS4_OK if successful, NFS4ERR_ACCESS otherwise.
 *
 */
nfsstat4 nfs_req_creds(struct svc_req *req)
{
	unsigned int i;
	const char *auth_label = "UNKNOWN";
	gid_t **garray_copy = &op_ctx->caller_garray_copy;
#ifdef _HAVE_GSSAPI
	struct svc_rpc_gss_data *gd = NULL;
	char principal[MAXNAMLEN + 1];
#endif

	/* Make sure we clear out all the cred_flags except CREDS_LOADED and
	 * CREDS_ANON.
	 */
	op_ctx->cred_flags &= CREDS_LOADED | CREDS_ANON;

	switch (req->rq_cred.oa_flavor) {
	case AUTH_NONE:
		/* Nothing to be done here... */
		op_ctx->cred_flags |= CREDS_LOADED | CREDS_ANON;
		auth_label = "AUTH_NONE";
		break;

	case AUTH_SYS:
		if ((op_ctx->cred_flags & CREDS_LOADED) == 0) {
			struct authunix_parms *creds = NULL;

			/* We map the rq_cred to Authunix_parms */
			creds = (struct authunix_parms *) req->rq_clntcred;
			op_ctx->original_creds.caller_uid = creds->aup_uid;
			op_ctx->original_creds.caller_gid = creds->aup_gid;
			op_ctx->original_creds.caller_glen = creds->aup_len;
			op_ctx->original_creds.caller_garray = creds->aup_gids;
			op_ctx->cred_flags |= CREDS_LOADED;
		}

		/* Copy original_creds creds */
		*op_ctx->creds = op_ctx->original_creds;

		/* Do we trust AUTH_SYS creds for groups or not ? */
		if ((op_ctx->export_perms->options & EXPORT_OPTION_MANAGE_GIDS)
		    != 0) {
			op_ctx->cred_flags |= MANAGED_GIDS;
			garray_copy = &op_ctx->managed_garray_copy;
		}

		auth_label = "AUTH_SYS";
		break;

#ifdef _HAVE_GSSAPI
	case RPCSEC_GSS:
		if ((op_ctx->cred_flags & CREDS_LOADED) == 0) {
			/* Get the gss data to process them */
			gd = SVCAUTH_PRIVATE(req->rq_auth);

			memcpy(principal, gd->cname.value, gd->cname.length);
			principal[gd->cname.length] = 0;

			LogMidDebug(COMPONENT_DISPATCH,
				     "Mapping RPCSEC_GSS principal %s to uid/gid",
				     principal);

			/* Convert to uid */
#if _MSPAC_SUPPORT
			if (!principal2uid(principal,
					   &op_ctx->original_creds.caller_uid,
					   &op_ctx->original_creds.caller_gid,
					   gd)) {
#else
			if (!principal2uid(principal,
					   &op_ctx->original_creds.caller_uid,
					   &op_ctx->original_creds.caller_gid)
			   ) {
#endif
				LogWarn(COMPONENT_IDMAPPER,
					"Could not map principal %s to uid",
					principal);
				/* For compatibility with Linux knfsd, we set
				 * the uid/gid to anonymous when a name->uid
				 * mapping can't be found.
				 */
				op_ctx->cred_flags |= CREDS_ANON |
						       CREDS_LOADED;
				auth_label = "RPCSEC_GSS (no mapping)";
				break;
			}

			op_ctx->cred_flags |= CREDS_LOADED;
		}

		auth_label = "RPCSEC_GSS";
		op_ctx->cred_flags |= MANAGED_GIDS;
		garray_copy = &op_ctx->managed_garray_copy;

		break;
#endif				/* _USE_GSSRPC */

	default:
		LogMidDebug(COMPONENT_DISPATCH,
			     "FAILURE: Request xid=%u, has unsupported authentication %d",
			     req->rq_xid, req->rq_cred.oa_flavor);
		/* Reject the request for weak authentication and
		 * return to worker
		 */
		return NFS4ERR_ACCESS;

		break;
	}

	/****************************************************************/
	/* Now check for anon creds or id squashing			*/
	/****************************************************************/
	if ((op_ctx->cred_flags & CREDS_ANON) != 0 ||
	    ((op_ctx->export_perms->options &
	      EXPORT_OPTION_ALL_ANONYMOUS) != 0) ||
	    ((op_ctx->export_perms->options & EXPORT_OPTION_ROOT) == 0 &&
	      op_ctx->original_creds.caller_uid == 0)) {
		op_ctx->creds->caller_uid =
					op_ctx->export_perms->anonymous_uid;
		op_ctx->creds->caller_gid =
					op_ctx->export_perms->anonymous_gid;
		op_ctx->creds->caller_glen = 0;
		LogMidDebugAlt(COMPONENT_DISPATCH, COMPONENT_EXPORT,
			    "%s creds squashed to uid=%u, gid=%u",
			    auth_label,
			    op_ctx->creds->caller_uid,
			    op_ctx->creds->caller_gid);
		op_ctx->cred_flags |= UID_SQUASHED | GID_SQUASHED;
		return NFS4_OK;
	}

	/* Now we will use the original_creds uid from original credential */
	op_ctx->creds->caller_uid = op_ctx->original_creds.caller_uid;

	/****************************************************************/
	/* Now sqush group or use original_creds gid			*/
	/****************************************************************/
	if ((op_ctx->export_perms->options & EXPORT_OPTION_ROOT) == 0 &&
	    op_ctx->original_creds.caller_gid == 0) {
		/* Squash gid */
		op_ctx->creds->caller_gid =
					op_ctx->export_perms->anonymous_gid;
		op_ctx->cred_flags |= GID_SQUASHED;
	} else {
		/* Use original_creds gid */
		op_ctx->creds->caller_gid = op_ctx->original_creds.caller_gid;
	}

	/****************************************************************/
	/* Check if we have manage_gids.				*/
	/****************************************************************/
	if ((op_ctx->cred_flags & MANAGED_GIDS) != 0) {
		/* Fetch the group data if required */
		if (op_ctx->caller_gdata == NULL &&
		    !uid2grp(op_ctx->original_creds.caller_uid,
			     &op_ctx->caller_gdata)) {
			/** @todo: do we really want to bail here? */
			LogCrit(COMPONENT_DISPATCH,
				"Attempt to fetch managed_gids failed");
			return NFS4ERR_ACCESS;
		}

		op_ctx->creds->caller_glen = op_ctx->caller_gdata->nbgroups;
		op_ctx->creds->caller_garray = op_ctx->caller_gdata->groups;
	} else {
		/* Use the original_creds group list */
		op_ctx->creds->caller_glen   =
					op_ctx->original_creds.caller_glen;
		op_ctx->creds->caller_garray =
					op_ctx->original_creds.caller_garray;
	}

	/****************************************************************/
	/* Check the garray for gid 0 to squash				*/
	/****************************************************************/

	/* If no root squashing in caller_garray, return now */
	if ((op_ctx->export_perms->options & EXPORT_OPTION_ROOT) != 0 ||
	    op_ctx->creds->caller_glen == 0)
		goto out;

	for (i = 0; i < op_ctx->creds->caller_glen; i++) {
		if (op_ctx->creds->caller_garray[i] == 0) {
			/* Meed to make a copy, or use the old copy */
			if ((*garray_copy) == NULL) {
				/* Make a copy of the active garray */
				(*garray_copy) =
					gsh_malloc(op_ctx->creds->caller_glen *
						   sizeof(gid_t));

				memcpy((*garray_copy),
				       op_ctx->creds->caller_garray,
				       op_ctx->creds->caller_glen *
				       sizeof(gid_t));
			}

			/* Now squash the root id. Since the original copy is
			 * always the same, any root ids in it were still in
			 * the same place, so even if using a copy that had a
			 * different anonymous_gid, we're fine.
			 */
			(*garray_copy)[i] =
					op_ctx->export_perms->anonymous_gid;

			/* Indicate we squashed the caller_garray */
			op_ctx->cred_flags |= GARRAY_SQUASHED;
		}
	}

	/* If we squashed the caller_garray, use the squashed copy */
	if ((op_ctx->cred_flags & GARRAY_SQUASHED) != 0)
		op_ctx->creds->caller_garray = *garray_copy;

out:

	LogMidDebugAlt(COMPONENT_DISPATCH, COMPONENT_EXPORT,
		    "%s creds mapped to uid=%u, gid=%u%s, glen=%d%s",
		    auth_label,
		    op_ctx->creds->caller_uid,
		    op_ctx->creds->caller_gid,
		    (op_ctx->cred_flags & GID_SQUASHED) != 0
			? " (squashed)"
			: "",
		    op_ctx->creds->caller_glen,
		    (op_ctx->cred_flags & MANAGED_GIDS) != 0
			? ((op_ctx->cred_flags & GARRAY_SQUASHED) != 0
				? " (managed and squashed)"
				: " (managed)")
			: ((op_ctx->cred_flags & GARRAY_SQUASHED) != 0
				? " (squashed)"
				: ""));

	return NFS4_OK;
}

/**
 * @brief Initialize request context and credentials.
 *
 */
void init_credentials(void)
{
	memset(op_ctx->creds, 0, sizeof(*op_ctx->creds));
	memset(&op_ctx->original_creds, 0, sizeof(op_ctx->original_creds));
	op_ctx->creds->caller_uid = op_ctx->export_perms->anonymous_uid;
	op_ctx->creds->caller_gid = op_ctx->export_perms->anonymous_gid;
	op_ctx->caller_gdata = NULL;
	op_ctx->caller_garray_copy = NULL;
	op_ctx->managed_garray_copy = NULL;
	op_ctx->cred_flags = 0;
}
Пример #2
0
/**
 *
 * get_req_uid_gid: 
 *
 * 
 *
 * @param ptr_req [IN]  incoming request.
 * @param pexport_client [IN] related export client
 * @param pexport [IN]  related export entry
 * @param user_credentials [OUT] Filled in structure with uid and gids
 * 
 * @return TRUE if successful, FALSE otherwise 
 *
 */
int get_req_uid_gid(struct svc_req *ptr_req,
                    exportlist_client_entry_t * pexport_client,
                    exportlist_t * pexport, struct user_cred *user_credentials)
{
  struct authunix_parms *punix_creds = NULL;
  unsigned int rpcxid = 0;
#ifdef _HAVE_GSSAPI
  struct svc_rpc_gss_data *gd = NULL;
  char principal[MAXNAMLEN];
#endif

  if (user_credentials == NULL)
    return FALSE;

  rpcxid = get_rpc_xid(ptr_req);

  switch (ptr_req->rq_cred.oa_flavor)
    {
    case AUTH_NONE:
      /* Nothing to be done here... */
      LogFullDebug(COMPONENT_DISPATCH,
                   "Request xid=%u has authentication AUTH_NONE",
                   rpcxid);
      break;

    case AUTH_UNIX:
      LogFullDebug(COMPONENT_DISPATCH,
                   "Request xid=%u has authentication AUTH_UNIX",
                   rpcxid);
      /* We map the rq_cred to Authunix_parms */
      punix_creds = (struct authunix_parms *)ptr_req->rq_clntcred;

      /* Get the uid/gid couple */
      user_credentials->caller_uid = punix_creds->aup_uid;
      user_credentials->caller_gid = punix_creds->aup_gid;
      user_credentials->caller_glen = punix_creds->aup_len;
      user_credentials->caller_garray = punix_creds->aup_gids;

      LogFullDebug(COMPONENT_DISPATCH, "----> Uid=%u Gid=%u",
                   (unsigned int)user_credentials->caller_uid, (unsigned int)user_credentials->caller_gid);

      break;

#ifdef _HAVE_GSSAPI
    case RPCSEC_GSS:
      LogFullDebug(COMPONENT_DISPATCH,
                   "Request xid=%u has authentication RPCSEC_GSS",
                   rpcxid);
      /* Get the gss data to process them */
      gd = SVCAUTH_PRIVATE(ptr_req->rq_xprt->xp_auth);


      if(isFullDebug(COMPONENT_RPCSEC_GSS))
        {
          OM_uint32 maj_stat = 0;
          OM_uint32 min_stat = 0;
	  char ptr[256];

          gss_buffer_desc oidbuff;

          LogFullDebug(COMPONENT_RPCSEC_GSS,
                       "----> RPCSEC_GSS svc=%u RPCSEC_GSS_SVC_NONE=%u RPCSEC_GSS_SVC_INTEGRITY=%u RPCSEC_GSS_SVC_PRIVACY=%u",
                       gd->sec.svc, RPCSEC_GSS_SVC_NONE, RPCSEC_GSS_SVC_INTEGRITY,
                       RPCSEC_GSS_SVC_PRIVACY);

          memcpy(&ptr, (void *)gd->ctx + 4, 4);
          LogFullDebug(COMPONENT_RPCSEC_GSS,
                       "----> Client=%s length=%lu  Qop=%u established=%u gss_ctx_id=%p|%p",
                       (char *)gd->cname.value, gd->cname.length, gd->established, gd->sec.qop,
                       gd->ctx, ptr);

          if((maj_stat = gss_oid_to_str(&min_stat, gd->sec.mech, &oidbuff)) != GSS_S_COMPLETE)
            {
              LogFullDebug(COMPONENT_DISPATCH, "Error in gss_oid_to_str: %u|%u",
                           maj_stat, min_stat);
            }
          else
            {
              LogFullDebug(COMPONENT_RPCSEC_GSS, "----> Client mech=%s len=%lu",
                           (char *)oidbuff.value, oidbuff.length);

              // Release the string
              (void)gss_release_buffer(&min_stat, &oidbuff); 
            }
       }

      LogFullDebug(COMPONENT_RPCSEC_GSS, "Mapping principal %s to uid/gid",
                   (char *)gd->cname.value);

      memcpy(principal, gd->cname.value, gd->cname.length);
      principal[gd->cname.length] = 0;

      /* Convert to uid */
      if(!principal2uid(principal, &user_credentials->caller_uid))
	{
          LogWarn(COMPONENT_IDMAPPER,
		  "WARNING: Could not map principal to uid; mapping principal "
		  "to anonymous uid/gid");

	  /* For compatibility with Linux knfsd, we set the uid/gid
	   * to anonymous when a name->uid mapping can't be found. */
	  user_credentials->caller_uid = pexport->anonymous_uid;
	  user_credentials->caller_gid = pexport->anonymous_gid;
	  
	  /* No alternate groups for "nobody" */
	  user_credentials->caller_glen = 0 ;
	  user_credentials->caller_garray = NULL ;

	  return TRUE;
	}

      if(uidgidmap_get(user_credentials->caller_uid, &user_credentials->caller_gid) != ID_MAPPER_SUCCESS)
        {
          LogMajor(COMPONENT_DISPATCH,
                   "FAILURE: Could not resolve uidgid map for %u",
                   user_credentials->caller_uid);
          user_credentials->caller_gid = -1;
        }
      LogFullDebug(COMPONENT_DISPATCH, "----> Uid=%u Gid=%u",
                   (unsigned int)user_credentials->caller_uid, (unsigned int)user_credentials->caller_gid);
      user_credentials->caller_glen = 0;
      user_credentials->caller_garray = 0;

      break;
#endif                          /* _USE_GSSRPC */

    default:
      LogFullDebug(COMPONENT_DISPATCH,
                   "FAILURE: Request xid=%u, has unsupported authentication %d",
                   rpcxid, ptr_req->rq_cred.oa_flavor);
      /* Reject the request for weak authentication and return to worker */
      return FALSE;

      break;
    }                           /* switch( ptr_req->rq_cred.oa_flavor ) */
  return TRUE;
}