X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fgssd%2Fgssd_proc.c;h=eff740cdcdfce96cd58d78c0bdb0f777a5d37c5c;hp=75a04f5ba23744af9c0a347db1d9447cd5d60da3;hb=2795f8c34d24b9d4f6cf55d02b899fb66cf3e6c4;hpb=660809fe7e597520d17deab9225f1b371c08d65c diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c index 75a04f5..eff740c 100644 --- a/utils/gssd/gssd_proc.c +++ b/utils/gssd/gssd_proc.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -79,19 +80,19 @@ * with an index into pollarray[], and other basic data about that client. * * Directory structure: created by the kernel nfs client - * /pipefsdir/clntXX : one per rpc_clnt struct in the kernel - * /pipefsdir/clntXX/krb5 : read uid for which kernel wants - * a context, write the resulting context - * /pipefsdir/clntXX/info : stores info such as server name + * {pipefs_nfsdir}/clntXX : one per rpc_clnt struct in the kernel + * {pipefs_nfsdir}/clntXX/krb5 : read uid for which kernel wants + * a context, write the resulting context + * {pipefs_nfsdir}/clntXX/info : stores info such as server name * * Algorithm: - * Poll all /pipefsdir/clntXX/krb5 files. When ready, data read + * Poll all {pipefs_nfsdir}/clntXX/krb5 files. When ready, data read * is a uid; performs rpcsec_gss context initialization protocol to * get a cred for that user. Writes result to corresponding krb5 file * in a form the kernel code will understand. * In addition, we make sure we are notified whenever anything is - * created or destroyed in pipefsdir/ or in an of the clntXX directories, - * and rescan the whole pipefsdir when this happens. + * created or destroyed in {pipefs_nfsdir} or in an of the clntXX directories, + * and rescan the whole {pipefs_nfsdir} when this happens. */ struct pollfd * pollarray; @@ -388,16 +389,16 @@ update_client_list(void) struct dirent **namelist; int i, j; - if (chdir(pipefsdir) < 0) { + if (chdir(pipefs_nfsdir) < 0) { printerr(0, "ERROR: can't chdir to %s: %s\n", - pipefsdir, strerror(errno)); + pipefs_nfsdir, strerror(errno)); return -1; } - j = scandir(pipefsdir, &namelist, NULL, alphasort); + j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort); if (j < 0) { printerr(0, "ERROR: can't scandir %s: %s\n", - pipefsdir, strerror(errno)); + pipefs_nfsdir, strerror(errno)); return -1; } update_old_clients(namelist, j); @@ -493,13 +494,13 @@ int create_auth_rpc_client(struct clnt_info *clp, /* Create the context as the user (not as root) */ save_uid = geteuid(); - if (seteuid(uid) != 0) { - printerr(0, "WARNING: Failed to seteuid for " + 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 euid %d (save_uid %d)\n", - geteuid(), save_uid); + 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; @@ -554,7 +555,7 @@ int create_auth_rpc_client(struct clnt_info *clp, ai_hints.ai_protocol = IPPROTO_UDP; } else { printerr(0, "WARNING: unrecognized protocol, '%s', requested " - "for connection to server %s for user with uid %d", + "for connection to server %s for user with uid %d\n", clp->protocol, clp->servername, uid); goto out_fail; } @@ -562,12 +563,12 @@ int create_auth_rpc_client(struct clnt_info *clp, /* 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); + "expected with service@host\n", 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); + "is too long!\n", clp->servicename); goto out_fail; } strncpy(service, clp->servicename, at_sign - clp->servicename); @@ -576,13 +577,13 @@ int create_auth_rpc_client(struct clnt_info *clp, 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)); + "'%s': %s\n", 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", + "connection to server %s for user with uid %d\n", clp->servername, uid); goto out_fail; } @@ -616,7 +617,7 @@ int create_auth_rpc_client(struct clnt_info *clp, } else { /* Shouldn't happen! */ printerr(0, "ERROR: requested protocol '%s', but " - "got addrinfo with protocol %d", + "got addrinfo with protocol %d\n", clp->protocol, a->ai_protocol); goto out_fail; } @@ -646,9 +647,9 @@ int create_auth_rpc_client(struct clnt_info *clp, gss_release_cred(&min_stat, &sec.cred); if (a != NULL) freeaddrinfo(a); /* Restore euid to original value */ - if ((save_uid != -1) && (seteuid(save_uid) != 0)) { - printerr(0, "WARNING: Failed to restore euid" - " to uid %d\n", save_uid); + 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; @@ -674,6 +675,7 @@ handle_krb5_upcall(struct clnt_info *clp) gss_buffer_desc token; char **credlist = NULL; char **ccname; + int create_resp = -1; printerr(1, "handling krb5 upcall\n"); @@ -687,49 +689,52 @@ handle_krb5_upcall(struct clnt_info *clp) goto out; } - if (uid == 0) { - int success = 0; - - /* - * Get a list of credential cache names and try each - * of them until one works or we've tried them all - */ - if (gssd_get_krb5_machine_cred_list(&credlist)) { - printerr(0, "WARNING: Failed to obtain machine " - "credentials for connection to " - "server %s\n", clp->servername); - goto out_return_error; - } - for (ccname = credlist; ccname && *ccname; ccname++) { - gssd_setup_krb5_machine_gss_ccache(*ccname); - if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, - AUTHTYPE_KRB5)) == 0) { - /* Success! */ - success++; - break; - } - printerr(2, "WARNING: Failed to create krb5 context " - "for user with uid %d with credentials " - "cache %s for server %s\n", - uid, *ccname, clp->servername); - } - gssd_free_krb5_machine_cred_list(credlist); - if (!success) { - printerr(0, "WARNING: Failed to create krb5 context " - "for user with uid %d with any " - "credentials cache for server %s\n", - uid, clp->servername); - goto out_return_error; - } - } - else { + if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0)) { /* Tell krb5 gss which credentials cache to use */ gssd_setup_krb5_user_gss_ccache(uid, clp->servername); - if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, - AUTHTYPE_KRB5)) != 0) { + create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, + AUTHTYPE_KRB5); + } + if (create_resp != 0) { + if (uid == 0 && root_uses_machine_creds == 1) { + int success = 0; + + /* + * Get a list of credential cache names and try each + * of them until one works or we've tried them all + */ + if (gssd_get_krb5_machine_cred_list(&credlist)) { + printerr(0, "WARNING: Failed to obtain machine " + "credentials for connection to " + "server %s\n", clp->servername); + goto out_return_error; + } + for (ccname = credlist; ccname && *ccname; ccname++) { + gssd_setup_krb5_machine_gss_ccache(*ccname); + if ((create_auth_rpc_client(clp, &rpc_clnt, + &auth, uid, + AUTHTYPE_KRB5)) == 0) { + /* Success! */ + success++; + break; + } + printerr(2, "WARNING: Failed to create krb5 context " + "for user with uid %d with credentials " + "cache %s for server %s\n", + uid, *ccname, clp->servername); + } + gssd_free_krb5_machine_cred_list(credlist); + if (!success) { + printerr(0, "WARNING: Failed to create krb5 context " + "for user with uid %d with any " + "credentials cache for server %s\n", + uid, clp->servername); + goto out_return_error; + } + } else { printerr(0, "WARNING: Failed to create krb5 context " - "for user with uid %d for server %s\n", + "for user with uid %d for server %s\n", uid, clp->servername); goto out_return_error; }