# include <netdb.h>
#endif
+#include <libcfs/util/param.h>
+
#include "gssd.h"
#include "err_util.h"
#include "gss_util.h"
/* Context creation response. */
struct lustre_gss_init_res {
- gss_buffer_desc gr_ctx; /* context handle */
- u_int gr_major; /* major status */
- u_int gr_minor; /* minor status */
- u_int gr_win; /* sequence window */
- gss_buffer_desc gr_token; /* token */
+ gss_buffer_desc gr_ctx; /* context handle */
+ unsigned int gr_major; /* major status */
+ unsigned int gr_minor; /* minor status */
+ unsigned int gr_win; /* sequence window */
+ gss_buffer_desc gr_token; /* token */
};
struct lustre_gss_data {
- int lgd_established;
- int lgd_lustre_svc; /* mds/oss */
- int lgd_uid; /* uid */
- char *lgd_uuid; /* client device uuid */
- gss_name_t lgd_name; /* service name */
-
- gss_OID lgd_mech; /* mech OID */
- u_int lgd_req_flags; /* request flags */
- gss_cred_id_t lgd_cred; /* credential */
- gss_ctx_id_t lgd_ctx; /* session context */
- gss_buffer_desc lgd_rmt_ctx; /* remote handle of context */
- uint32_t lgd_seq_win; /* sequence window */
-
- int lgd_rpc_err;
- int lgd_gss_err;
+ int lgd_established;
+ int lgd_lustre_svc; /* mds/oss */
+ int lgd_uid; /* uid */
+ char *lgd_uuid; /* client device uuid */
+ gss_name_t lgd_name; /* service name */
+
+ gss_OID lgd_mech; /* mech OID */
+ unsigned int lgd_req_flags; /* request flags */
+ gss_cred_id_t lgd_cred; /* credential */
+ gss_ctx_id_t lgd_ctx; /* session context */
+ gss_buffer_desc lgd_rmt_ctx; /* remote handle of context */
+ uint32_t lgd_seq_win; /* sequence window */
+
+ int lgd_rpc_err;
+ int lgd_gss_err;
};
static int
return -1;
}
-#if 0
-/*
- * Create an RPC connection and establish an authenticated
- * gss context with a server.
- */
-int create_auth_rpc_client(struct clnt_info *clp,
- CLIENT **clnt_return,
- AUTH **auth_return,
- uid_t uid,
- int authtype)
-{
- CLIENT *rpc_clnt = NULL;
- struct rpc_gss_sec sec;
- AUTH *auth = NULL;
- uid_t save_uid = -1;
- int retval = -1;
- int errcode;
- OM_uint32 min_stat;
- char rpc_errmsg[1024];
- int sockp = RPC_ANYSOCK;
- int sendsz = 32768, recvsz = 32768;
- struct addrinfo ai_hints, *a = NULL;
- char service[64];
- char *at_sign;
-
- /* Create the context as the user (not as root) */
- save_uid = geteuid();
- if (setfsuid(uid) != 0) {
- printerr(0, "WARNING: Failed to setfsuid for "
- "user with uid %d\n", uid);
- goto out_fail;
- }
- printerr(2, "creating context using fsuid %d (save_uid %d)\n",
- uid, save_uid);
-
- sec.qop = GSS_C_QOP_DEFAULT;
- sec.svc = RPCSEC_GSS_SVC_NONE;
- sec.cred = GSS_C_NO_CREDENTIAL;
- sec.req_flags = 0;
- if (authtype == AUTHTYPE_KRB5) {
- sec.mech = (gss_OID)&krb5oid;
- sec.req_flags = GSS_C_MUTUAL_FLAG;
- }
- else if (authtype == AUTHTYPE_SPKM3) {
- sec.mech = (gss_OID)&spkm3oid;
- /* XXX sec.req_flags = GSS_C_ANON_FLAG;
- * Need a way to switch....
- */
- 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, uid)) {
- 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);
-
- memset(&ai_hints, '\0', sizeof(ai_hints));
- ai_hints.ai_family = PF_INET;
- ai_hints.ai_flags |= AI_CANONNAME;
- if ((strcmp(clp->protocol, "tcp")) == 0) {
- ai_hints.ai_socktype = SOCK_STREAM;
- ai_hints.ai_protocol = IPPROTO_TCP;
- } else if ((strcmp(clp->protocol, "udp")) == 0) {
- ai_hints.ai_socktype = SOCK_DGRAM;
- ai_hints.ai_protocol = IPPROTO_UDP;
- } else {
- printerr(0, "WARNING: unrecognized protocol, '%s', requested "
- "for connection to server %s for user with uid %d",
- clp->protocol, clp->servername, uid);
- goto out_fail;
- }
-
- /* extract the service name from clp->servicename */
- if ((at_sign = strchr(clp->servicename, '@')) == NULL) {
- printerr(0, "WARNING: servicename (%s) not formatted as "
- "expected with service@host", clp->servicename);
- goto out_fail;
- }
- if ((at_sign - clp->servicename) >= sizeof(service)) {
- printerr(0, "WARNING: service portion of servicename (%s) "
- "is too long!", clp->servicename);
- goto out_fail;
- }
- strncpy(service, clp->servicename, at_sign - clp->servicename);
- service[at_sign - clp->servicename] = '\0';
-
- errcode = getaddrinfo(clp->servername, service, &ai_hints, &a);
- if (errcode) {
- printerr(0, "WARNING: Error from getaddrinfo for server "
- "'%s': %s", clp->servername, gai_strerror(errcode));
- goto out_fail;
- }
-
- if (a == NULL) {
- printerr(0, "WARNING: No address information found for "
- "connection to server %s for user with uid %d",
- clp->servername, uid);
- goto out_fail;
- }
- if (a->ai_protocol == IPPROTO_TCP) {
- if ((rpc_clnt = clnttcp_create(
- (struct sockaddr_in *) a->ai_addr,
- clp->prog, clp->vers, &sockp,
- sendsz, recvsz)) == NULL) {
- snprintf(rpc_errmsg, sizeof(rpc_errmsg),
- "WARNING: can't create tcp rpc_clnt "
- "for server %s for user with uid %d",
- clp->servername, uid);
- printerr(0, "%s\n",
- clnt_spcreateerror(rpc_errmsg));
- goto out_fail;
- }
- } else if (a->ai_protocol == IPPROTO_UDP) {
- const struct timeval timeout = {5, 0};
- if ((rpc_clnt = clntudp_bufcreate(
- (struct sockaddr_in *) a->ai_addr,
- clp->prog, clp->vers, timeout,
- &sockp, sendsz, recvsz)) == NULL) {
- snprintf(rpc_errmsg, sizeof(rpc_errmsg),
- "WARNING: can't create udp rpc_clnt "
- "for server %s for user with uid %d",
- clp->servername, uid);
- printerr(0, "%s\n",
- clnt_spcreateerror(rpc_errmsg));
- goto out_fail;
- }
- } else {
- /* Shouldn't happen! */
- printerr(0, "ERROR: requested protocol '%s', but "
- "got addrinfo with protocol %d",
- clp->protocol, a->ai_protocol);
- goto out_fail;
- }
- /* We're done with this */
- freeaddrinfo(a);
- a = NULL;
-
- printerr(2, "creating context with server %s\n", clp->servicename);
- auth = authgss_create_default(rpc_clnt, clp->servicename, &sec);
- if (!auth) {
- /* Our caller should print appropriate message */
- printerr(2, "WARNING: Failed to create %s context for "
- "user with uid %d for server %s\n",
- (authtype == AUTHTYPE_KRB5 ? "krb5":"spkm3"),
- uid, clp->servername);
- 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);
- if (a != NULL) freeaddrinfo(a);
- /* Restore euid to original value */
- if ((save_uid != -1) && (setfsuid(save_uid) != uid)) {
- printerr(0, "WARNING: Failed to restore fsuid"
- " to uid %d from %d\n", save_uid, uid);
- }
- return retval;
-
- out_fail:
- /* Only destroy here if failure. Otherwise, caller is responsible */
- if (rpc_clnt) clnt_destroy(rpc_clnt);
-
- goto out;
-}
-#endif
-
static
int do_negotiation(struct lustre_gss_data *lgd,
gss_buffer_desc *gss_token,
struct lustre_gss_init_res *gr,
int timeout)
{
- char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel";
struct lgssd_ioctl_param param;
struct passwd *pw;
- int fd, ret;
char outbuf[8192];
unsigned int *p;
- int res;
+ glob_t path;
+ int fd;
+ int rc;
pw = getpwuid(lgd->lgd_uid);
if (!pw) {
return -1;
}
- param.version = GSSD_INTERFACE_VERSION;
+ param.version = GSSD_INTERFACE_VERSION_V1;
param.uuid = lgd->lgd_uuid;
param.lustre_svc = lgd->lgd_lustre_svc;
param.uid = lgd->lgd_uid;
param.reply_buf_size = sizeof(outbuf);
param.reply_buf = outbuf;
- fd = open(file, O_RDWR);
- if (fd < 0) {
- printerr(0, "can't open file %s\n", file);
+ if (cfs_get_param_paths(&path, "sptlrpc/gss/init_channel") != 0)
return -1;
- }
- ret = write(fd, ¶m, sizeof(param));
+ fd = open(path.gl_pathv[0], O_RDWR);
+ if (fd < 0) {
+ printerr(0, "can't open file %s\n", path.gl_pathv[0]);
+ rc = -1;
+ goto out_params;
+ }
- if (ret != sizeof(param)) {
+ rc = write(fd, ¶m, sizeof(param));
+ if (rc != sizeof(param)) {
printerr(0, "lustre ioctl err: %d\n", strerror(errno));
- close(fd);
- return -1;
+ rc = -1;
+ goto out_fd;
}
if (param.status) {
- close(fd);
printerr(0, "status: %d (%s)\n",
param.status, strerror((int)param.status));
if (param.status == -ETIMEDOUT) {
lgd->lgd_rpc_err = param.status;
lgd->lgd_gss_err = 0;
}
- return -1;
+ rc = -1;
+ goto out_fd;
}
p = (unsigned int *)outbuf;
- res = *p++;
gr->gr_major = *p++;
gr->gr_minor = *p++;
gr->gr_win = *p++;
printerr(2, "do_negotiation: receive handle len %d, token len %d\n",
gr->gr_ctx.length, gr->gr_token.length);
+ rc = 0;
+out_fd:
close(fd);
- return 0;
+out_params:
+ cfs_free_param_data(&path);
+ return rc;
}
static
goto out;
}
-/*
- * this code uses the userland rpcsec gss library to create an spkm3
- * context on behalf of the kernel
- */
-void
-handle_spkm3_upcall(struct clnt_info *clp)
-{
-#if 0
- uid_t uid;
- CLIENT *rpc_clnt = NULL;
- AUTH *auth = NULL;
- struct authgss_private_data pd;
- gss_buffer_desc token;
-
- printerr(2, "handling spkm3 upcall\n");
-
- token.length = 0;
- token.value = NULL;
-
- if (read(clp->spkm3_fd, &uid, sizeof(uid)) < sizeof(uid)) {
- printerr(0, "WARNING: failed reading uid from spkm3 "
- "upcall pipe: %s\n", strerror(errno));
- goto out;
- }
-
- if (create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, AUTHTYPE_SPKM3)) {
- printerr(0, "WARNING: Failed to create spkm3 context for "
- "user with uid %d\n", uid);
- goto out_return_error;
- }
-
- if (!authgss_get_private_data(auth, &pd)) {
- printerr(0, "WARNING: Failed to obtain authentication "
- "data for user with uid %d for server %s\n",
- uid, clp->servername);
- goto out_return_error;
- }
-
- if (serialize_context_for_kernel(pd.pd_ctx, &token, &spkm3oid)) {
- printerr(0, "WARNING: Failed to serialize spkm3 context for "
- "user with uid %d for server\n",
- uid, clp->servername);
- goto out_return_error;
- }
-
- do_downcall(clp->spkm3_fd, uid, &pd, &token);
-
-out:
- if (token.value)
- free(token.value);
- if (auth)
- AUTH_DESTROY(auth);
- if (rpc_clnt)
- clnt_destroy(rpc_clnt);
- return;
-
-out_return_error:
- do_error_downcall(clp->spkm3_fd, uid, -1);
- goto out;
-#endif
-}