#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/fsuid.h>
+#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
struct pollfd * pollarray;
-int pollsize; /* the size of pollaray (in pollfd's) */
+unsigned long pollsize; /* the size of pollaray (in pollfd's) */
/*
* convert a presentation address string to a sockaddr_storage struct. Returns
if ((p = strstr(buf, "port")) != NULL)
sscanf(p, "port: %127s\n", port);
- /* check service, program, and version */
- if (memcmp(service, "nfs", 3) != 0)
- return -1;
+ /* get program, and version numbers */
*prog = atoi(program + 1); /* skip open paren */
*vers = atoi(version);
- if (strlen(service) == 3 ) {
- if ((*prog != 100003) || ((*vers != 2) && (*vers != 3) &&
- (*vers != 4)))
- goto fail;
- } else if (memcmp(service, "nfs4_cb", 7) == 0) {
- if (*vers != 1)
- goto fail;
- }
-
if (!addrstr_to_sockaddr(addr, address, port))
goto fail;
char gname[PATH_MAX];
char info_file_name[PATH_MAX];
+ if (clp->gssd_close_me) {
+ printerr(2, "Closing 'gssd' pipe for %s\n", clp->dirname);
+ close(clp->gssd_fd);
+ memset(&pollarray[clp->gssd_poll_index], 0,
+ sizeof(struct pollfd));
+ clp->gssd_fd = -1;
+ clp->gssd_poll_index = -1;
+ clp->gssd_close_me = 0;
+ }
+ if (clp->krb5_close_me) {
+ printerr(2, "Closing 'krb5' pipe for %s\n", clp->dirname);
+ close(clp->krb5_fd);
+ memset(&pollarray[clp->krb5_poll_index], 0,
+ sizeof(struct pollfd));
+ clp->krb5_fd = -1;
+ clp->krb5_poll_index = -1;
+ clp->krb5_close_me = 0;
+ }
+
if (clp->gssd_fd == -1) {
snprintf(gname, sizeof(gname), "%s/gssd", clp->dirname);
clp->gssd_fd = open(gname, O_RDWR);
static int
get_poll_index(int *ind)
{
- int i;
+ unsigned int i;
*ind = -1;
- for (i=0; i<FD_ALLOC_BLOCK; i++) {
+ for (i=0; i<pollsize; i++) {
if (pollarray[i].events == 0) {
*ind = i;
break;
void
init_client_list(void)
{
+ struct rlimit rlim;
TAILQ_INIT(&clnt_list);
/* Eventually plan to grow/shrink poll array: */
pollsize = FD_ALLOC_BLOCK;
+ if (getrlimit(RLIMIT_NOFILE, &rlim) < 0 &&
+ rlim.rlim_cur != RLIM_INFINITY)
+ pollsize = rlim.rlim_cur;
pollarray = calloc(pollsize, sizeof(struct pollfd));
}
update_old_clients(namelist, j, pipe_name);
for (i=0; i < j; i++) {
- if (i < FD_ALLOC_BLOCK
- && !strncmp(namelist[i]->d_name, "clnt", 4)
- && !find_client(namelist[i]->d_name, pipe_name))
+ if (!strncmp(namelist[i]->d_name, "clnt", 4)
+ && !find_client(namelist[i]->d_name, pipe_name))
process_clnt_dir(namelist[i]->d_name, pipe_name);
free(namelist[i]);
}
static int
do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
- gss_buffer_desc *context_token)
+ gss_buffer_desc *context_token, OM_uint32 lifetime_rec)
{
char *buf = NULL, *p = NULL, *end = NULL;
unsigned int timeout = context_timeout;
unsigned int buf_size = 0;
- printerr(1, "doing downcall\n");
+ printerr(1, "doing downcall lifetime_rec %u\n", lifetime_rec);
buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
sizeof(context_token->length) + context_token->length;
p = buf = malloc(buf_size);
end = buf + buf_size;
+ /* context_timeout set by -t option overrides context lifetime */
+ if (timeout == 0)
+ timeout = lifetime_rec;
if (WRITE_BYTES(&p, end, uid)) goto out_err;
if (WRITE_BYTES(&p, end, timeout)) goto out_err;
if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
* 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)
+static 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;
char **dirname;
int create_resp = -1;
int err, downcall_err = -EACCES;
+ OM_uint32 maj_stat, min_stat, lifetime_rec;
printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
- if (tgtname) {
- if (clp->servicename) {
- free(clp->servicename);
- clp->servicename = strdup(tgtname);
- }
- }
token.length = 0;
token.value = NULL;
memset(&pd, 0, sizeof(struct authgss_private_data));
int success = 0;
do {
gssd_refresh_krb5_machine_credential(clp->servername,
- NULL, service);
+ NULL, service,
+ tgtname);
/*
* Get a list of credential cache names and try each
* of them until one works or we've tried them all
goto out_return_error;
}
+ /* Grab the context lifetime to pass to the kernel. lifetime_rec
+ * is set to zero on error */
+ maj_stat = gss_inquire_context(&min_stat, pd.pd_ctx, NULL, NULL,
+ &lifetime_rec, NULL, NULL, NULL, NULL);
+
+ if (maj_stat)
+ printerr(1, "WARNING: Failed to inquire context for lifetme "
+ "maj_stat %u\n", maj_stat);
+
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",
goto out_return_error;
}
- do_downcall(fd, uid, &pd, &token);
+ do_downcall(fd, uid, &pd, &token, lifetime_rec);
out:
if (token.value)
return;
}
- return process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
+ process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
}
void