]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/gssd/gssd_proc.c
gssd: Fix double free when exporting lucid context
[nfs-utils.git] / utils / gssd / gssd_proc.c
index 1bc394270a0861b9d375d110cfd678e8119ea837..d6f07e63e714c2fdc77b436ecd7adc825127d64d 100644 (file)
@@ -52,6 +52,7 @@
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #include <sys/fsuid.h>
+#include <sys/resource.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -168,7 +169,7 @@ sockaddr_to_hostname(const struct sockaddr *sa, const char *addr)
 {
        socklen_t               addrlen;
        int                     err;
-       char                    *hostname;
+       char                    *hostname;
        char                    hbuf[NI_MAXHOST];
 
        switch (sa->sa_family) {
@@ -250,21 +251,10 @@ read_service_info(char *info_file_name, char **servicename, char **servername,
        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;
 
@@ -398,10 +388,10 @@ process_clnt_dir_files(struct clnt_info * clp)
 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;
@@ -483,9 +473,13 @@ fail_keep_client:
 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));
 }
 
@@ -567,9 +561,8 @@ process_pipedir(char *pipe_name)
 
        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]);
        }
@@ -715,7 +708,7 @@ out_err:
 
 /*
  * If the port isn't already set, do an rpcbind query to the remote server
- * using the program and version and get the port. 
+ * using the program and version and get the port.
  *
  * Newer kernels send the value of the port= mount option in the "info"
  * file for the upcall or '0' for NFSv2/3. For NFSv4 it sends the value
@@ -962,12 +955,6 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
 
        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));
@@ -1016,7 +1003,8 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
                        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
@@ -1025,7 +1013,7 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
                                        printerr(0, "ERROR: No credentials found "
                                                 "for connection to server %s\n",
                                                 clp->servername);
-                                               goto out_return_error;
+                                       goto out_return_error;
                                }
                                for (ccname = credlist; ccname && *ccname; ccname++) {
                                        gssd_setup_krb5_machine_gss_ccache(*ccname);
@@ -1035,12 +1023,12 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
                                                /* Success! */
                                                success++;
                                                break;
-                                       } 
+                                       }
                                        printerr(2, "WARNING: Failed to create machine krb5 context "
                                                 "with credentials cache %s for server %s\n",
                                                 *ccname, clp->servername);
                                }
-                               gssd_free_krb5_machine_cred_list(credlist);                     
+                               gssd_free_krb5_machine_cred_list(credlist);
                                if (!success) {
                                        if(nocache == 0) {
                                                nocache++;
@@ -1078,7 +1066,7 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
                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)) {
+       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);
@@ -1090,8 +1078,8 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
 out:
        if (token.value)
                free(token.value);
-#ifndef HAVE_LIBTIRPC
-       if (pd.pd_ctx_hndl.length != 0)
+#ifdef HAVE_AUTHGSS_FREE_PRIVATE_DATA
+       if (pd.pd_ctx_hndl.length != 0 || pd.pd_ctx != 0)
                authgss_free_private_data(&pd);
 #endif
        if (auth)
@@ -1116,7 +1104,7 @@ handle_krb5_upcall(struct clnt_info *clp)
                return;
        }
 
-       return process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
+       process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
 }
 
 void
@@ -1237,6 +1225,6 @@ out:
        free(enctypes);
        free(target);
        free(service);
-       return; 
+       return;
 }