fsal_status_t fsal_internal_set_auth_gss(proxyfsal_op_context_t * p_thr_context)
{
#ifdef _USE_GSSRPC
  fsal_status_t fsal_status;
  struct rpc_gss_sec rpcsec_gss_data;
  gss_OID mechOid;
  char mechname[1024];
  gss_buffer_desc mechgssbuff;
  OM_uint32 maj_stat, min_stat;

  /* Set up mechOid */
  strcpy(mechname, "{ 1 2 840 113554 1 2 2 }");

  mechgssbuff.value = mechname;
  mechgssbuff.length = strlen(mechgssbuff.value);

  LogFullDebug(COMPONENT_FSAL, "----> %p\n", p_thr_context->rpc_client);
  if((maj_stat = gss_str_to_oid(&min_stat, &mechgssbuff, &mechOid)) != GSS_S_COMPLETE)
    Return(ERR_FSAL_SEC, maj_stat, INDEX_FSAL_InitClientContext);

  /* Authentification avec RPCSEC_GSS */
  rpcsec_gss_data.mech = mechOid;
  rpcsec_gss_data.qop = GSS_C_QOP_DEFAULT;
  rpcsec_gss_data.svc = global_fsal_proxy_specific_info.sec_type;

  if((p_thr_context->rpc_client->cl_auth =
      authgss_create_default(p_thr_context->rpc_client,
                             global_fsal_proxy_specific_info.remote_principal,
                             &rpcsec_gss_data)) == NULL)
    Return(ERR_FSAL_SEC, 0, INDEX_FSAL_InitClientContext);
#endif
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_InitClientContext);
}                               /* fsal_internal_set_auth_gss */
Esempio n. 2
0
static inline void
nfs_rpc_callback_setup_gss(rpc_call_channel_t *chan,
                           nfs_client_cred_t *cred)
{
    AUTH *auth;
    char hprinc[MAXPATHLEN];
    int32_t code = 0;

    assert(cred->flavor == RPCSEC_GSS);

    /* MUST RFC 3530bis, section 3.3.3 */
    chan->gss_sec.svc = cred->auth_union.auth_gss.svc;
    chan->gss_sec.qop = cred->auth_union.auth_gss.qop;

    /* the GSSAPI k5 mech needs to find an unexpired credential
     * for nfs/hostname in an accessible k5ccache */
    code = gssd_refresh_krb5_machine_credential(
        host_name, NULL, nfs_param.krb5_param.svc.principal);
    if (code) {
        LogWarn(COMPONENT_NFS_CB, "gssd_refresh_krb5_machine_credential "
                 "failed (%d:%d)", code, errno);
        goto out;
    }

    if (! format_host_principal(chan, hprinc, sizeof(hprinc))) {
        LogCrit(COMPONENT_NFS_CB, "format_host_principal failed");
        goto out;
    }

    chan->gss_sec.cred = GSS_C_NO_CREDENTIAL;
    chan->gss_sec.req_flags = 0;

    if (chan->gss_sec.svc != RPCSEC_GSS_SVC_NONE) {
        /* no more lipkey, spkm3 */
        chan->gss_sec.mech = (gss_OID) &krb5oid;
        chan->gss_sec.req_flags = GSS_C_MUTUAL_FLAG; /* XXX */
        auth = 
            authgss_create_default(chan->clnt,
                                   hprinc,
                                   &chan->gss_sec);
        /* authgss_create and authgss_create_default return NULL on
         * failure, don't assign NULL to clnt->cl_auth */
        if (auth)
            chan->auth = auth;
    }

out:
    return;
}
Esempio n. 3
0
/*
 * Create an RPC connection and establish an authenticated
 * gss context with a server.
 */
static int
create_auth_rpc_client(struct clnt_info *clp,
		       char *tgtname,
		       CLIENT **clnt_return,
		       AUTH **auth_return,
		       uid_t uid,
		       int authtype,
		       gss_cred_id_t cred)
{
	CLIENT			*rpc_clnt = NULL;
	struct rpc_gss_sec	sec;
	AUTH			*auth = NULL;
	int			retval = -1;
	OM_uint32		min_stat;
	char			rpc_errmsg[1024];
	int			protocol;
	struct timeval	timeout;
	struct sockaddr		*addr = (struct sockaddr *) &clp->addr;
	socklen_t		salen;

	sec.qop = GSS_C_QOP_DEFAULT;
	sec.svc = RPCSEC_GSS_SVC_NONE;
	sec.cred = cred;
	sec.req_flags = 0;
	if (authtype == AUTHTYPE_KRB5) {
		sec.mech = (gss_OID)&krb5oid;
		sec.req_flags = GSS_C_MUTUAL_FLAG;
	}
	else {
		printerr(0, "ERROR: Invalid authentication type (%d) "
			"in create_auth_rpc_client\n", authtype);
		goto out_fail;
	}


	if (authtype == AUTHTYPE_KRB5) {
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
		/*
		 * Do this before creating rpc connection since we won't need
		 * rpc connection if it fails!
		 */
		if (limit_krb5_enctypes(&sec)) {
			printerr(1, "WARNING: Failed while limiting krb5 "
				    "encryption types for user with uid %d\n",
				 uid);
			goto out_fail;
		}
#endif
	}

	/* create an rpc connection to the nfs server */

	printerr(2, "creating %s client for server %s\n", clp->protocol,
			clp->servername);

	protocol = IPPROTO_TCP;
	if ((strcmp(clp->protocol, "udp")) == 0)
		protocol = IPPROTO_UDP;

	switch (addr->sa_family) {
	case AF_INET:
		salen = sizeof(struct sockaddr_in);
		break;
#ifdef IPV6_SUPPORTED
	case AF_INET6:
		salen = sizeof(struct sockaddr_in6);
		break;
#endif /* IPV6_SUPPORTED */
	default:
		printerr(1, "ERROR: Unknown address family %d\n",
			 addr->sa_family);
		goto out_fail;
	}

	if (!populate_port(addr, salen, clp->prog, clp->vers, protocol))
		goto out_fail;

	/* set the timeout according to the requested valued */
	timeout.tv_sec = (long) rpc_timeout;
	timeout.tv_usec = (long) 0;

	rpc_clnt = nfs_get_rpcclient(addr, salen, protocol, clp->prog,
				     clp->vers, &timeout);
	if (!rpc_clnt) {
		snprintf(rpc_errmsg, sizeof(rpc_errmsg),
			 "WARNING: can't create %s rpc_clnt to server %s for "
			 "user with uid %d",
			 protocol == IPPROTO_TCP ? "tcp" : "udp",
			 clp->servername, uid);
		printerr(0, "%s\n",
			 clnt_spcreateerror(rpc_errmsg));
		goto out_fail;
	}
	if (!tgtname)
		tgtname = clp->servicename;

	printerr(2, "creating context with server %s\n", tgtname);
	auth = authgss_create_default(rpc_clnt, tgtname, &sec);
	if (!auth) {
		/* Our caller should print appropriate message */
		printerr(1, "WARNING: Failed to create krb5 context for "
			    "user with uid %d for server %s\n",
			 uid, tgtname);
		goto out_fail;
	}

	/* Success !!! */
	rpc_clnt->cl_auth = auth;
	*clnt_return = rpc_clnt;
	*auth_return = auth;
	retval = 0;

  out:
	if (sec.cred != GSS_C_NO_CREDENTIAL)
		gss_release_cred(&min_stat, &sec.cred);
	return retval;

  out_fail:
	/* Only destroy here if failure.  Otherwise, caller is responsible */
	if (rpc_clnt) clnt_destroy(rpc_clnt);

	goto out;
}