Add secinfo processing. From: Fred Isaman Signed-off-by: Fred Isaman Add secinfo processing. --- support/include/nfslib.h | 6 ++ support/nfs/exports.c | 142 ++++++++++++++++++++++++++++++++++++++++++++- utils/exportfs/exportfs.c | 3 + utils/mountd/cache.c | 15 +++++ 4 files changed, 162 insertions(+), 4 deletions(-) diff --git a/support/include/nfslib.h b/support/include/nfslib.h index 8f95209..7235523 100644 --- a/support/include/nfslib.h +++ b/support/include/nfslib.h @@ -57,6 +57,9 @@ enum cle_maptypes { CLE_MAP_UGIDD, }; +extern char *secflavor_name[]; +#define SECFLAVOR_COUNT 4 + /* * Data related to a single exports entry as returned by getexportent. * FIXME: export options should probably be parsed at a later time to @@ -82,6 +85,8 @@ struct exportent { char * e_mountpoint; int e_fslocmethod; char * e_fslocdata; + int e_secinfo_order[SECFLAVOR_COUNT+1]; + int e_secinfo_flags[SECFLAVOR_COUNT]; }; struct rmtabent { @@ -95,6 +100,7 @@ struct rmtabent { */ void setexportent(char *fname, char *type); struct exportent * getexportent(int,int); +void secinfo_show(FILE *fp, struct exportent *ep); void putexportent(struct exportent *xep); void endexportent(void); struct exportent * mkexportent(char *hname, char *path, char *opts); diff --git a/support/nfs/exports.c b/support/nfs/exports.c index 4f236ff..e7b8d00 100644 --- a/support/nfs/exports.c +++ b/support/nfs/exports.c @@ -50,6 +50,10 @@ static int parsenum(char **cpp); static int parsemaptype(char *type); static void freesquash(void); static void syntaxerr(char *msg); +static unsigned int parse_flavors(char *str, struct exportent *ep); +static int secinfo_default(struct exportent *ep); +static void setflags(int mask, unsigned int *ap, struct exportent *ep); +static void clearflags(int mask, unsigned int *ap, struct exportent *ep); void setexportent(char *fname, char *type) @@ -96,6 +100,7 @@ getexportent(int fromkernel, int fromexp ee.e_mountpoint = NULL; ee.e_fslocmethod = FSLOC_NONE; ee.e_fslocdata = NULL; + ee.e_secinfo_order[0] = -1; ee.e_nsquids = 0; ee.e_nsqgids = 0; @@ -158,6 +163,19 @@ getexportent(int fromkernel, int fromexp } void +secinfo_show(FILE *fp, struct exportent *ep) +{ + int *p1, *p2; + for (p1=ep->e_secinfo_order; *p1>=0; p1=p2) { + fprintf(fp, ",sec=%s", secflavor_name[*p1]); + for (p2=p1+1; (*p2>=0) && (ep->e_secinfo_flags[*p1]==ep->e_secinfo_flags[*p2]); p2++) { + fprintf(fp, ":%s", secflavor_name[*p2]); + } + fprintf(fp, ",%s", (ep->e_secinfo_flags[*p1] & NFSEXP_READONLY)? "ro" : "rw"); + } +} + +void putexportent(struct exportent *ep) { FILE *fp; @@ -175,7 +193,6 @@ putexportent(struct exportent *ep) 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)? "" : "no_"); @@ -248,7 +265,9 @@ putexportent(struct exportent *ep) else fprintf(fp, "%d,", id[i]); } - fprintf(fp, "anonuid=%d,anongid=%d)\n", ep->e_anonuid, ep->e_anongid); + fprintf(fp, "anonuid=%d,anongid=%d", ep->e_anonuid, ep->e_anongid); + secinfo_show(fp, ep); + fprintf(fp, ")\n"); } void @@ -295,6 +314,7 @@ mkexportent(char *hname, char *path, cha ee.e_squids = NULL; ee.e_sqgids = NULL; ee.e_mountpoint = NULL; + ee.e_secinfo_order[0] = -1; ee.e_nsquids = 0; ee.e_nsqgids = 0; @@ -334,6 +354,9 @@ parseopts(char *cp, struct exportent *ep int had_subtree_opt = 0; char *flname = efname?efname:"command line"; int flline = efp?efp->x_line:0; + int *p; + unsigned int active = 0; + int secmask = NFSEXP_READONLY; /* options that can vary per flavor */ squids = ep->e_squids; nsquids = ep->e_nsquids; sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids; @@ -356,9 +379,9 @@ parseopts(char *cp, struct exportent *ep /* process keyword */ if (strcmp(opt, "ro") == 0) - ep->e_flags |= NFSEXP_READONLY; + setflags(NFSEXP_READONLY, &active, ep); else if (strcmp(opt, "rw") == 0) - ep->e_flags &= ~NFSEXP_READONLY; + clearflags(NFSEXP_READONLY, &active, ep); else if (!strcmp(opt, "secure")) ep->e_flags &= ~NFSEXP_INSECURE_PORT; else if (!strcmp(opt, "insecure")) @@ -470,6 +493,10 @@ bad_option: } else if (strncmp(opt, "replicas=", 9) == 0) { ep->e_fslocmethod = FSLOC_REPLICA; ep->e_fslocdata = strdup(opt+9); + } else if (strncmp(opt, "sec=", 4) == 0) { + active = parse_flavors(opt+4, ep); + if (!active) + goto bad_option; } else { xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n", flname, flline, opt); @@ -481,6 +508,12 @@ bad_option: cp++; } + if (!active) + active = secinfo_default(ep); + for (p=ep->e_secinfo_order; *p>=0; p++) + ep->e_secinfo_flags[*p] |= (ep->e_flags & ~secmask); + /* If did not use sec= option, ensure e_flags is backward compatible */ + ep->e_flags = ep->e_secinfo_flags[ep->e_secinfo_order[0]]; ep->e_squids = squids; ep->e_sqgids = sqgids; ep->e_nsquids = nsquids; @@ -609,3 +642,104 @@ syntaxerr(char *msg) efname, efp?efp->x_line:0, msg); } +char *secflavor_name[SECFLAVOR_COUNT] = { "sys", + "krb5", + "krb5i", + "krb5p" +}; + +static void +secinfo_addflavor(int bit, struct exportent *ep) +{ + int *p; + for (p=ep->e_secinfo_order; *p>=0; p++) { + if (*p == bit) + return; + } + *p++ = bit; + *p = -1; + ep->e_secinfo_flags[bit] = 0; +} + +static int +secinfo_nameindex(char *name) +{ + int i; + for (i=0; ie_hostname. */ +static int +secinfo_default(struct exportent *ep) +{ + int i=-1; + if (strncmp(ep->e_hostname, "gss/", 4) == 0) { + i = secinfo_nameindex(ep->e_hostname + 4); + if (i < 0) + xlog(L_WARNING, "unknown flavor %s\n", ep->e_hostname); + } + /* Default to auth_sys */ + if (i < 0) + i = secinfo_nameindex("sys"); + secinfo_addflavor(i, ep); + return 1<e_secinfo_flags[flavor] |= mask; + flavor++; + active >>= 1; + } +} + +/* Clears the bits in @mask for the appropriate security flavor flags. */ +static void +clearflags(int mask, unsigned int *ap, struct exportent *ep) +{ + int active, flavor=0; + if (!*ap) + *ap = secinfo_default(ep); + active = *ap; + while (active) { + if (active & 1) + ep->e_secinfo_flags[flavor] &= ~mask; + flavor++; + active >>= 1; + } +} diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c index 4260591..cc4ed99 100644 --- a/utils/exportfs/exportfs.c +++ b/utils/exportfs/exportfs.c @@ -376,10 +376,12 @@ dump(int verbose) continue; } c = '('; + /* if (ep->e_flags & NFSEXP_READONLY) c = dumpopt(c, "ro"); else c = dumpopt(c, "rw"); + */ if (ep->e_flags & NFSEXP_ASYNC) c = dumpopt(c, "async"); if (ep->e_flags & NFSEXP_GATHERED_WRITES) @@ -429,6 +431,7 @@ dump(int verbose) c = dumpopt(c, "fsloc=stub"); break; } + secinfo_show(stdout, ep); printf("%c\n", (c != '(')? ')' : ' '); } } diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c index ac75be7..2ff19b5 100644 --- a/utils/mountd/cache.c +++ b/utils/mountd/cache.c @@ -263,6 +263,20 @@ static void write_fsloc(FILE *f, struct release_replicas(servers); } +static void write_secinfo(FILE *f, struct exportent *ep) +{ + int *p; + qword_print(f, "secinfo"); + for (p=ep->e_secinfo_order; *p>=0; p++) + ; /* Do nothing */ + qword_printint(f, p - ep->e_secinfo_order); + for (p=ep->e_secinfo_order; *p>=0; p++) { + qword_print(f, secflavor_name[*p]); + qword_printint(f, ep->e_secinfo_flags[*p]); + } + +} + void nfsd_export(FILE *f) { /* requests are: @@ -320,6 +334,7 @@ void nfsd_export(FILE *f) qword_printint(f, found->m_export.e_anongid); qword_printint(f, found->m_export.e_fsid); write_fsloc(f, &found->m_export, path); + write_secinfo(f, &found->m_export); mountlist_add(dom, path); } qword_eol(f);