-/*
- * support/nfs/nfsclient.c
- *
- * Parse the nfsclients file.
- *
- * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <syslog.h>
-#include <ctype.h>
-#include "xmalloc.h"
-#include "nfslib.h"
-#include "exportfs.h"
-#include "xio.h"
-
-static char *cfname = NULL;
-static XFILE *cfp = NULL;
-static int *squash_uids = NULL,
- *squash_gids = NULL;
-static int squash_uidlen = 0,
- squash_gidlen = 0;
-static char *hosts = NULL;
-
-static int parsesquash(char *list, int **idp, int *lenp);
-static int parsenum(char **cpp);
-static int parsekey(struct nfskey *keyp, char *str);
-static int hexdigit(char c);
-static int gettag(char *tag, int len);
-static int getattr(char *attr, int alen, char *value, int vlen);
-static void syntaxerr(char *msg);
-
-#ifndef isblank
-#define isblank(c) ((c) == ' ' || (c) == '\t')
-#endif
-
-void
-setnfsclntent(char *fname)
-{
- if (cfp)
- xfclose(cfp);
- if (!fname)
- fname = _PATH_NFSCLIENTS;
- if ((cfp = xfopen(fname)) == NULL)
- xlog(L_ERROR, "can't open %s for reading", fname);
- cfname = strdup(fname);
-}
-
-struct nfsclntent *
-getnfsclntent(void)
-{
- static struct nfsclntent cle;
- static char *hostptr = NULL;
- char attr[32], val[512], *sp;
- int ok;
-
- if (!cfp)
- endnfsclntent();
-
-again:
- if (hosts) {
- if (hostptr)
- goto nexthost;
- xfree(hosts);
- hosts = NULL;
- }
-
- if ((ok = gettag(cle.c_tag, sizeof(cle.c_tag))) < 0)
- syntaxerr("expected tag");
- if (ok <= 0)
- return NULL;
-
- cle.c_hostname[0] = '\0';
- cle.c_fhkey.k_type = CLE_KEY_NONE;
- cle.c_mapping = CLE_MAP_IDENT;
- cle.c_anonuid = -2;
- cle.c_anongid = -2;
-
- if (squash_uids)
- xfree(squash_uids);
- if (squash_gids)
- xfree(squash_gids);
- squash_uids = squash_gids = NULL;
- squash_uidlen = squash_gidlen = 0;
-
- while (ok) {
- if ((ok = getattr(attr, sizeof(attr), val, sizeof(val))) < 0)
- return NULL;
- if (!ok)
- break;
- if (attr[0] == 'h' && !strcmp(attr, "hosts")) {
- int l0 = hosts? strlen(hosts) : 0;
-
- hosts = (char *) xrealloc(hosts, l0+strlen(val)+2);
- if (l0)
- hosts[l0++] = ':';
- strcpy(hosts+l0, val);
- } else
- if (attr[0] == 'f' && !strcmp(attr, "fhmac")) {
- if (!parsekey(&cle.c_fhkey, val))
- return NULL;
- } else
- if (attr[0] == 'm' && !strcmp(attr, "mapping")) {
- if (!strcmp(val, "identity"))
- cle.c_mapping = CLE_MAP_IDENT;
- else if (!strcmp(val, "file"))
- cle.c_mapping = CLE_MAP_FILE;
- else if (!strcmp(val, "daemon"))
- cle.c_mapping = CLE_MAP_UGIDD;
- else {
- syntaxerr("invalid mapping type");
- return NULL;
- }
- } else
- if (attr[0] == 's' && !strcmp(attr, "squash_uids")) {
- if (!parsesquash(val, &squash_uids, &squash_uidlen))
- return NULL;
- } else
- if (attr[0] == 's' && !strcmp(attr, "squash_gids")) {
- if (!parsesquash(val, &squash_gids, &squash_gidlen))
- return NULL;
- } else
- if (attr[0] == 'a' && !strcmp(attr, "anonuid"))
- cle.c_anonuid = atoi(val);
- else
- if (attr[0] == 'a' && !strcmp(attr, "anongid"))
- cle.c_anongid = atoi(val);
- else
- syntaxerr("unknown attribute");
- }
-
- cle.c_squashuids = squash_uids;
- cle.c_squashgids = squash_gids;
-
- /* This is the anon entry */
- if (!hosts) {
- if (strcmp(cle.c_tag, "anonymous")) {
- xlog(L_ERROR,
- "%s:%d: entry %s allows anonymous access. Ignored.",
- cfname, xfp->x_line, cle.c_tag);
- goto again;
- }
- return &cle;
- }
- hostptr = hosts;
-
-nexthost:
- if (*hostptr == ':' && strcmp(cle.c_tag, "anonymous")) {
- xlog(L_ERROR,
- "%s:%d: entry %s allows anonymous access. Ignored.",
- cfname, cfp->x_line, cle.c_tag);
- while (*hostptr == ':')
- hostptr++;
- }
-
- /* Ignore trailing colons */
- if (!*hostptr) {
- hostptr = NULL;
- goto again;
- }
-
- sp = hostptr;
- hostptr = strchr(hostptr, ':');
- if (hostptr)
- *hostptr++ = '\0';
- strncpy(cle.c_hostname, sp, sizeof(cle.c_hostname) - 1);
- cle.c_hostname [sizeof(cle.c_hostname) - 1] = '\0';
- return &cle;
-}
-
-void
-endnfsclntent(void)
-{
- if (cfname)
- free(cfname);
- if (cfp)
- xfclose(cfp);
- if (squash_uids)
- xfree(squash_uids);
- if (squash_gids)
- xfree(squash_gids);
- if (hosts)
- xfree(hosts);
- cfname = NULL;
- cfp = NULL;
- squash_uids = NULL;
- squash_gids = NULL;
- hosts = NULL;
-}
-
-static int
-parsekey(struct nfskey *keyp, char *str)
-{
- char *sp;
- int i, l, x0, x1;
-
-
- if ((sp = strchr(str, ':')) != NULL)
- *sp++ = '\0';
- if (!strcmp(str, "null"))
- keyp->k_type = CLE_KEY_NULL;
- else if (!strcmp(str, "md5"))
- keyp->k_type = CLE_KEY_MD5;
- else if (!strcmp(str, "sha"))
- keyp->k_type = CLE_KEY_SHA;
- else {
- syntaxerr("unknown key type");
- return 0;
- }
- if (keyp->k_type == CLE_KEY_NULL) {
- keyp->k_len = 0;
- if (sp)
- syntaxerr("unexpected key data for null key");
- return sp? 0 : 1;
- } else if (sp) {
- if ((l = strlen(sp)) & 1) {
- syntaxerr("odd key length");
- return 0;
- }
-
- l >>= 1;
- for (i = 0; i < l && i < sizeof(keyp->k_key); i++, sp += 2) {
- if ((x0 = hexdigit(sp[0])) == 0xff ||
- (x1 = hexdigit(sp[1])) == 0xff) {
- syntaxerr("bad key digit");
- return 0;
- }
- keyp->k_key[i] = (x0 << 4) | x1;
- }
- keyp->k_len = i;
- return 1;
- }
- return 0;
-}
-
-static int
-hexdigit(char c)
-{
- if ((c = tolower(c)) >= '0' && c <= '9')
- return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- return 0xff;
-}
-
-static int
-parsesquash(char *list, int **idp, int *lenp)
-{
- char *cp = list;
- int id0, id1;
- int len = *lenp;
- int *id = *idp;
-
- do {
- id0 = parsenum(&cp);
- if (*cp == '-') {
- cp++;
- id1 = parsenum(&cp);
- } else {
- id1 = id0;
- }
- if (id0 == -1 || id1 == -1) {
- syntaxerr("uid/gid -1 not permitted");
- return 0;
- }
- if ((len % 8) == 0)
- id = (int *) xrealloc(id, (len + 9) * sizeof(*id));
- id[len++] = id0;
- id[len++] = id1;
- if (!*cp)
- break;
- if (*cp != ',') {
- syntaxerr("bad uid/gid list");
- return 0;
- }
- cp++;
- } while(1);
-
- id[len] = -1;
- *lenp = len;
- *idp = id;
- return 1;
-}
-
-static int
-parsenum(char **cpp)
-{
- char *cp = *cpp, c;
- int num = 0;
-
- if (**cpp == '-')
- (*cpp)++;
- while (isdigit(**cpp))
- (*cpp)++;
- c = **cpp; **cpp = '\0'; num = atoi(cp); **cpp = c;
- return num;
-}
-
-static int
-gettag(char *tag, int len)
-{
- xskip(cfp, " \t\n");
- return xgettok(cfp, ':', tag, len);
-}
-
-static int
-getattr(char *attr, int alen, char *value, int vlen)
-{
- int ok;
-
- xskip(cfp, " \t");
- if ((ok = xgettok(cfp, '=', attr, alen)) < 0)
- syntaxerr("missing attribute");
- if (ok <= 0)
- return ok;
- xskip(cfp, " \t=");
-
- return xgettok(cfp, 0, value, vlen);
-}
-
-static void
-syntaxerr(char *msg)
-{
- xlog(L_ERROR, "%s:%d: syntax error: %s",
- cfname, cfp->x_line, msg);
-}
-