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 */
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; }
/* * 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; }