Index: enf/src/nfs-utils/0.3.3/ChangeLog diff -u enf/src/nfs-utils/0.3.3/ChangeLog:1.1.1.1 enf/src/nfs-utils/0.3.3/ChangeLog:1.3 --- enf/src/nfs-utils/0.3.3/ChangeLog:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/ChangeLog Tue Feb 19 16:11:19 2002 @@ -1,3 +1,22 @@ +2001-10-05 Joseph Spadavecchia [JES] + + Added id range-mapping (rmap) and file-cloaking (clist) + support features... + + * support/export/export.c: fixed up dupexport() to copy rmap & clist data + * support/export/nfsctl.c: modified export_export(), export_unexport() + to flush, add, and delete rmaps and clists accordingly. + * support/include/nfs/nfs.h: copy over new nfsctl_enf struct + * support/include/nfslib.h: new user-space struct for rmaps and clists + * support/nfs/Makefile: added nfsenf.c + * support/nfs/nfsenf.c: ioctls for adding rmaps and clists + * support/nfs/exports.c: parserangemap(), parsecloaklist() added + also added new line '\' support and true white-space support + * utils/exportfs/exportfs.c: -f option added + * utils/exportfs/exportfs.man: updated for -f option + * utils/exportfs/exports.man: rmap and clist doc. + * utils/mountd/mountd.c: umnt_1 export_unexport non FQDN clients + 2001-09-24 H.J. Lu * configure.in (VERSION): Set to "0.3.3". @@ -1238,3 +1257,5 @@ * linux-nfs/TODO: Likewise. * Starting from knfsd 1.4.7. + LocalWords: Lu utils ll nfs README + Index: enf/src/nfs-utils/0.3.3/NEWS diff -u /dev/null enf/src/nfs-utils/0.3.3/NEWS:1.2 --- /dev/null Tue Mar 19 02:12:28 2002 +++ enf/src/nfs-utils/0.3.3/NEWS Tue Feb 19 16:11:19 2002 @@ -0,0 +1,28 @@ +NEWS + +2001-10-05 Joseph Spadavecchia [JES] + + New Enhanced NFS Features API available for id range-mapping + and file-cloaking. + + user-space changes: + ~~~~~~~~~~~~~~~~~~~ + nfsenf(struct nfsctl_enf *) - add, delete, or flush range-mapping + and file-cloaking information + + Either range-mapping or file-cloaking information can be passed to + knfsd using this ioctl by setting the value of en_type to either + ENF_TRMAP, or ENF_TCLIST, respectively. + + Range mapping and file cloaking information is added, deleted, or + flushed depending on the value of en_func. This value can be + ENF_ADD, ENF_DELETE, or ENF_FLUSH. + + For a complete look at the required parameters of nfsctl_enf + please see support/include/nfs/nfs.h. + + kernel-space changes: + ~~~~~~~~~~~~~~~~~~~~~ + enf_add(struct nfsctl_enf *) + enf_delete(struct nfsctl_enf *) + enf_flush(struct nfsctl_enf *) Index: enf/src/nfs-utils/0.3.3/TODO diff -u /dev/null enf/src/nfs-utils/0.3.3/TODO:1.2 --- /dev/null Tue Mar 19 02:12:28 2002 +++ enf/src/nfs-utils/0.3.3/TODO Sat Mar 9 00:36:01 2002 @@ -0,0 +1,5 @@ +TODO + +range mapping and file cloaking things to do: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +- Add full proc support for range mapping and file cloaking information. Index: enf/src/nfs-utils/0.3.3/support/export/export.c diff -u enf/src/nfs-utils/0.3.3/support/export/export.c:1.1.1.1 enf/src/nfs-utils/0.3.3/support/export/export.c:1.2 --- enf/src/nfs-utils/0.3.3/support/export/export.c:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/support/export/export.c Fri Oct 12 18:01:26 2001 @@ -4,6 +4,10 @@ * Maintain list of exported file systems. * * Copyright (C) 1995, 1996 Olaf Kirch + * + * CHANGES: March 4, 2001 - range mapping support added + * Joseph Spadavecchia + * Nenad Dedic */ #include "config.h" @@ -228,6 +232,12 @@ void export_freeall(void) { + struct rmapent* rmap_entp; + struct rmapent* rmap; + + struct cloakent* cloak_entp; + struct cloakent* clist; + nfs_export *exp, *nxt; int i; @@ -239,6 +249,26 @@ xfree(exp->m_export.e_squids); if (exp->m_export.e_sqgids) xfree(exp->m_export.e_sqgids); + + /* free our rmapent lists */ + rmap = exp->m_export.e_rmap; + + while (rmap) { + rmap_entp = rmap->r_next; + free(rmap); + rmap = rmap_entp; + } + + + /* free cloak list */ + clist = exp->m_export.e_clist; + + while(clist) { + cloak_entp = clist->c_next; + free(clist); + clist = cloak_entp; + } + xfree(exp); } exportlist[i] = NULL; Index: enf/src/nfs-utils/0.3.3/support/export/nfsctl.c diff -u enf/src/nfs-utils/0.3.3/support/export/nfsctl.c:1.1.1.1 enf/src/nfs-utils/0.3.3/support/export/nfsctl.c:1.2 --- enf/src/nfs-utils/0.3.3/support/export/nfsctl.c:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/support/export/nfsctl.c Fri Oct 12 18:01:26 2001 @@ -4,6 +4,10 @@ * Communicate export information to knfsd. * * Copyright (C) 1995 Olaf Kirch + * + * CHANGES: March 4, 2001 - added support for id range mapping + * Joseph Spadavecchia + * Nenad Dedic */ #include "config.h" @@ -18,24 +22,36 @@ static int expsetup(struct nfsctl_export *exparg, nfs_export *exp); static int cltsetup(struct nfsctl_client *cltarg, nfs_client *clp); +static int export_enf(nfs_export *exp, unsigned char type); +static int unexport_enf(nfs_export *exp, unsigned char type); int export_export(nfs_export *exp) { - nfs_client * clp = exp->m_client; + nfs_client * clp = exp->m_client; struct nfsctl_export exparg; struct nfsctl_client cltarg; - if (!clp->m_exported) { + if(!clp->m_exported) { if (!cltsetup(&cltarg, clp)) return 0; if (nfsaddclient(&cltarg) < 0) return 0; clp->m_exported = 1; } - if (!expsetup(&exparg, exp)) + + if(!expsetup(&exparg, exp)) + return 0; + if(nfsexport(&exparg) < 0) + return 0; + + if(!unexport_enf(exp, ENF_TRMAP)) return 0; - if (nfsexport(&exparg) < 0) + if(!unexport_enf(exp, ENF_TCLIST)) + return 0; + if(!export_enf(exp, ENF_TRMAP)) + return 0; + if(!export_enf(exp, ENF_TCLIST)) return 0; exp->m_exported = 1; return 1; @@ -46,6 +62,15 @@ { struct nfsctl_export exparg; + /* Remove range mapping file cloaking + * information for this export. + */ + if(!unexport_enf(exp, ENF_TRMAP)) + return 0; + + if(!unexport_enf(exp, ENF_TCLIST)) + return 0; + if (!expsetup(&exparg, exp) || nfsunexport(&exparg) < 0) return 0; exp->m_exported = 0; @@ -102,4 +127,127 @@ exparg->ex_anon_gid = exp->m_export.e_anongid; return 1; +} + +static int +export_enf(nfs_export *exp, unsigned char type) +{ + struct nfsctl_enf enfarg; + struct cloakent *cloak_entp; + struct rmapent *rmap_entp; + int i_err; + + switch(type) { + case ENF_TRMAP: + case ENF_TCLIST: + break; + default: + i_err = 0; + goto out; + } + + /* This uniquely identifies an /etc/exports entry's + * enf information in the kernel. The id must be + * made with the hostname as it appears in + * /etc/exports; hence, e_hostname!!! + */ + enf_mkid(enfarg.ne_id, sizeof(enfarg.ne_id), + exp->m_export.e_path, + exp->m_export.e_hostname); + /* ne_client must be the actual FQDN! */ + strncpy(enfarg.ne_client, exp->m_client->m_hostname, sizeof(enfarg.ne_client)); + strncpy(enfarg.ne_path, exp->m_export.e_path, sizeof(enfarg.ne_path)); + + enfarg.ne_func = ENF_ADD; + enfarg.ne_type = type; + + switch(type) { + case ENF_TCLIST: + cloak_entp = exp->m_export.e_clist; + while(cloak_entp) { + enfarg.ne_uid = cloak_entp->c_uid; + if(enfarg.ne_uid) { + enfarg.u_lo.uid = cloak_entp->c_lo; + enfarg.u_hi.uid = cloak_entp->c_hi; + } else { + enfarg.u_lo.gid = cloak_entp->c_lo; + enfarg.u_hi.gid = cloak_entp->c_hi; + } + + enfarg.ne_mask = cloak_entp->c_mask; + + i_err = nfsenf(&(enfarg)); + if(i_err < 0) { + perror("nfsenf"); + i_err = 0; + goto out; + } + + cloak_entp = cloak_entp->c_next; + } + break; + case ENF_TRMAP: + rmap_entp = exp->m_export.e_rmap; + while(rmap_entp) { + enfarg.ne_uid = rmap_entp->r_uid; + if(enfarg.ne_uid) { + enfarg.u_lo.uid = rmap_entp->r_lo; + enfarg.u_hi.uid = rmap_entp->r_hi; + enfarg.u_mapto.uid = rmap_entp->r_mapto; + } else { + enfarg.u_lo.gid = rmap_entp->r_lo; + enfarg.u_hi.gid = rmap_entp->r_hi; + enfarg.u_mapto.gid = rmap_entp->r_mapto; + } + + enfarg.ne_map = rmap_entp->r_map; + + i_err = nfsenf(&(enfarg)); + if(i_err < 0) { + perror("nfsenf"); + i_err = 0; + goto out; + } + rmap_entp = rmap_entp->r_next; + } + break; + } + + i_err = 1; +out: + return i_err; +} + +static int +unexport_enf(nfs_export *exp, unsigned char type) +{ + struct nfsctl_enf enfarg; + int i_err; + + switch(type) { + case ENF_TRMAP: + case ENF_TCLIST: + break; + default: + i_err = 0; + goto out; + } + + /* ne_client must be the actual FQDN! */ + strncpy(enfarg.ne_client, exp->m_client->m_hostname, sizeof(enfarg.ne_client)); + strncpy(enfarg.ne_path, exp->m_export.e_path, sizeof(enfarg.ne_path)); + + enfarg.ne_func = ENF_FLUSH; + enfarg.ne_type = type; + + i_err = nfsenf(&(enfarg)); + if(i_err < 0) { + perror("nfsenf"); + i_err = 0; + goto out; + } + + i_err = 1; +out: + return i_err; } Index: enf/src/nfs-utils/0.3.3/support/include/exportfs.h diff -u enf/src/nfs-utils/0.3.3/support/include/exportfs.h:1.1.1.1 enf/src/nfs-utils/0.3.3/support/include/exportfs.h:1.2 --- enf/src/nfs-utils/0.3.3/support/include/exportfs.h:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/support/include/exportfs.h Fri Oct 12 18:01:26 2001 @@ -66,6 +66,8 @@ void export_freeall(void); int export_export(nfs_export *); int export_unexport(nfs_export *); +void export_printrmaps(); +void export_printclists(); int xtab_mount_read(void); int xtab_export_read(void); Index: enf/src/nfs-utils/0.3.3/support/include/exports.h diff -u /dev/null enf/src/nfs-utils/0.3.3/support/include/exports.h:1.1 --- /dev/null Tue Mar 19 02:12:28 2002 +++ enf/src/nfs-utils/0.3.3/support/include/exports.h Sun Oct 14 22:30:41 2001 @@ -0,0 +1,12 @@ +/* include/exports.h + * + * Common routines for printing out + * range mapping and file cloaking + * information. (unparsing) + */ + +#define PR_CONSOLE 0 +#define PR_CONFIG 1 + +void print_rmaps(FILE *fd, unsigned short type, struct exportent *ep); +void print_clists(FILE *fd, unsigned short type, struct exportent *ep); Index: enf/src/nfs-utils/0.3.3/support/include/nfslib.h diff -u enf/src/nfs-utils/0.3.3/support/include/nfslib.h:1.1.1.1 enf/src/nfs-utils/0.3.3/support/include/nfslib.h:1.2 --- enf/src/nfs-utils/0.3.3/support/include/nfslib.h:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/support/include/nfslib.h Fri Oct 12 18:01:26 2001 @@ -4,6 +4,14 @@ * General support functions for NFS user-space programs. * * Copyright (C) 1995 Olaf Kirch + * + * Wed Feb 28 07:57:25 2001 + * Joseph Spadavecchia + * Nenad Dedic + * + * Added support for range mapping (created struct rmapent, + * and added struct rmapent* e_rmap to struct exportent + * */ #ifndef NFSLIB_H @@ -19,6 +27,7 @@ #include #include #include "xlog.h" +#include #ifndef _PATH_EXPORTS #define _PATH_EXPORTS "/etc/exports" @@ -51,6 +60,33 @@ CLE_MAP_UGIDD, }; +/* range mapping per export/host(s) pair is kept + * as a linked list of rmapents + */ +struct rmapent { + unsigned char r_uid:1, /* 1 for uid 0 for gid */ + r_map:1; /* 0 for squash 1 for map */ + + unsigned short r_lo; /* lower bound for range */ + unsigned short r_hi; /* upper bound for range */ + unsigned short r_mapto; /* mapping offset or squash value */ + struct rmapent* r_next; +}; + +/* file cloaking information, cloak_list, + * is kept per export/host(s) pair + * in a linked list of cloakents + */ +struct cloakent { + unsigned char c_uid:1; /* 1 for uid 0 for gid */ + + umode_t c_mask; /* cloak mask */ + unsigned short c_lo; /* lower bound for range */ + unsigned short c_hi; /* upper bound for range */ + + struct cloakent* c_next; +}; + /* * Data related to a single exports entry as returned by getexportent. * FIXME: export options should probably be parsed at a later time to @@ -72,6 +108,8 @@ int e_nsquids; int * e_sqgids; int e_nsqgids; + struct rmapent* e_rmap; /* info about range mappings */ + struct cloakent* e_clist; }; struct rmtabent { @@ -117,9 +155,15 @@ int nfsdelclient(struct nfsctl_client *clp); int nfsexport(struct nfsctl_export *exp); int nfsunexport(struct nfsctl_export *exp); + +char *enf_mkid(char *result, int size, char *hostid, char *path); +int nfsenf(struct nfsctl_enf *data); + struct nfs_fh_len * getfh_old(struct sockaddr *addr, dev_t dev, ino_t ino); struct nfs_fh_len * getfh(struct sockaddr *addr, const char *); struct nfs_fh_len * getfh_size(struct sockaddr *addr, const char *, int size); + + /* lockd. */ int lockdsvc(); Index: enf/src/nfs-utils/0.3.3/support/include/nfs/export.h diff -u enf/src/nfs-utils/0.3.3/support/include/nfs/export.h:1.1.1.1 enf/src/nfs-utils/0.3.3/support/include/nfs/export.h:1.4 --- enf/src/nfs-utils/0.3.3/support/include/nfs/export.h:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/support/include/nfs/export.h Mon Mar 11 21:51:20 2002 @@ -23,6 +23,8 @@ #define NFSEXP_CROSSMNT 0x0200 #define NFSEXP_NOSUBTREECHECK 0x0400 #define NFSEXP_NOAUTHNLM 0x0800 -#define NFSEXP_ALLFLAGS 0x0FFF +#define NFSEXP_MSNFS 0x1000 /* do silly things that MS clients expect */ +#define NFSEXP_NOCLIENTCACHE 0x2000 /* force clients not to cache to assits file cloaking */ +#define NFSEXP_ALLFLAGS 0x2FFF #endif /* _NSF_EXPORT_H */ Index: enf/src/nfs-utils/0.3.3/support/include/nfs/nfs.h diff -u enf/src/nfs-utils/0.3.3/support/include/nfs/nfs.h:1.1.1.1 enf/src/nfs-utils/0.3.3/support/include/nfs/nfs.h:1.3 --- enf/src/nfs-utils/0.3.3/support/include/nfs/nfs.h:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/support/include/nfs/nfs.h Mon Mar 11 22:13:30 2002 @@ -6,6 +6,7 @@ #include #include #include +#include #define NFS3_FHSIZE 64 #define NFS_FHSIZE 32 @@ -31,7 +32,7 @@ #define NFSCTL_DELCLIENT 2 /* Remove an NFS client. */ #define NFSCTL_EXPORT 3 /* export a file system. */ #define NFSCTL_UNEXPORT 4 /* unexport a file system. */ -#define NFSCTL_UGIDUPDATE 5 /* update a client's uid/gid map. */ +#define NFSCTL_ENF 5 /* update a client,exp uid/gid map. */ #define NFSCTL_GETFH 6 /* get an fh (used by mountd) */ #define NFSCTL_GETFD 7 /* get an fh by path (used by mountd) */ #define NFSCTL_GETFS 8 /* get an fh by path with max size (used by mountd) */ @@ -40,8 +41,6 @@ #define NFSCTL_LOCKD 0x10000 #define LOCKDCTL_SVC NFSCTL_LOCKD - - /* SVC */ struct nfsctl_svc { unsigned short svc_port; @@ -69,17 +68,63 @@ __kernel_gid_t ex_anon_gid; }; -/* UGIDUPDATE */ -struct nfsctl_uidmap { - char * ug_ident; - __kernel_uid_t ug_uidbase; - int ug_uidlen; - __kernel_uid_t * ug_udimap; - __kernel_gid_t ug_gidbase; - int ug_gidlen; - __kernel_gid_t * ug_gdimap; +#define ENF_TRMAP 0 +#define ENF_TCLIST 1 +#define ENF_MAXIDLEN NFSCLNT_IDMAX + NFS_MAXPATHLEN + +/* Enhanced NFS Features + * range map and file cloaking ioctl arguments + */ +struct nfsctl_enf { +/* functions ne_func */ +#define ENF_ADD 1 +#define ENF_DELETE 2 +#define ENF_FLUSH 3 + /* The type of information we are adding + */ + unsigned char ne_type; /* range map (ENF_TRMAP) */ + /* file cloak (ENF_TCLIST) */ + + /* This is only set for enf_add(). It the the key in the global + * def. list that uniquely identifies the /etc/exports entry + * this belongs to. It alows us to save memory by storing + * one copy of a range mapping or cloaking definition for all + * clients connected an export + */ + char ne_id[ENF_MAXIDLEN]; + + /* Used to identify an actual client and export. + * nr_client is always a FQDN, where nr_id may + * have non FQDN client portion + */ + char ne_client[NFSCLNT_IDMAX]; + char ne_path[NFS_MAXPATHLEN]; + + unsigned short ne_func:8, /* function to perform */ + ne_uid:1, /* 1 for uid map 0 for gidmap */ + ne_generic:6; /* 6 bits future features */ + + umode_t ne_mask; /*file-cloaking mask */ + /* 13 12 11 10 8 7 6 5 4 3 2 1 0 */ + /* show u g t gr gw gx or ow ox */ + union { + uid_t uid; + gid_t gid; + } u_lo; + union { + uid_t uid; + gid_t gid; + } u_hi; + + /* Below only used to add range mapping information */ + unsigned char ne_map:1; /* 1 for mapping 0 for squashing */ + union { + uid_t uid; + gid_t gid; + } u_mapto; }; + /* GETFH */ struct nfsctl_fhparm { struct sockaddr gf_addr; @@ -111,7 +156,7 @@ struct nfsctl_svc u_svc; struct nfsctl_client u_client; struct nfsctl_export u_export; - struct nfsctl_uidmap u_umap; + struct nfsctl_enf u_enf; struct nfsctl_fhparm u_getfh; struct nfsctl_fdparm u_getfd; struct nfsctl_fsparm u_getfs; @@ -119,7 +164,7 @@ #define ca_svc u.u_svc #define ca_client u.u_client #define ca_export u.u_export -#define ca_umap u.u_umap +#define ca_enf u.u_enf #define ca_getfh u.u_getfh #define ca_getfd u.u_getfd #define ca_getfs u.u_getfs @@ -130,5 +175,6 @@ struct nfs_fh_old cr_getfh; struct nfs_fh_len cr_getfs; }; + #endif /* _NFS_NFS_H */ Index: enf/src/nfs-utils/0.3.3/support/include/rpcsvc/nfs_prot.h diff -u enf/src/nfs-utils/0.3.3/support/include/rpcsvc/nfs_prot.h:1.1.1.1 enf/src/nfs-utils/0.3.3/support/include/rpcsvc/nfs_prot.h:1.2 --- enf/src/nfs-utils/0.3.3/support/include/rpcsvc/nfs_prot.h:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/support/include/rpcsvc/nfs_prot.h Fri Oct 12 18:01:26 2001 @@ -42,7 +42,8 @@ NFSERR_NOTEMPTY = 66, NFSERR_DQUOT = 69, NFSERR_STALE = 70, - NFSERR_WFLUSH = 99, + NFSERR_WFLUSH = 99, + NFSERR_NOMSG = 100009 }; typedef enum nfsstat nfsstat; #ifdef __cplusplus Index: enf/src/nfs-utils/0.3.3/support/nfs/Makefile diff -u enf/src/nfs-utils/0.3.3/support/nfs/Makefile:1.1.1.1 enf/src/nfs-utils/0.3.3/support/nfs/Makefile:1.2 --- enf/src/nfs-utils/0.3.3/support/nfs/Makefile:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/support/nfs/Makefile Fri Oct 12 18:01:26 2001 @@ -5,7 +5,8 @@ LIBNAME = libnfs.a OBJS = exports.o rmtab.o xio.o \ rpcmisc.o rpcdispatch.o xlog.o xmalloc.o wildmat.o \ - nfssvc.o nfsclient.o nfsexport.o getfh.o nfsctl.o lockdsvc.o + nfssvc.o nfsclient.o nfsexport.o getfh.o nfsctl.o lockdsvc.o \ + nfsenf.o include $(TOP)rules.mk Index: enf/src/nfs-utils/0.3.3/support/nfs/exports.c diff -u enf/src/nfs-utils/0.3.3/support/nfs/exports.c:1.1.1.1 enf/src/nfs-utils/0.3.3/support/nfs/exports.c:1.7 --- enf/src/nfs-utils/0.3.3/support/nfs/exports.c:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/support/nfs/exports.c Fri Mar 15 21:38:01 2002 @@ -1,5 +1,5 @@ /* - * support/nfs/export.c + * support/nfs/exports.c * * Parse the exports file. Derived from the unfsd implementation. * @@ -12,6 +12,11 @@ * This software maybe be used for any purpose provided * the above copyright notice is retained. It is supplied * as is, with no warranty expressed or implied. + * + * Changes: + * Wed Feb 28 13:01:08 2001 - range mapping + file cloaking + * Joseph Spadavecchia + * Nenad Dedic */ #include "config.h" @@ -27,14 +32,21 @@ #include "xmalloc.h" #include "xlog.h" #include "xio.h" +#include "exports.h" #define EXPORT_DEFAULT_FLAGS \ (NFSEXP_ASYNC|NFSEXP_READONLY|NFSEXP_ROOTSQUASH|NFSEXP_GATHERED_WRITES) +#define MAX_OPTS 262144 /* max strlen of an /etc/export entry */ +#define MAX_IDVAL 65536 /* uid_t and gid_t max value */ + static XFILE *efp = NULL; static int first; static int *squids = NULL, nsquids = 0, *sqgids = NULL, nsqgids = 0; +/* force range map option + */ +int gi_force_rmap = 0; static int getexport(char *exp, int len); static int getpath(char *path, int len); @@ -42,13 +54,175 @@ static int parsesquash(char *list, int **idp, int *lenp, char **ep); static int parsenum(char **cpp); static int parsemaptype(char *type); + static void freesquash(void); + +/* range mapping and file cloaking + */ +static int parserangemap(char *, struct rmapent *rmap); +static int parsecloaklist(char *, struct cloakent *cloak_list); +static int is_overlap(unsigned short new_lo, unsigned short new_hi, + unsigned short ok_lo, unsigned short ok_hi); + static void syntaxerr(char *msg); +/* check if range new_* overlaps with range ok_* + */ +int +is_overlap(unsigned short new_lo, unsigned short new_hi, + unsigned short ok_lo, unsigned short ok_hi) +{ + int i_ret = 1; + + if(new_lo < ok_lo) { + if(new_hi < ok_lo) { + i_ret = 0; + } + } else if(new_lo > ok_hi) { + i_ret = 0; + } + + return i_ret; +} + +/** + * Print range mapping information in format similar to /etc/exports. + * Expects to be printing in context of the entire /etc/exports entry + * where path and hostname have already been printed in the usual way. + * + * IN: + * @fd: fd to print to + * @type: style output to generate + * @ep: export to look for rmaps in + */ +void +print_rmaps(FILE *fd, unsigned short type, struct exportent *ep) +{ + int i_tab_cnt, i; + + if(!ep) { + fprintf(stderr, "ASSERT FAILED: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__); + *((char *)0) = 0; + } + + switch(type) { + case PR_CONSOLE: + case PR_CONFIG: + break; + default: + fprintf(stderr, "%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); + *((char *)0) = 0; + } + + i_tab_cnt = (strnlen(ep->e_path, sizeof(ep->e_path)) + + strnlen(ep->e_hostname, sizeof(ep->e_hostname)))/7 + 1; + + if(ep->e_rmap) { + struct rmapent *rmap_entp; + + rmap_entp = ep->e_rmap; + for(i = 0; i < i_tab_cnt; i++) { + fprintf(fd, "\t"); + } + + fprintf(fd, "range_map ="); + while(rmap_entp) { + fprintf(fd, "%s\n", (type == PR_CONSOLE) ? "": " \\"); + for(i = 0; i < i_tab_cnt; i++) { + fprintf(fd, "\t"); + } + + if(rmap_entp->r_lo != rmap_entp->r_hi) { + fprintf(fd, "%cid\t%5d\t%5d\t%-6s\t%5d", + rmap_entp->r_uid ? 'u' : 'g', + rmap_entp->r_lo, + rmap_entp->r_hi, + rmap_entp->r_map ? "map" : + "squash", + rmap_entp->r_mapto); + } else { + fprintf(fd, "%cid\t%5d\t%-6s\t%5d", + rmap_entp->r_uid ? 'u' : 'g', + rmap_entp->r_lo, + rmap_entp->r_map ? "map" : + "squash", + rmap_entp->r_mapto); + } + rmap_entp = rmap_entp->r_next; + } + } +} + +/** + * Print file cloaking information in format similar to /etc/exports. + * Expects to be printing in context of the entire /etc/exports entry + * where path and hostname have already been printed in the usual way. + * + * IN: + * @fd: fd to print to + * @type: style output to generate + * @ep: export to look for rmaps in + */ +void +print_clists(FILE *fd, unsigned short type, struct exportent *ep) +{ + int i_tab_cnt, i; + + if(!ep) { + fprintf(stderr, "ASSERT FAILED: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__); + *((char *)0) = 0; + } + + switch(type) { + case PR_CONSOLE: + case PR_CONFIG: + break; + default: + fprintf(stderr, "%s %s %d\n", __FILE__, __FUNCTION__, __LINE__); + *((char *)0) = 0; + } + + i_tab_cnt = (strnlen(ep->e_path, sizeof(ep->e_path)) + + strnlen(ep->e_hostname, sizeof(ep->e_hostname)))/7 + 1; + + if(ep->e_clist) { + struct cloakent *cloak_entp; + + cloak_entp = ep->e_clist; + for(i = 0; i < i_tab_cnt; i++) { + fprintf(fd, "\t"); + } + + fprintf(fd, "cloak_list = "); + while(cloak_entp) { + fprintf(fd, " %s\n", (type == PR_CONSOLE) ? "":"\\"); + for(i = 0; i < i_tab_cnt; i++) { + fprintf(fd, "\t"); + } + if(cloak_entp->c_lo != cloak_entp->c_hi) { + fprintf(fd, "%cid\t%c%03x\t%5d\t%5d", + cloak_entp->c_uid ? 'u' : 'g', + (cloak_entp->c_mask & 0x1000) ? '+' : '-', + cloak_entp->c_mask & 0x0777, + cloak_entp->c_lo, + cloak_entp->c_hi); + } else { + fprintf(fd, "%cid\t%c%03x\t%5d", + cloak_entp->c_uid ? 'u' : 'g', + (cloak_entp->c_mask & 0x1000) ? '+' : '-', + cloak_entp->c_mask & 0x0777, + cloak_entp->c_lo); + } + cloak_entp = cloak_entp->c_next; + } + } + +} + void setexportent(char *fname, char *type) { - if (efp) +if (efp) endexportent(); if (!fname) fname = _PATH_EXPORTS; @@ -62,7 +236,7 @@ getexportent(void) { static struct exportent ee; - char exp[512]; + char exp[MAX_OPTS]; char rpath[MAXPATHLEN+1]; char *opt, *sp; int ok; @@ -79,6 +253,8 @@ ee.e_sqgids = NULL; ee.e_nsquids = 0; ee.e_nsqgids = 0; + ee.e_rmap = NULL; + ee.e_clist = NULL; if (first || (ok = getexport(exp, sizeof(exp))) == 0) { ok = getpath(ee.e_path, sizeof(ee.e_path)); @@ -88,6 +264,7 @@ ee.m_path [sizeof (ee.m_path) - 1] = '\0'; ok = getexport(exp, sizeof(exp)); } + if (ok < 0) { xlog(L_ERROR, "expected client(options...)"); return NULL; @@ -102,12 +279,15 @@ xlog(L_WARNING, "No host name given with %s %s, suggest *%s to avoid warning", ee.e_path, exp, exp); *opt++ = '\0'; if (!(sp = strchr(opt, ')')) || sp[1] != '\0') { + syntaxerr("bad option list"); return NULL; } *sp = '\0'; if (parseopts(opt, &ee) < 0) + { return NULL; + } } else { xlog(L_WARNING, "No options for %s %s: suggest %s() to avoid warning", ee.e_path, exp, exp); } @@ -134,12 +314,15 @@ putexportent(struct exportent *ep) { FILE *fp; - int *id, i; + int *id, i, i_tab_cnt; char *esc=ep->e_path; if (!efp) return; + i_tab_cnt = (strnlen(ep->e_path, sizeof(ep->e_path)) + + strnlen(ep->e_hostname, sizeof(ep->e_hostname)))/7 + 1; + fp = efp->x_fp; for (i=0; esc[i]; i++) if (iscntrl(esc[i]) || esc[i] == '"' || esc[i] == '\\'|| isspace(esc[i])) @@ -148,33 +331,38 @@ fprintf(fp, "%c", esc[i]); fprintf(fp, "\t%s(", ep->e_hostname); - fprintf(fp, "%s,", (ep->e_flags & NFSEXP_READONLY)? "ro" : "rw"); - fprintf(fp, "%ssync,", (ep->e_flags & NFSEXP_ASYNC)? "a" : ""); - fprintf(fp, "%swdelay,", (ep->e_flags & NFSEXP_GATHERED_WRITES)? + fprintf(fp, "%s, ", (ep->e_flags & NFSEXP_READONLY)? "ro" : "rw"); + fprintf(fp, "%ssync, ", (ep->e_flags & NFSEXP_ASYNC)? "a" : ""); + fprintf(fp, "%swdelay, ", (ep->e_flags & NFSEXP_GATHERED_WRITES)? "" : "no_"); - fprintf(fp, "%shide,", (ep->e_flags & NFSEXP_CROSSMNT)? + fprintf(fp, "%shide, ", (ep->e_flags & NFSEXP_CROSSMNT)? "no" : ""); - fprintf(fp, "%ssecure,", (ep->e_flags & NFSEXP_INSECURE_PORT)? + fprintf(fp, "%ssecure, ", (ep->e_flags & NFSEXP_INSECURE_PORT)? "in" : ""); - fprintf(fp, "%sroot_squash,", (ep->e_flags & NFSEXP_ROOTSQUASH)? + fprintf(fp, "%sroot_squash, ", (ep->e_flags & NFSEXP_ROOTSQUASH)? "" : "no_"); - fprintf(fp, "%sall_squash,", (ep->e_flags & NFSEXP_ALLSQUASH)? + fprintf(fp, "%sall_squash, \\\n", (ep->e_flags & NFSEXP_ALLSQUASH)? "" : "no_"); - fprintf(fp, "%ssubtree_check,", (ep->e_flags & NFSEXP_NOSUBTREECHECK)? + + for(i = 0; i < i_tab_cnt; i++) { + fprintf(fp, "\t"); + } + + fprintf(fp, "%ssubtree_check, ", (ep->e_flags & NFSEXP_NOSUBTREECHECK)? "no_" : ""); - fprintf(fp, "%ssecure_locks,", (ep->e_flags & NFSEXP_NOAUTHNLM)? + fprintf(fp, "%ssecure_locks, ", (ep->e_flags & NFSEXP_NOAUTHNLM)? "in" : ""); fprintf(fp, "mapping="); switch (ep->e_maptype) { case CLE_MAP_IDENT: - fprintf(fp, "identity,"); + fprintf(fp, "identity, "); break; case CLE_MAP_UGIDD: - fprintf(fp, "ugidd,"); + fprintf(fp, "ugidd, "); break; case CLE_MAP_FILE: - fprintf(fp, "file,"); + fprintf(fp, "file, "); break; default: xlog(L_ERROR, "unknown mapping type for %s:%s", @@ -184,19 +372,40 @@ fprintf(fp, "squash_uids="); for (i = 0; i < ep->e_nsquids; i += 2) if (id[i] != id[i+1]) - fprintf(fp, "%d-%d,", id[i], id[i+1]); + fprintf(fp, "%d-%d, ", id[i], id[i+1]); else - fprintf(fp, "%d,", id[i]); + fprintf(fp, "%d, ", id[i]); } if ((id = ep->e_sqgids) != NULL) { fprintf(fp, "squash_gids="); for (i = 0; i < ep->e_nsquids; i += 2) if (id[i] != id[i+1]) - fprintf(fp, "%d-%d,", id[i], id[i+1]); + fprintf(fp, "%d-%d, ", id[i], id[i+1]); else - fprintf(fp, "%d,", id[i]); + fprintf(fp, "%d, ", id[i]); + } + + fprintf(fp, "%s", (ep->e_flags & NFSEXP_NOCLIENTCACHE) ? "no_client_cache, " : ""); + + /* range mapping info */ + if(ep->e_rmap) { + fprintf(fp, "\\\n"); + print_rmaps(fp, PR_CONFIG, ep); + } + + if(ep->e_clist) { + fprintf(fp, "%s\n", (ep->e_rmap) ? ", \\" : "\\"); + print_clists(fp, PR_CONFIG, ep); } - fprintf(fp, "anonuid=%d,anongid=%d)\n", ep->e_anonuid, ep->e_anongid); + + if(ep->e_rmap || ep->e_clist) { + fprintf(fp, ", \\\n"); + for(i = 0; i < i_tab_cnt; i++) { + fprintf(fp, "\t"); + } + } + + fprintf(fp, "anonuid=%d, anongid=%d)\n", ep->e_anonuid, ep->e_anongid); } void @@ -211,17 +420,43 @@ void dupexportent(struct exportent *dst, struct exportent *src) { - int n; + int n; - *dst = *src; - if ((n = src->e_nsquids) != 0) { - dst->e_squids = (int *) xmalloc(n * sizeof(int)); - memcpy(dst->e_squids, src->e_squids, n * sizeof(int)); - } - if ((n = src->e_nsqgids) != 0) { - dst->e_sqgids = (int *) xmalloc(n * sizeof(int)); - memcpy(dst->e_sqgids, src->e_sqgids, n * sizeof(int)); + struct rmapent **l, *s; + struct cloakent **cloak_entpp, *cloak_srcp; + + *dst = *src; + if ((n = src->e_nsquids) != 0) { + dst->e_squids = (int *) xmalloc(n * sizeof(int)); + memcpy(dst->e_squids, src->e_squids, n * sizeof(int)); + } + if ((n = src->e_nsqgids) != 0) { + dst->e_sqgids = (int *) xmalloc(n * sizeof(int)); + memcpy(dst->e_sqgids, src->e_sqgids, n * sizeof(int)); + } + + l = &(dst->e_rmap); + s = src->e_rmap; + + while (s) { + *l = (struct rmapent *)xmalloc(sizeof(struct rmapent)); + **l = *s; + (*l)->r_next = NULL; + l = &((*l)->r_next); + s = s->r_next; + } + + cloak_entpp = &(dst->e_clist); + cloak_srcp = src->e_clist; + + while(cloak_srcp) { + *cloak_entpp = (struct cloakent *)xmalloc(sizeof(struct cloakent)); + **cloak_entpp = *cloak_srcp; + (*cloak_entpp)->c_next = NULL; + cloak_entpp = &((*cloak_entpp)->c_next); + cloak_srcp = cloak_srcp->c_next; } + } struct exportent * @@ -237,6 +472,8 @@ ee.e_sqgids = NULL; ee.e_nsquids = 0; ee.e_nsqgids = 0; + ee.e_rmap = NULL; + ee.e_clist = NULL; if (strlen(hname) >= sizeof(ee.e_hostname)) { xlog(L_WARNING, "client name %s too long", hname); @@ -271,10 +508,15 @@ static int parseopts(char *cp, struct exportent *ep) { + struct rmapent* rmap = NULL; + struct cloakent* clist = NULL; /* cloak list */ + int i; + char *tmp, *param = NULL; squids = ep->e_squids; nsquids = ep->e_nsquids; sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids; + while (isblank(*cp)) cp++; while (*cp) { @@ -283,10 +525,38 @@ while (*cp && *cp != ',') cp++; if (*cp) { - opt[cp-optstart] = '\0'; + opt[cp - optstart] = '\0'; cp++; } + /* remove trailing spaces from option */ + for (i = strlen(opt) - 1; i >= 0 && (opt[i] == ' ' || opt[i] == '\t'); i--) { + opt[i] = opt[i+1]; + } + + + /* if of form "opt =" then remove intermediate spaces */ + if((tmp = strchr(opt, '='))) { + *tmp = '\0'; + + /* remove trailing spaces from option */ + for (i = strlen(opt) - 1; i >= 0 && opt[i] == ' '; i--) { + opt[i] = opt[i+1]; + } + + param = (tmp + 1); + + /* option names cannot have spaces in them */ + if((tmp = strchr(opt, ' '))) { + xlog(L_ERROR, + "Bad option \"%s\" in export file (no spaces allowed in option name)\n", + opt); + ep->e_flags |= NFSEXP_ALLSQUASH | NFSEXP_READONLY; + free(opt); + return -1; + } + } + /* process keyword */ if (strcmp(opt, "ro") == 0) ep->e_flags |= NFSEXP_READONLY; @@ -328,34 +598,88 @@ ep->e_flags &= ~NFSEXP_NOAUTHNLM; else if (strcmp(opt, "insecure_locks") == 0) ep->e_flags |= NFSEXP_NOAUTHNLM; - else if (strncmp(opt, "mapping=", 8) == 0) + else if (strncmp(opt, "mapping", 8) == 0) ep->e_maptype = parsemaptype(opt+8); else if (strcmp(opt, "map_identity") == 0) /* old style */ ep->e_maptype = CLE_MAP_IDENT; else if (strcmp(opt, "map_daemon") == 0) /* old style */ ep->e_maptype = CLE_MAP_UGIDD; - else if (strncmp(opt, "anonuid=", 8) == 0) + else if (strncmp(opt, "anonuid", 8) == 0) ep->e_anonuid = atoi(opt+8); - else if (strncmp(opt, "anongid=", 8) == 0) + else if (strncmp(opt, "anongid", 8) == 0) ep->e_anongid = atoi(opt+8); - else if (strncmp(opt, "squash_uids=", 12) == 0) { - if (parsesquash(opt+12, &squids, &nsquids, &cp) < 0) { + else if (strncmp(opt, "no_client_cache", 13) == 0) + ep->e_flags |= NFSEXP_NOCLIENTCACHE; + else if (strncmp(opt, "squash_uids", 12) == 0 && param) { + if (parsesquash(param, &squids, &nsquids, &cp) < 0) { free(opt); return -1; } - } else if (strncmp(opt, "squash_gids=", 12) == 0) { - if (parsesquash(opt+12, &sqgids, &nsqgids, &cp) < 0) { + } else if (!strncmp(opt, "squash_gids", 12) && param) { + if (parsesquash(param, &sqgids, &nsqgids, &cp) < 0) { free(opt); return -1; } - } else { - xlog(L_ERROR, + } else if (strncmp(opt, "range_map", 10) == 0) { + if(rmap) { + struct rmapent* rmap_tmp; + + /* cleanup range map */ + do { + rmap_tmp = rmap->r_next; + free(rmap); + rmap = rmap_tmp; + } while(rmap); + + free(opt); + + xlog(L_ERROR, + "Duplicate option \"%s\" in export file\n", + opt); + return -1; + } else if (param && strcmp(param, "") != 0) { + rmap = + (struct rmapent *)malloc(sizeof(struct rmapent)); + + if(parserangemap(param, rmap) < 0) { + free(opt); + return -1; + } + } + } else if (strncmp(opt, "cloak_list", 11) == 0) { + if(clist) { + struct cloakent* cloak_tmp; + + /* cleanup cloak_list*/ + do { + cloak_tmp = clist->c_next; + free(clist); + clist = cloak_tmp; + } while(clist); + + free(opt); + + xlog(L_ERROR, + "Duplicate option \"%s\" in export file\n", + opt); + return -1; + } else if (param && strcmp(param, "") != 0) { + clist = + (struct cloakent *)malloc(sizeof(struct cloakent)); + + if(parsecloaklist(param, clist) < 0) { + free(opt); + return -1; + } + } + } else { xlog(L_ERROR, "Unknown keyword \"%s\" in export file\n", opt); ep->e_flags |= NFSEXP_ALLSQUASH | NFSEXP_READONLY; free(opt); return -1; } + free(opt); while (isblank(*cp)) cp++; @@ -365,6 +689,8 @@ ep->e_sqgids = sqgids; ep->e_nsquids = nsquids; ep->e_nsqgids = nsqgids; + ep->e_rmap = rmap; + ep->e_clist = clist; return 1; } @@ -454,6 +780,478 @@ return CLE_MAP_IDENT; /* default */ } +/** + * Parse a range map entry. + * IN: + * @sz_buf: buffer to be parsed + * @rmap: _pre-allocated_ structure to hold range maps + * OUT: + * int error code: -1 on failure, 0 on success + */ +static int +parserangemap(char * sz_buf, struct rmapent* rmap) +{ + int i_ret; + char sz_type[16]; + char b_uid; + int i_lo; + int i_hi; + int i_mapto; + unsigned char b_map; + unsigned char b_range; + + /* for parsing buff using sscanf */ + int i_cnt; + int i_read = 0; + int i_off = 0; + int i_size; + int i_mapto_hi; + + struct rmapent *rmap_entp = rmap; + struct rmapent *rmap_loop; + + rmap_entp->r_next = NULL; + + i_ret = 0; + i_size = strlen(sz_buf); /* pray that sz_buf is zt */ + + while(i_off < i_size) { + /* SCAN the id type */ + sz_type[0] = '\0'; + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%s%n", + (char *)&(sz_type[0]), + &(i_read)); + + /* CHECK id type */ + if(i_cnt < 1) { + syntaxerr("bad range_map"); + fprintf(stderr, "missing id type\n"); + i_ret = -1; + break; + } else if(!strncmp((char *)&(sz_type[0]), "uid", sizeof(sz_type))) { + b_uid = 1; + } else if(!strncmp((char *)&(sz_type[0]), "gid", sizeof(sz_type))) { + b_uid = 0; + } + else { + syntaxerr("bad range_map"); + fprintf(stderr, "invalid id type %s\n", sz_type); + i_ret = -1; + break; + } + + i_off += i_read; + + /* SCAN lower bound */ + i_lo = 0; + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%d%n", + &(i_lo), + &(i_read)); + + /* CHECK lower bound */ + if(i_cnt < 1) { + syntaxerr("bad range_map"); + fprintf(stderr, "missing local id range\n"); + i_ret = -1; + break; + } else if(i_lo < 0 || i_lo > MAX_IDVAL) { + syntaxerr("bad range_map"); + fprintf(stderr, "invalid lower bound %d\n", i_lo); + i_ret = -1; + break; + } + + i_off += i_read; + + /* PEEK at upper bound */ + sz_type[0] = '\0'; + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%s%n", + (char *)&(sz_type[0]), + &(i_read)); + + /* CHECK if we got an range operation type */ + b_range = 1; + if(i_cnt < 1) { + syntaxerr("bad range_map"); + fprintf(stderr, "missing range operation (map, squash)\n"); + i_ret = -1; + break; + } else if(!strncmp((char *)&(sz_type[0]), "map", sizeof(sz_type))) { + b_range = 0; + } else if(!strncmp((char *)&(sz_type[0]), "squash", sizeof(sz_type))) { + b_range = 0; + } + + i_hi = i_lo; + if(b_range) { + i_hi = 0; + /* SCAN in upper bound */ + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%d%n", + &(i_hi), + &(i_read)); + + /* CHECK upper bound */ + if(i_hi < 0 || i_hi > MAX_IDVAL) { + syntaxerr("bad range_map"); + fprintf(stderr, "invalid upper bound %d\n", i_hi); + i_ret = -1; + break; + } + + /* CHECK range */ + if(i_hi < i_lo) { + syntaxerr("bad range_map"); + fprintf(stderr, "invalid local range %d %d\n", i_lo, i_hi); + i_ret = -1; + break; + } + + i_off += i_read; + } + + + /* GET range operation */ + sz_type[0] = '\0'; + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%s%n", + (char *)&(sz_type[0]), + &(i_read)); + + /* CHECK if we got an range operation type */ + if(i_cnt < 1) { + syntaxerr("bad range_map"); + fprintf(stderr, "missing range operation (map, squash)\n"); + i_ret = -1; + break; + } else if(!strncmp((char *)&(sz_type[0]), "map", sizeof(sz_type))) { + b_map = 1; + } else if(!strncmp((char *)&(sz_type[0]), "squash", sizeof(sz_type))) { + b_map = 0; + } else { + syntaxerr("bad range_map"); + fprintf(stderr, "bad range operation %s (map, squash)\n", sz_type); + i_ret = -1; + break; + } + + i_off += i_read; + + i_mapto = 0; + /* GET mapto value */ + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%d%n", + &(i_mapto), + &(i_read)); + + if(i_cnt < 1) { + syntaxerr("bad range_map"); + fprintf(stderr, "missing mapto\n"); + i_ret = -1; + break; + } + + i_off += i_read; + + /* fill in file cloaking entry */ + rmap_entp->r_uid = b_uid; + rmap_entp->r_map = b_map; + rmap_entp->r_mapto = i_mapto; + rmap_entp->r_lo = i_lo; + rmap_entp->r_hi = i_hi; + + /* overlap checking */ + for(rmap_loop = rmap; !gi_force_rmap && rmap_loop != rmap_entp; + rmap_loop = rmap_loop->r_next) { + /* check for remote overlap */ + if(rmap_entp->r_uid == rmap_loop->r_uid == 1 && + is_overlap(rmap_entp->r_lo, rmap_entp->r_hi, + rmap_loop->r_lo, rmap_loop->r_hi)) { + syntaxerr("range mapping overlap"); + + fprintf(stderr, "remote %cid overlap:\n" + "entry\t\t%cid\t%d\t%d\t%s\t%d\n" + "overlaps\t%cid\t%d\t%d\t%s\t%d\n", + (rmap_entp->r_uid) ? 'u' : 'g', + (rmap_entp->r_uid) ? 'u' : 'g', + rmap_entp->r_lo, + rmap_entp->r_hi, + (rmap_entp->r_map) ? "map" : "squash", + rmap_entp->r_mapto, + (rmap_loop->r_uid) ? 'u' : 'g', + rmap_loop->r_lo, + rmap_loop->r_hi, + (rmap_loop->r_map) ? "map" : "squash", + rmap_loop->r_mapto); + + i_ret = -1; + break; + } + + /* check for local overlap */ + i_mapto_hi = rmap_loop->r_mapto + rmap_loop->r_hi - rmap_loop->r_lo; + + if(rmap_entp->r_uid == rmap_loop->r_uid == 1 && + is_overlap(rmap_entp->r_mapto, + rmap_entp->r_mapto + rmap_entp->r_hi - rmap_entp->r_lo, + rmap_loop->r_mapto, i_mapto_hi)) { + syntaxerr("range mapping overlap"); + + fprintf(stderr, "local %cid overlap:\n" + "entry\t\t%cid\t%d\t%d\t%s\t%d\n" + "overlaps\t%cid\t%d\t%d\t%s\t%d\n", + (rmap_entp->r_uid) ? 'u' : 'g', + (rmap_entp->r_uid) ? 'u' : 'g', + rmap_entp->r_lo, + rmap_entp->r_hi, + (rmap_entp->r_map) ? "map" : "squash", + rmap_entp->r_mapto, + (rmap_loop->r_uid) ? 'u' : 'g', + rmap_loop->r_lo, + rmap_loop->r_hi, + (rmap_loop->r_map) ? "map" : "squash", + rmap_loop->r_mapto); + + + i_ret = -1; + break; + } + } + + if(i_off < i_size) { + rmap_entp->r_next = + (struct rmapent *)malloc(sizeof(struct cloakent)); + if (!(rmap_entp->r_next)) { + xlog(L_ERROR, "out of memory\n"); + i_ret = -1; + break; + } + rmap_entp = rmap_entp->r_next; + rmap_entp->r_next = NULL; + } + } + + /* clean up on error */ + if(i_ret == -1 && rmap) { + struct rmapent* rmap_tmp; + + do { + rmap_tmp = rmap; + rmap = rmap->r_next; + free(rmap_tmp); + } while(rmap); + } + + return i_ret; +} + +/** + * Parse a cloak list entry. + * IN: + * @sz_buf: buffer to be parsed + * @clist: _pre-allocated_ structure to hold the cloaking rules + * OUT: + * error code returned: -1 on error, 0 on success + */ +static int +parsecloaklist(char * sz_buf, struct cloakent* clist) +{ + int i_ret; + char sz_type[16]; + char sz_mask[5]; + char b_uid; + int i_lo; + int i_hi; + int i_mask; + unsigned char b_range, c_show; + + /* for parsing buff using sscanf */ + int i_cnt; + int i_read = 0; + int i_off = 0; + int i_size; + + struct cloakent* cloak_entp = clist; + + cloak_entp->c_next = NULL; + + i_ret = 0; + i_size = strlen(sz_buf); /* pray that sz_buf is zt */ + + while(i_off < i_size) { + /* SCAN the id type */ + sz_type[0] = '\0'; + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%s%n", + (char *)&(sz_type[0]), + &(i_read)); + + /* CHECK id type */ + if(i_cnt < 1) { + syntaxerr("bad cloak_list"); + fprintf(stderr, "missing id type\n"); + i_ret = -1; + break; + } else if(!strncmp((char *)&(sz_type[0]), "uid", sizeof(sz_type))) { + b_uid = 1; + } else if(!strncmp((char *)&(sz_type[0]), "gid", sizeof(sz_type))) { + b_uid = 0; + } + else { + syntaxerr("bad cloak_list"); + fprintf(stderr, "invalid id type %s\n", sz_type); + i_ret = -1; + break; + } + + i_off += i_read; + + sz_mask[0] = '\0'; + /* SCAN clocking behavior '+' or '-' */ + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%s%n", + (char *)&(sz_mask[0]), + &(i_read)); + + c_show = sz_mask[0]; + + /* CHECK show option */ + if(i_cnt < 1 || (c_show != '+' && c_show != '-')) { + syntaxerr("bad cloak_list"); + fprintf(stderr, + "missing mask mode: should proceed mask with '+' or '-'\n"); + i_ret = -1; + break; + } + + /* SCAN the 12-bit mask */ + i_mask = 0; + i_cnt = sscanf((char *)&(sz_mask[1]), + "%03x", + &(i_mask)); + + /* CHECK mask format ugrwxrwx */ + if(i_cnt < 1) { + syntaxerr("bad cloak_list"); + fprintf(stderr, "missing mask\n"); + i_ret = -1; + break; + } else if(i_mask & 0x888) { + syntaxerr("bad cloak_list"); + fprintf(stderr, "invalid mask: %03x\n", i_mask); + i_ret = -1; + break; + } + + i_off += i_read; + + if(c_show == '+') { + i_mask = i_mask | (1 << 12); + } + + /* SCAN lower bound */ + i_lo = 0; + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%d%n", + &(i_lo), + &(i_read)); + + /* CHECK lower bound */ + if(i_cnt < 1) { + syntaxerr("bad cloak_list"); + fprintf(stderr, "missing id range\n"); + i_ret = -1; + break; + } else if(i_lo < 0 || i_lo > MAX_IDVAL) { + syntaxerr("bad cloak_list"); + fprintf(stderr, "invalid lower bound %d\n", i_lo); + i_ret = -1; + break; + } + + i_off += i_read; + + /* LOOK for upper bound */ + sz_type[0] = '\0'; + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%s%n", + (char *)&(sz_type[0]), + &(i_read)); + + /* CHECK if we got an id type */ + b_range = 1; + if(i_cnt < 1) { + b_range = 0; + } else if(!strncmp((char *)&(sz_type[0]), "uid", sizeof(sz_type))) { + b_range = 0; + } else if(!strncmp((char *)&(sz_type[0]), "gid", sizeof(sz_type))) { + b_range = 0; + } + + i_hi = i_lo; + if(b_range) { + /* SCAN in upper bound */ + i_hi = 0; + i_cnt = sscanf((char *)&(sz_buf[i_off]), + "%d%n", + &(i_hi), + &(i_read)); + + /* CHECK upper bound */ + if(i_hi < 0 || i_hi > MAX_IDVAL) { + syntaxerr("bad cloak_list"); + fprintf(stderr, "invalid upper bound %d\n", i_hi); + i_ret = -1; + break; + } + + /* CHECK range */ + if(i_hi < i_lo) { + syntaxerr("bad cloak_list"); + fprintf(stderr, "invalid range %d %d\n", i_lo, i_hi); + i_ret = -1; + break; + } + + i_off += i_read; + } + + /* fill in file cloaking entry */ + cloak_entp->c_uid = b_uid; + cloak_entp->c_mask = i_mask; + cloak_entp->c_lo = i_lo; + cloak_entp->c_hi = i_hi; + + if(i_off < i_size) { + cloak_entp->c_next = + (struct cloakent *)malloc(sizeof(struct cloakent)); + if (!(cloak_entp->c_next)) { + xlog(L_ERROR, "out of memory\n"); + i_ret = -1; + break; + } + cloak_entp = cloak_entp->c_next; + cloak_entp->c_next = NULL; + } + } + + /* clean up on error */ + if(i_ret == -1 && clist) { + struct cloakent* cloak_tmp; + + do { + cloak_tmp = clist; + clist = clist->c_next; + free(cloak_tmp); + } while(clist); + } + + return i_ret; +} + static int getpath(char *path, int len) { @@ -461,14 +1259,57 @@ return xgettok(efp, 0, path, len); } + +/* [JES] modified to return multi-line export entries. + * The returned entry has new lines, white space stripped. + */ static int getexport(char *exp, int len) { - int ok; + int ok = 0; + int b_lcont = 0; /* line continuation boolean */ + int i = 0; xskip(efp, " \t"); - if ((ok = xgettok(efp, 0, exp, len)) < 0) - xlog(L_ERROR, "error parsing export entry"); + + b_lcont = 0; + while(i++ < len && (*exp = xgetc(efp))) { + if(b_lcont && *exp != '\n') { + xlog(L_ERROR, "[1] error parsing export entry\n"); + return -1; + } + + + if(*exp == ')') { + break; + } else if(*exp == '\\') { + b_lcont = 1; + exp--; + xskip(efp, " \t"); + } else if(*exp == '\n') { + if(b_lcont) { + b_lcont = 0; + } else { + if(ok == 0) { + break; + } + + xlog(L_ERROR, "[2] error parsing export entry\n"); + return -1; + } + exp--; + } + ok++; + exp++; + } + + if(i++ >= len) { + fprintf(stderr, "export entry too large\n"); + return -1; + } + + *(exp + 1) = '\0'; + return ok; } Index: enf/src/nfs-utils/0.3.3/support/nfs/nfsenf.c diff -u /dev/null enf/src/nfs-utils/0.3.3/support/nfs/nfsenf.c:1.1 --- /dev/null Tue Mar 19 02:12:28 2002 +++ enf/src/nfs-utils/0.3.3/support/nfs/nfsenf.c Sun Oct 14 22:30:41 2001 @@ -0,0 +1,38 @@ +/* + * support/nfs/nfsenf.c + * + * Add, delete, or flush range mapping + * and file cloaking info in knfsd + * Mon Mar 5 02:27:46 2001 + * + * Joseph Spadavecchia + * Nenad Dedic + */ + +#include "config.h" + +#include +#include "nfslib.h" + +char *enf_mkid(char *result, int size, char *path, char *hostid) +{ + if (size < NFSCLNT_IDMAX + NFS_MAXPATHLEN) { + return NULL; + } + strncpy(result, path, NFS_MAXPATHLEN); + strncat(result, hostid, NFSCLNT_IDMAX); + result[NFSCLNT_IDMAX + NFSCLNT_IDMAX] = '\0'; + return result; +} + +/* Add range mapping or file cloaking information. + */ +int +nfsenf(struct nfsctl_enf *data) +{ + struct nfsctl_arg arg; + + arg.ca_version = NFSCTL_VERSION; + memcpy(&(arg.ca_enf), data, sizeof(arg.ca_enf)); + return nfsctl(NFSCTL_ENF, &arg, NULL); +} Index: enf/src/nfs-utils/0.3.3/utils/exportfs/exportfs.c diff -u enf/src/nfs-utils/0.3.3/utils/exportfs/exportfs.c:1.1.1.1 enf/src/nfs-utils/0.3.3/utils/exportfs/exportfs.c:1.4 --- enf/src/nfs-utils/0.3.3/utils/exportfs/exportfs.c:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/utils/exportfs/exportfs.c Mon Mar 11 21:51:20 2002 @@ -6,10 +6,17 @@ * Copyright (C) 1995, 1996, 1997 Olaf Kirch * * Extensive changes, 1999, Neil Brown + * + * Tue Mar 6 13:33:24 2001 + * Joseph Spadavecchia + * Nenad Dedic + * + * added range mapping and file cloaking support */ #include "config.h" +#include #include #include #include @@ -22,6 +29,7 @@ #include "exportfs.h" #include "xmalloc.h" #include "xlog.h" +#include "exports.h" static void export_all(int verbose); static void exportfs(char *arg, char *options, int verbose); @@ -31,6 +39,7 @@ static void error(nfs_export *exp, int err); static void usage(void); +extern int gi_force_rmap; int main(int argc, char **argv) @@ -45,7 +54,7 @@ xlog_open("exportfs"); - while ((c = getopt(argc, argv, "aio:ruv")) != EOF) { + while ((c = getopt(argc, argv, "faio:ruv")) != EOF) { switch(c) { case 'a': f_all = 1; @@ -56,6 +65,9 @@ case 'o': options = optarg; break; + case 'f': + gi_force_rmap = 1; + break; case 'r': f_reexport = 1; f_all = 1; @@ -314,47 +326,75 @@ hname = ""; else hname = ep->e_hostname; + if (strlen(ep->e_path) > 14) - printf("%-14s\n\t\t%s", ep->e_path, hname); + printf("%s\n\t\t%s", ep->e_path, hname); else - printf("%-14s\t%s", ep->e_path, hname); + printf("%s\t%s", ep->e_path, hname); + if (!verbose) { printf("\n"); continue; } + c = '('; + if (ep->e_flags & NFSEXP_READONLY) c = dumpopt(c, "ro"); else - c = dumpopt(c, "rw"); + c = dumpopt(c, "rw"); + if (ep->e_flags & NFSEXP_ASYNC) - c = dumpopt(c, "async"); + c = dumpopt(c, " async"); + if (ep->e_flags & NFSEXP_GATHERED_WRITES) - c = dumpopt(c, "wdelay"); + c = dumpopt(c, " wdelay"); + if (ep->e_flags & NFSEXP_CROSSMNT) - c = dumpopt(c, "nohide"); + c = dumpopt(c, " nohide"); + if (ep->e_flags & NFSEXP_INSECURE_PORT) - c = dumpopt(c, "insecure"); + c = dumpopt(c, " insecure"); + if (ep->e_flags & NFSEXP_ROOTSQUASH) - c = dumpopt(c, "root_squash"); + c = dumpopt(c, " root_squash"); else - c = dumpopt(c, "no_root_squash"); + c = dumpopt(c, " no_root_squash"); + if (ep->e_flags & NFSEXP_ALLSQUASH) - c = dumpopt(c, "all_squash"); + c = dumpopt(c, " all_squash"); + if (ep->e_flags & NFSEXP_NOSUBTREECHECK) - c = dumpopt(c, "no_subtree_check"); + c = dumpopt(c, " no_subtree_check"); + if (ep->e_flags & NFSEXP_NOAUTHNLM) - c = dumpopt(c, "insecure_locks"); + c = dumpopt(c, " insecure_locks"); + if (ep->e_maptype == CLE_MAP_UGIDD) - c = dumpopt(c, "mapping=ugidd"); + c = dumpopt(c, " mapping = ugidd"); else if (ep->e_maptype == CLE_MAP_FILE) - c = dumpopt(c, "mapping=file"); + c = dumpopt(c, " mapping = file"); + if (ep->e_anonuid != -2) - c = dumpopt(c, "anonuid=%d", ep->e_anonuid); + c = dumpopt(c, " anonuid = %d", ep->e_anonuid); + if (ep->e_anongid != -2) - c = dumpopt(c, "anongid=%d", ep->e_anongid); + c = dumpopt(c, " anongid = %d", ep->e_anongid); + + if (ep->e_flags & NFSEXP_NOCLIENTCACHE) + c = dumpopt(c, " no_client_cache"); + + if(ep->e_rmap) { + printf("%s", (c == '(') ? "" : ", \n"); + print_rmaps(stdout, PR_CONSOLE, ep); + } + + if(ep->e_clist) { + printf("%s", (c == '(') ? "" : ", \n"); + print_clists(stdout, PR_CONSOLE, ep); + } - printf("%c\n", (c != '(')? ')' : ' '); + printf("%s\n", ")"); } } } @@ -369,6 +409,6 @@ static void usage(void) { - fprintf(stderr, "usage: exportfs [-aruv] [host:/path]\n"); + fprintf(stderr, "usage: exportfs [-afruv] [host:/path]\n"); exit(1); } Index: enf/src/nfs-utils/0.3.3/utils/exportfs/exportfs.man diff -u enf/src/nfs-utils/0.3.3/utils/exportfs/exportfs.man:1.1.1.1 enf/src/nfs-utils/0.3.3/utils/exportfs/exportfs.man:1.2 --- enf/src/nfs-utils/0.3.3/utils/exportfs/exportfs.man:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/utils/exportfs/exportfs.man Fri Oct 12 18:01:26 2001 @@ -7,11 +7,11 @@ .SH NAME exportfs \- maintain list of NFS exported file systems .SH SYNOPSIS -.BI "/usr/sbin/exportfs [-avi] [-o " "options,.." "] [" "client:/path" " ..] +.BI "/usr/sbin/exportfs [-avif] [-o " "options,.." "] [" "client:/path" " ..] .br .BI "/usr/sbin/exportfs -r [-v]" .br -.BI "/usr/sbin/exportfs [-av] -u [" "client:/path" " ..] +.BI "/usr/sbin/exportfs [-avf] -u [" "client:/path" " ..] .br .BI "/usr/sbin/exportfs [-v] .br @@ -71,7 +71,6 @@ which are deleted from /etc/exports, and remove any entries from the kernel export table which are no longer valid. .TP -.TP .B -u Unexport one or more directories. .TP @@ -79,6 +78,12 @@ Be verbose. When exporting or unexporting, show what's going on. When displaying the current export list, also display the list of export options. +.TP +.B -f +Force export entries with conflicting range mapping or file cloaking definitions +to be exported. In such a case an entry is entered with two operations +defined for the same range. When this flag is used the conflict will be ignored +and the last operation defined on the range is used. .SH DISCUSSION .\" -------------------- Exporting Directories -------------------- .SS Exporting Directories Index: enf/src/nfs-utils/0.3.3/utils/exportfs/exports.man diff -u enf/src/nfs-utils/0.3.3/utils/exportfs/exports.man:1.1.1.1 enf/src/nfs-utils/0.3.3/utils/exportfs/exports.man:1.8 --- enf/src/nfs-utils/0.3.3/utils/exportfs/exports.man:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/utils/exportfs/exports.man Mon Mar 11 21:51:20 2002 @@ -26,6 +26,7 @@ it should be quoted using double-quotes. You can also specify spaces or any other unusual characters in the export path name using a backslash followed by the character code as 3 octal digits. +- .PP .SS Machine Name Formats NFS clients may be specified in a number of ways: @@ -54,7 +55,6 @@ contiguous mask length (for example, either `/255.255.252.0' or `/22' appended to the network base address result in identical subnetworks with 10 bits of host). -.TP '''.B =public '''This is a special ``hostname'' that identifies the given directory name '''as the public root directory (see the section on WebNFS in @@ -79,7 +79,7 @@ understands the following export options: .TP .IR secure "\*d -This option requires that requests originate on an internet port less +This option requires that requests originate on an Internet port less than IPPORT_RESERVED (1024). This option is on by default. To turn it off, specify .IR insecure . @@ -107,7 +107,7 @@ progress or may arrive soon. This allows multiple write requests to be committed to disc with the one operation which can improve performance. If an NFS server received mainly small unrelated -requests, this behaviour could actually reduce performance, so +requests, this behavior could actually reduce performance, so .IR no_wdelay is available to turn it off. The default can be explicitly requested with the @@ -124,7 +124,7 @@ Setting the .I nohide option on a filesystem causes it not to be hidden, and an -appropriately authorised client will be able to move from the parent to +appropriately authorized client will be able to move from the parent to that filesystem without noticing the change. However, some NFS clients do not cope well with this situation as, for @@ -194,12 +194,22 @@ the old implementations. Use this flag if you find that you can only lock files which are world readable. -The default behaviour of requiring authentication for NLM requests can +The default behavior of requiring authentication for NLM requests can be explicitly requested with either of the synonymous .IR auth_nlm , or .IR secure_locks . +.TP +.IR no_client_cache +This option causes the NFS server to force NFS clients that have +file_cloaking defined for them to disable their client-side caching of +dentries. This option should be used in conjunction with the +cloak_list option when using file-cloaking for multi-user clients. +This was left as an non-default option to improve performance. In the +common case where an NFS volume is exported to a single-user client +workstation client-side caching does not need to be disabled. + '''.TP '''.I noaccess '''This makes everything below the directory inaccessible for the named @@ -256,6 +266,11 @@ Finally, you can map all user requests to the anonymous uid by specifying the .IR all_squash " option. +.PP +Arbitrary id mappings for any set of users and groups can be made +with the range_map option. This option is a superset of the root_squash, no_root_squash, +and all_squash options. This feature eliminates the requirement that +the same uids and gids are used on the client and server. '''.PP '''For the benefit of installations where uids differ between different '''machines, @@ -379,10 +394,84 @@ all requests appear to be from one user. As an example, consider the export entry for .B /home/joe -in the example section below, which maps all requests to uid 150 (which +in example 1 below, which maps all requests to uid 150 (which is supposedly that of user joe). -.IP -.SH EXAMPLE +.TP +.IR range_map +This option allows the specification of arbitrary uid and gid mappings. +Range-mapping takes precedence over root_squash and all_squash. However, +it can be used in conjunction with root_squash and all_squash. For example, +in example 2 below the export entry for +.B /home/ljilja +uses the all_squash option +to specify that all uids except those specified by the range-mapping +definition are to be squashed. The following shows the format for a range_map definition: +.nf + + := range_map = {} + := (id|gid) [] (map|squash) + +.fi +where is the remote-host id lower bound, is the remote-host id +upper bound >= , and is the localhost mapped range lower bound. +If is not specified is set to . If map is chosen from +(map|squash) then the resulting definition will map range up to to +range up to + - . If squash is selected then the +resulting definition will map each id from up to to . +.SS File-Cloaking +File-cloaking is a pliable tool for restricting visibility and access +to exported files. In file-cloaking if a file is not visible then the +user does not have access to it. However, if a file is visible to a +given user this does not imply the user has access to it. Standard +UNIX permissions still apply. +.TP +.IR cloak_list +File-cloaking is specified with the cloak_list option, which has a similar +format to the range_map option. The following shows the format for a file +cloaking definition: +.nf + + := cloak_list = {} + := (uid|gid) [] + +.fi +where range up to is the localhost id range for the files to +cloaked. If is not specified then is set to . The + is a 9-bit bitmask in octal preceeded by either a '+' or '-'. +When the mask is proceeded by a '-' it specifies when file-cloaking is +to be done. When the mask is proceeded by a '+' it specifies when +file-cloaking is not to be done. The has the following format: +.nf + +(+|-)ugtrwxrwx + +.fi +For a given file and id between and visibility and access to +the file is determined by the following three checks: + +Check 1: If the id making the request is the file's owner then the AND +is not performed and the file is visible. Otherwise perform check 2. + +Check 2: If id is a not member of the group on the file then goto +check 3. Otherwise, the middle 3 bits are ANDed with the group rwx +protection bits of the file. If the mask is proceeded by '+' and the +result of the AND is non-zero then the file is visible. If the mask +is proceeded by '+' and the result of the AND is zero then the file is +hidden. If the mask is proceeded by '-' and the result of the AND is +non-zero then the file is hidden. If the mask is proceeded by '-' and +the result of the AND is zero then the file is visible. + +Check 3: The last 3 bits (other rwx) and the first 3 bits (ugt) are +ANDed with the other rwx protection bits and the setuid, setgid, and +sticky bit of the file. If the mask is proceeded by '+' and the +result of the AND is non-zero then the file is visible. If the mask +is proceeded by '+' and the result of the AND is zero then the file is +hidden. If the mask is proceeded by '-' and the result of the AND is +non-zero then the file is hidden. If the mask is proceeded by '-' and +the result of the AND is zero then the file is visible. + +.PP +.SH EXAMPLE 1 .PP .nf .ta +3i @@ -392,9 +481,9 @@ /usr *.local.domain(ro) @trusted(rw) /home/joe pc001(rw,all_squash,anonuid=150,anongid=100) /pub (ro,insecure,all_squash) -'''/pub/private (noaccess) .fi .PP + The first line exports the entire filesystem to machines master and trusty. In addition to write access, all uid squashing is turned off for host trusty. The second and third entry show examples for wildcard hostnames @@ -420,6 +509,45 @@ '''.I /usr/X11R6 '''entry apply. This is also true when the latter is a wildcard or netgroup '''entry. +.SH EXAMPLE 2 +.PP +.nf +# sample /etc/exports file with range-mapping and file-cloaking +# definitions +/projects master(rw, range_map = \\ + uid 0 squash -2 \\ + gid 0 squash -2) +/home/joe pc100(rw, range_map = \\ + uid 0 -1 squash 150 \\ + gid 0 -1 squash 100) +/home/ljilja pclinux(rw, all_squash, range_map = \\ + uid 0 map 0 \\ + uid 2300 2350 map 1000 \\ + gid 500 map 100) +/home/u1 *.local.domain(rw, all_squash, \\ + cloak_list = \\ + uid +000 0 \\ + gid -004 1604, \\ + range_map = \\ + uid 1000 2000 map 2300 \\ + gid 100 110 map 319) +/pub a1.local.domain(rw, cloak_list = \\ + uid -400 1 -1) +.fi + +The /projects export shows how the range_map option can be used to +achieve the same result as the root_squash option. The /home/joe +export is exported exactly as in Example 1 above. The /home/ljilja +export shows how all_squash can be used in conjunction with range_map. +All uids and gids not specified in range_map definition are squashed +to anonuid and anongid. The /home/u1 export shows two things being +done with file-cloaking: First, file-cloaking is specified for files +owned by root so that they are only visible and accessible to root. +Second, world readable files with group 1604 ownership are hidden from +all users except the owners of the files themselves. The last example +shows how to cloak SETUID files. + +'''/pub/private (noaccess) .SH FILES /etc/exports '''.SH DIAGNOSTICS @@ -428,3 +556,4 @@ '''host is reported at that time, but often not all hosts are not yet known '''to named(8) at boot time, thus as hosts are found they are reported '''with the same syslogd(8) parameters. +\" LocalWords: joe uid gid Index: enf/src/nfs-utils/0.3.3/utils/mountd/mountd.c diff -u enf/src/nfs-utils/0.3.3/utils/mountd/mountd.c:1.1.1.1 enf/src/nfs-utils/0.3.3/utils/mountd/mountd.c:1.2 --- enf/src/nfs-utils/0.3.3/utils/mountd/mountd.c:1.1.1.1 Wed Oct 10 15:46:39 2001 +++ enf/src/nfs-utils/0.3.3/utils/mountd/mountd.c Fri Oct 12 18:01:26 2001 @@ -72,8 +72,12 @@ struct nfs_fh_len *fh; xlog(D_CALL, "MNT1(%s) called", *path); + if ((fh = get_rootfh(rqstp, path, &res->fhs_status, 0)) != NULL) memcpy(&res->fhstatus_u.fhs_fhandle, fh->fh_handle, 32); + + xlog(L_NOTICE, "get_rootfh() NFSV3 done"); + return 1; } @@ -109,6 +113,8 @@ if (!(exp = auth_authenticate("unmount", sin, p))) { return 1; } + + export_unexport(exp); mountlist_del(exp, p); export_reset (exp); return 1; @@ -218,7 +224,7 @@ struct nfs_fh_len *fh; xlog(D_CALL, "MNT3(%s) called", *path); - if ((fh = get_rootfh(rqstp, path, (int *) &res->fhs_status, 1)) != NULL) { + if ((fh = get_rootfh(rqstp, path, (int *) &res->fhs_status, 1)) != NULL) { struct mountres3_ok *ok = &res->mountres3_u.mountinfo; ok->fhandle.fhandle3_len = fh->fh_size; @@ -226,6 +232,8 @@ ok->auth_flavors.auth_flavors_len = 2; ok->auth_flavors.auth_flavors_val = flavors; } + + xlog(L_NOTICE, "get_rootfh() NFS3 DONE $"); return 1; } @@ -251,6 +259,8 @@ p = rpath; } + xlog(L_NOTICE, "get_rootfh()"); + /* Now authenticate the intruder... */ if (!(exp = auth_authenticate("mount", sin, p))) { *error = NFSERR_ACCES; @@ -266,7 +276,7 @@ *error = NFSERR_NOTDIR; } else { struct nfs_fh_len *fh; - + xlog(L_NOTICE, "will export_export() (%d)", exp->m_exported); if (exp->m_exported<1) export_export(exp); if (!exp->m_xtabent) @@ -304,6 +314,9 @@ nfs_export *exp; int i; + + xlog(L_NOTICE, "get_exportlist"); + if (!auth_reload() && elist) return elist; @@ -383,6 +396,7 @@ } } + xlog(L_NOTICE, "get_exportlist end"); return elist; }