]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mountd/cache.c
Fix silly bug with gid lookup
[nfs-utils.git] / utils / mountd / cache.c
index 6947203c0f9b91ee362458602a405173f3a816f6..fbe829e2d3fc188fbe686fc78a820199b5951ac3 100644 (file)
 #include <fcntl.h>
 #include <errno.h>
 #include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
 #include "misc.h"
 #include "nfslib.h"
 #include "exportfs.h"
 #include "mountd.h"
 #include "xmalloc.h"
+#include "fsloc.h"
 
 #include "blkid/blkid.h"
 
@@ -101,6 +104,53 @@ void auth_unix_ip(FILE *f)
        
 }
 
+void auth_unix_gid(FILE *f)
+{
+       /* Request are
+        *  uid
+        * reply is
+        *  uid expiry count list of group ids
+        */
+       int uid;
+       struct passwd *pw;
+       gid_t glist[100], *groups = glist;
+       int ngroups = 100;
+       int rv, i;
+       char *cp;
+
+       if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+               return;
+
+       cp = lbuf;
+       if (qword_get_int(&cp, &uid) != 0)
+               return;
+
+       pw = getpwuid(uid);
+       if (!pw)
+               rv = -1;
+       else {
+               rv = getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
+               if (rv == -1 && ngroups >= 100) {
+                       groups = malloc(sizeof(gid_t)*ngroups);
+                       if (!groups)
+                               rv = -1;
+                       else
+                               rv = getgrouplist(pw->pw_name, pw->pw_gid,
+                                                 groups, &ngroups);
+               }
+       }
+       qword_printint(f, uid);
+       qword_printint(f, time(0)+30*60);
+       if (rv >= 0) {
+               qword_printint(f, ngroups);
+               for (i=0; i<ngroups; i++)
+                       qword_printint(f, groups[i]);
+       }
+       qword_eol(f);
+       if (groups != glist)
+               free(groups);
+}
+
 int get_uuid(char *path, char *uuid, int uuidlen, char *u)
 {
        /* extract hex digits from uuidstr and compose a uuid
@@ -372,6 +422,29 @@ void nfsd_fh(FILE *f)
        return;         
 }
 
+static void write_fsloc(FILE *f, struct exportent *ep, char *path)
+{
+       struct servers *servers;
+
+       if (ep->e_fslocmethod == FSLOC_NONE)
+               return;
+
+       servers = replicas_lookup(ep->e_fslocmethod, ep->e_fslocdata, path);
+       if (!servers)
+               return;
+       qword_print(f, "fsloc");
+       qword_printint(f, servers->h_num);
+       if (servers->h_num >= 0) {
+               int i;
+               for (i=0; i<servers->h_num; i++) {
+                       qword_print(f, servers->h_mp[i]->h_host);
+                       qword_print(f, servers->h_mp[i]->h_path);
+               }
+       }
+       qword_printint(f, servers->h_referral);
+       release_replicas(servers);
+}
+
 static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
 {
        qword_print(f, domain);
@@ -382,6 +455,7 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex
                qword_printint(f, exp->e_anonuid);
                qword_printint(f, exp->e_anongid);
                qword_printint(f, exp->e_fsid);
+               write_fsloc(f, exp, path);
                if (exp->e_uuid == NULL) {
                        char u[16];
                        if (get_uuid(exp->e_path, NULL, 16, u)) {
@@ -462,16 +536,20 @@ struct {
        FILE *f;
 } cachelist[] = {
        { "auth.unix.ip", auth_unix_ip},
+       { "auth.unix.gid", auth_unix_gid},
        { "nfsd.export", nfsd_export},
        { "nfsd.fh", nfsd_fh},
        { NULL, NULL }
 };
 
+extern int manage_gids;
 void cache_open(void) 
 {
        int i;
-       for (i=0; cachelist[i].cache_name; i++ ){
+       for (i=0; cachelist[i].cache_name; i++ ) {
                char path[100];
+               if (!manage_gids && cachelist[i].cache_handle == auth_unix_gid)
+                       continue;
                sprintf(path, "/proc/net/rpc/%s/channel", cachelist[i].cache_name);
                cachelist[i].f = fopen(path, "r+");
        }
@@ -529,7 +607,7 @@ int cache_export(nfs_export *exp)
        if (exp->m_export.e_maptype != CLE_MAP_IDENT) {
                xlog(L_ERROR, "%s: unsupported mapping; kernel supports only 'identity' (default)",
                    exp->m_export.m_path);
-               return;
+               return -1;
        }
 
        f = fopen("/proc/net/rpc/auth.unix.ip/channel", "w");