Add secinfo processing. From: Fred Isaman <iisaman@citi.umich.edu> Signed-off-by: Fred Isaman <iisaman@citi.umich.edu> Add secinfo processing. --- support/include/nfslib.h | 6 ++ support/nfs/exports.c | 145 ++++++++++++++++++++++++++++++++++++++++++++- utils/exportfs/exportfs.c | 3 + utils/mountd/cache.c | 14 ++++ 4 files changed, 164 insertions(+), 4 deletions(-) diff --git a/support/include/nfslib.h b/support/include/nfslib.h index c085029..6d7743d 100644 --- a/support/include/nfslib.h +++ b/support/include/nfslib.h @@ -57,6 +57,9 @@ enum cle_maptypes { CLE_MAP_UGIDD, }; +#define SECFLAVOR_COUNT 7 +extern char *secflavor_name[SECFLAVOR_COUNT]; + /* * Data related to a single exports entry as returned by getexportent. * FIXME: export options should probably be parsed at a later time to @@ -83,6 +86,8 @@ struct exportent { int e_fslocmethod; char * e_fslocdata; char * e_uuid; + int e_secinfo_order[SECFLAVOR_COUNT+1]; + int e_secinfo_flags[SECFLAVOR_COUNT]; }; struct rmtabent { @@ -96,6 +101,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 294e1c9..af9ab2f 100644 --- a/support/nfs/exports.c +++ b/support/nfs/exports.c @@ -51,6 +51,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) @@ -102,6 +106,7 @@ getexportent(int fromkernel, int fromexp def_ee.e_mountpoint = NULL; def_ee.e_fslocmethod = FSLOC_NONE; def_ee.e_fslocdata = NULL; + def_ee.e_secinfo_order[0] = -1; def_ee.e_nsquids = 0; def_ee.e_nsqgids = 0; @@ -182,6 +187,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; @@ -199,7 +217,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_"); @@ -276,7 +293,9 @@ #endif 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 @@ -325,6 +344,7 @@ mkexportent(char *hname, char *path, cha 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; ee.e_uuid = NULL; @@ -376,6 +396,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; @@ -398,9 +421,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")) @@ -522,6 +545,10 @@ #endif } 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); @@ -533,6 +560,12 @@ #endif 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; @@ -663,3 +696,107 @@ syntaxerr(char *msg) efname, efp?efp->x_line:0, msg); } +char *secflavor_name[SECFLAVOR_COUNT] = { "sys", + "krb5", + "krb5i", + "krb5p", + "spkm3", + "spkm3i", + "spkm3p" +}; + +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; i<SECFLAVOR_COUNT; i++) { + if (strcmp(secflavor_name[i], name) == 0) + return i; + } + return -1; +} + +/* @str is a colon seperated list of security flavors. Their order + * is recorded in @ep, and a bitmap corresponding to the list is returned. + * A zero return indicates an error. + */ +static unsigned int +parse_flavors(char *str, struct exportent *ep) +{ + unsigned int out=0; + char *flavor; + int bit; + + while ( (flavor=strsep(&str, ":")) ) { + bit = secinfo_nameindex(flavor); + if (bit == -1) { + xlog(L_ERROR, "unknown flavor %s\n", flavor); + return 0; + } + out |= 1<<bit; + secinfo_addflavor(bit, ep); + } + return out; +} + +/* Determine a default security flavor based on ep->e_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<<i; +} + +/* Sets the bits in @mask for the appropriate security flavor flags. */ +static void +setflags(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; + } +} + +/* 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 22e13a3..30732b8 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) @@ -433,6 +435,7 @@ #ifdef DEBUG break; #endif } + secinfo_show(stdout, ep); printf("%c\n", (c != '(')? ')' : ' '); } } diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c index 5f0d12a..78a8f75 100644 --- a/utils/mountd/cache.c +++ b/utils/mountd/cache.c @@ -445,6 +445,19 @@ 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]); + } +} + static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp) { qword_print(f, domain); @@ -466,6 +479,7 @@ static int dump_to_cache(FILE *f, char * qword_print(f, "uuid"); qword_printhex(f, exp->e_uuid, 16); } + write_secinfo(f, exp); } return qword_eol(f); }