This patch modifies the NFSv4 'mount' command to accept multiple authentication flavors. This list of flavors will be used during security negotiation to determine which flavors the user is willing to use (most preferred flavor is listed first). This patch applies on top of CITI's version 2.11z-3 of util-linux. The format for passing one flavor is unchanged: mount -tnfs4 -osec=krb5 server:/ /mnt/nfs4 The format for passing multiple flavors is: mount -tnfs4 -osec=krb5:spkm3p:unix server:/ /mnt/nfs4 If no sec= option is given, we assume AUTH_UNIX. From Nick Wilson --- util-linux-2.12-bfields/mount/nfs4mount.c | 102 ++++++++++++++++++++++-------- 1 files changed, 75 insertions(+), 27 deletions(-) diff -puN mount/nfs4mount.c~modify_mount_to_support_multiple_security_flavors mount/nfs4mount.c --- util-linux-2.12/mount/nfs4mount.c~modify_mount_to_support_multiple_security_flavors 2004-10-13 14:18:23.000000000 -0400 +++ util-linux-2.12-bfields/mount/nfs4mount.c 2004-10-13 14:21:18.000000000 -0400 @@ -36,6 +36,7 @@ #include #include #include +#include #include "sundries.h" @@ -48,6 +49,57 @@ #define NFS_PORT 2049 #endif +struct { + char *flavour; + int fnum; +} flav_map[] = { + { "krb5", RPC_AUTH_GSS_KRB5 }, + { "krb5i", RPC_AUTH_GSS_KRB5I }, + { "krb5p", RPC_AUTH_GSS_KRB5P }, + { "lipkey", RPC_AUTH_GSS_LKEY }, + { "lipkey-i", RPC_AUTH_GSS_LKEYI }, + { "lipkey-p", RPC_AUTH_GSS_LKEYP }, + { "spkm3", RPC_AUTH_GSS_SPKM }, + { "spkm3i", RPC_AUTH_GSS_SPKMI }, + { "spkm3p", RPC_AUTH_GSS_SPKMP }, + { "unix", AUTH_UNIX }, + { "sys", AUTH_SYS }, + { "null", AUTH_NULL }, + { "none", AUTH_NONE }, +}; + +#define FMAPSIZE (sizeof(flav_map)/sizeof(flav_map[0])) +#define MAX_USER_FLAVOUR 16 + +static int parse_sec(char *sec, int *pseudoflavour) +{ + int i, num_flavour = 0; + + for (sec = strtok(sec, ":"); sec; sec = strtok(NULL, ":")) { + if (num_flavour >= MAX_USER_FLAVOUR) { + fprintf(stderr, + _("mount: maximum number of security flavors " + "exceeded\n")); + return 0; + } + for (i = 0; i < FMAPSIZE; i++) { + if (strcmp(sec, flav_map[i].flavour) == 0) { + pseudoflavour[num_flavour++] = flav_map[i].fnum; + break; + } + } + if (i == FMAPSIZE) { + fprintf(stderr, + _("mount: unknown security type %s\n"), sec); + return 0; + } + } + if (!num_flavour) + fprintf(stderr, + _("mount: no security flavors passed to sec= option\n")); + return num_flavour; +} + static int parse_devname(char *hostdir, char **hostname, char **dirname) { char *s; @@ -117,7 +169,8 @@ int nfs4mount(const char *spec, const ch static char hostdir[1024]; static char ip_addr[16] = "127.0.0.1"; static struct sockaddr_in server_addr; - static int pseudoflavour = 0; + static int pseudoflavour[MAX_USER_FLAVOUR]; + int num_flavour = 0; char *hostname, *dirname, *old_opts; char new_opts[1024]; @@ -228,29 +281,9 @@ int nfs4mount(const char *spec, const ch strncpy(ip_addr,opteq+1, sizeof(ip_addr)); ip_addr[sizeof(ip_addr)-1] = '\0'; } else if (!strcmp(opt, "sec")) { - if (!strcmp(opteq+1, "krb5")) - pseudoflavour = 390003; - else if (!strcmp(opteq+1, "krb5i")) - pseudoflavour = 390004; - else if (!strcmp(opteq+1, "krb5p")) - pseudoflavour = 390005; - else if (!strcmp(opteq+1, "lipkey")) - pseudoflavour = 390006; - else if (!strcmp(opteq+1, "lipkey-i")) - pseudoflavour = 390007; - else if (!strcmp(opteq+1, "lipkey-p")) - pseudoflavour = 390008; - else if (!strcmp(opteq+1, "spkm3")) - pseudoflavour = 390009; - else if (!strcmp(opteq+1, "spkm3i")) - pseudoflavour = 390010; - else if (!strcmp(opteq+1, "spkm3p")) - pseudoflavour = 390011; - else { - printf(_("unknown security type %s\n"), - opteq+1); + num_flavour = parse_sec(opteq+1, pseudoflavour); + if (!num_flavour) goto fail; - } } else if (!strcmp(opt, "addr")) { /* ignore */; } else { @@ -293,10 +326,10 @@ int nfs4mount(const char *spec, const ch | (nocto ? NFS4_MOUNT_NOCTO : 0) | (noac ? NFS4_MOUNT_NOAC : 0); - if (pseudoflavour != 0) { - data.auth_flavourlen = 1; - data.auth_flavours = &pseudoflavour; - } + if (num_flavour == 0) + pseudoflavour[num_flavour++] = AUTH_UNIX; + data.auth_flavourlen = num_flavour; + data.auth_flavours = pseudoflavour; data.client_addr.data = ip_addr; data.client_addr.len = strlen(ip_addr); @@ -321,6 +354,21 @@ int nfs4mount(const char *spec, const ch (data.flags & NFS4_MOUNT_INTR) != 0, (data.flags & NFS4_MOUNT_NOCTO) != 0, (data.flags & NFS4_MOUNT_NOAC) != 0); + + if (num_flavour > 0) { + int pf_cnt, i; + + printf("sec = "); + for (pf_cnt = 0; pf_cnt < num_flavour; pf_cnt++) { + for (i = 0; i < FMAPSIZE; i++) { + if (flav_map[i].fnum == pseudoflavour[pf_cnt]) { + printf("%s", flav_map[i].flavour); + break; + } + } + printf("%s", (pf_cnt < num_flavour-1) ? ":" : "\n"); + } + } printf("proto = %s\n", (data.proto == IPPROTO_TCP) ? "tcp" : "udp"); #endif _