X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fgssd%2Fgssd_proc.c;h=fb97a13e7e2761673d130397a2318db2fbf156e7;hp=3b190f2995a97f54ebe3e76e6a93078d37c65374;hb=7f1f9985cf510b087e7a817597094acba9143795;hpb=f5954afaeeee07ca6ded6c4cdcbf965f02f7a670 diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c index 3b190f2..fb97a13 100644 --- a/utils/gssd/gssd_proc.c +++ b/utils/gssd/gssd_proc.c @@ -38,10 +38,14 @@ */ +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif -#include "config.h" + #include #include #include @@ -66,7 +70,6 @@ #include "gssd.h" #include "err_util.h" #include "gss_util.h" -#include "gss_oids.h" #include "krb5_util.h" #include "context.h" @@ -102,9 +105,9 @@ int pollsize; /* the size of pollaray (in pollfd's) */ /* XXX buffer problems: */ static int read_service_info(char *info_file_name, char **servicename, char **servername, - int *prog, int *vers, char **protocol) { + int *prog, int *vers, char **protocol, int *port) { #define INFOBUFLEN 256 - char buf[INFOBUFLEN]; + char buf[INFOBUFLEN + 1]; static char dummy[128]; int nbytes; static char service[128]; @@ -112,6 +115,8 @@ read_service_info(char *info_file_name, char **servicename, char **servername, char program[16]; char version[16]; char protoname[16]; + char cb_port[128]; + char *p; in_addr_t inaddr; int fd = -1; struct hostent *ent = NULL; @@ -127,6 +132,7 @@ read_service_info(char *info_file_name, char **servicename, char **servername, if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1) goto fail; close(fd); + buf[nbytes] = '\0'; numfields = sscanf(buf,"RPC server: %127s\n" "service: %127s %15s version %15s\n" @@ -143,6 +149,10 @@ read_service_info(char *info_file_name, char **servicename, char **servername, goto fail; } + cb_port[0] = '\0'; + if ((p = strstr(buf, "port")) != NULL) + sscanf(p, "port: %127s\n", cb_port); + /* check service, program, and version */ if(memcmp(service, "nfs", 3)) return -1; *prog = atoi(program + 1); /* skip open paren */ @@ -163,6 +173,8 @@ read_service_info(char *info_file_name, char **servicename, char **servername, if (!(*servicename = calloc(strlen(buf) + 1, 1))) goto fail; memcpy(*servicename, buf, strlen(buf)); + if (cb_port[0] != '\0') + *port = atoi(cb_port); if (!(*protocol = strdup(protoname))) goto fail; @@ -238,7 +250,7 @@ process_clnt_dir_files(struct clnt_info * clp) if ((clp->servicename == NULL) && read_service_info(info_file_name, &clp->servicename, &clp->servername, &clp->prog, &clp->vers, - &clp->protocol)) + &clp->protocol, &clp->port)) return -1; return 0; } @@ -419,7 +431,7 @@ do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd, gss_buffer_desc *context_token) { char *buf = NULL, *p = NULL, *end = NULL; - unsigned int timeout = 0; /* XXX decide on a reasonable value */ + unsigned int timeout = context_timeout; unsigned int buf_size = 0; printerr(1, "doing downcall\n"); @@ -430,7 +442,6 @@ do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd, end = buf + buf_size; if (WRITE_BYTES(&p, end, uid)) goto out_err; - /* Not setting any timeout for now: */ if (WRITE_BYTES(&p, end, timeout)) goto out_err; if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err; if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err; @@ -441,7 +452,7 @@ do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd, return 0; out_err: if (buf) free(buf); - printerr(0, "Failed to write downcall!\n"); + printerr(1, "Failed to write downcall!\n"); return -1; } @@ -464,7 +475,7 @@ do_error_downcall(int k5_fd, uid_t uid, int err) if (write(k5_fd, buf, p - buf) < p - buf) goto out_err; return 0; out_err: - printerr(0, "Failed to write error downcall!\n"); + printerr(1, "Failed to write error downcall!\n"); return -1; } @@ -555,7 +566,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; } @@ -563,12 +574,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); @@ -577,16 +588,18 @@ 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; } + if (clp->port) + ((struct sockaddr_in *)a->ai_addr)->sin_port = htons(clp->port); if (a->ai_protocol == IPPROTO_TCP) { if ((rpc_clnt = clnttcp_create( (struct sockaddr_in *) a->ai_addr, @@ -617,7 +630,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; } @@ -675,6 +688,7 @@ handle_krb5_upcall(struct clnt_info *clp) gss_buffer_desc token; char **credlist = NULL; char **ccname; + char **dirname; int create_resp = -1; printerr(1, "handling krb5 upcall\n"); @@ -691,23 +705,28 @@ handle_krb5_upcall(struct clnt_info *clp) 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); - - create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, - AUTHTYPE_KRB5); + for (dirname = ccachesearch; *dirname != NULL; dirname++) { + if (gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname) == 0) + create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, + AUTHTYPE_KRB5); + if (create_resp == 0) + break; + } } if (create_resp != 0) { if (uid == 0 && root_uses_machine_creds == 1) { int success = 0; + gssd_refresh_krb5_machine_credential(clp->servername, + NULL); /* * 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); + printerr(0, "ERROR: No credentials found " + "for connection to server %s\n", + clp->servername); goto out_return_error; } for (ccname = credlist; ccname && *ccname; ccname++) { @@ -726,14 +745,14 @@ handle_krb5_upcall(struct clnt_info *clp) } gssd_free_krb5_machine_cred_list(credlist); if (!success) { - printerr(0, "WARNING: Failed to create krb5 context " + printerr(1, "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 " + printerr(1, "WARNING: Failed to create krb5 context " "for user with uid %d for server %s\n", uid, clp->servername); goto out_return_error; @@ -741,13 +760,13 @@ handle_krb5_upcall(struct clnt_info *clp) } if (!authgss_get_private_data(auth, &pd)) { - printerr(0, "WARNING: Failed to obtain authentication " + printerr(1, "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, &krb5oid)) { + if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid, NULL)) { printerr(0, "WARNING: Failed to serialize krb5 context for " "user with uid %d for server %s\n", uid, clp->servername); @@ -759,8 +778,10 @@ handle_krb5_upcall(struct clnt_info *clp) out: if (token.value) free(token.value); +#ifndef HAVE_LIBTIRPC if (pd.pd_ctx_hndl.length != 0) authgss_free_private_data(&pd); +#endif if (auth) AUTH_DESTROY(auth); if (rpc_clnt) @@ -809,7 +830,7 @@ handle_spkm3_upcall(struct clnt_info *clp) goto out_return_error; } - if (serialize_context_for_kernel(pd.pd_ctx, &token, &spkm3oid)) { + if (serialize_context_for_kernel(pd.pd_ctx, &token, &spkm3oid, NULL)) { printerr(0, "WARNING: Failed to serialize spkm3 context for " "user with uid %d for server\n", uid, clp->servername);