summaryrefslogtreecommitdiffstats
path: root/utils/mountd/auth.c
diff options
context:
space:
mode:
authorhjl <hjl>1999-10-18 23:21:12 +0000
committerhjl <hjl>1999-10-18 23:21:12 +0000
commit8b7ad01b14df1e7529b9ba8a1ea17df0d6004ef9 (patch)
tree0904ef8554ed680fe3244fa618685e1fb7ea148b /utils/mountd/auth.c
downloadnfs-utils-8b7ad01b14df1e7529b9ba8a1ea17df0d6004ef9.tar.gz
nfs-utils-8b7ad01b14df1e7529b9ba8a1ea17df0d6004ef9.tar.xz
nfs-utils-8b7ad01b14df1e7529b9ba8a1ea17df0d6004ef9.zip
Initial revision
Diffstat (limited to 'utils/mountd/auth.c')
-rw-r--r--utils/mountd/auth.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c
new file mode 100644
index 0000000..9f63120
--- /dev/null
+++ b/utils/mountd/auth.c
@@ -0,0 +1,215 @@
+/*
+ * utils/mountd/auth.c
+ *
+ * Authentication procedures for mountd.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "mountd.h"
+
+enum auth_error
+{
+ bad_path,
+ unknown_host,
+ no_entry,
+ not_exported,
+ illegal_port,
+ faked_hostent,
+ success
+};
+
+static void auth_fixpath(char *path);
+static nfs_export* auth_authenticate_internal
+ (char *what, struct sockaddr_in *caller, char *path,
+ struct hostent **hpp, enum auth_error *error);
+static char *export_file = NULL;
+
+void
+auth_init(char *exports)
+{
+
+ export_file = exports;
+ auth_reload();
+ xtab_mount_write();
+}
+
+int
+auth_reload()
+{
+ struct stat stb;
+ static time_t last_modified = 0;
+
+ if (stat(_PATH_ETAB, &stb) < 0)
+ xlog(L_FATAL, "couldn't stat %s", _PATH_ETAB);
+ if (stb.st_mtime == last_modified)
+ return 0;
+ last_modified = stb.st_mtime;
+
+ export_freeall();
+ // export_read(export_file);
+ xtab_export_read();
+
+ return 1;
+}
+
+static nfs_export *
+auth_authenticate_internal(char *what, struct sockaddr_in *caller,
+ char *path, struct hostent **hpp,
+ enum auth_error *error)
+{
+ struct in_addr addr = caller->sin_addr;
+ nfs_export *exp;
+
+ if (path[0] != '/') {
+ *error = bad_path;
+ return NULL;
+ }
+ auth_fixpath(path);
+
+ if (!(*hpp = gethostbyaddr((const char *)&addr, sizeof(addr), AF_INET)))
+ *hpp = get_hostent((const char *)&addr, sizeof(addr),
+ AF_INET);
+ else {
+ /* must make sure the hostent is authorative. */
+ char *name = strdup((*hpp)->h_name);
+ char **sp;
+ *hpp = gethostbyname(name);
+ /* now make sure the "addr" is in the list */
+ for (sp = (*hpp)->h_addr_list ; *sp ; sp++) {
+ if (memcmp(*sp, &addr, (*hpp)->h_length)==0)
+ break;
+ }
+
+ if (!*sp) {
+ free(name);
+ /* it was a FAKE */
+ *error = faked_hostent;
+ *hpp = NULL;
+ return NULL;
+ }
+ *hpp = hostent_dup (*hpp);
+ free(name);
+ }
+
+ if (!(exp = export_find(*hpp, path))) {
+ *error = no_entry;
+ return NULL;
+ }
+ if (!exp->m_mayexport) {
+ *error = not_exported;
+ return NULL;
+ }
+
+ if (!(exp->m_export.e_flags & NFSEXP_INSECURE_PORT) &&
+ (ntohs(caller->sin_port) < IPPORT_RESERVED/2 ||
+ ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
+ *error = illegal_port;
+ return NULL;
+ }
+
+ *error = success;
+
+ return exp;
+}
+
+nfs_export *
+auth_authenticate(char *what, struct sockaddr_in *caller, char *path)
+{
+ nfs_export *exp = NULL;
+ char epath[MAXPATHLEN+1];
+ char *p = NULL;
+ struct hostent *hp = NULL;
+ struct in_addr addr = caller->sin_addr;
+ enum auth_error error;
+
+ if (path [0] != '/') return exp;
+
+ strncpy(epath, path, sizeof (epath) - 1);
+ epath[sizeof (epath) - 1] = '\0';
+
+ /* Try the longest matching exported pathname. */
+ while (1) {
+ if (hp) {
+ free (hp);
+ hp = NULL;
+ }
+ exp = auth_authenticate_internal(what, caller, epath,
+ &hp, &error);
+ if (exp || (error != not_exported && error != no_entry))
+ break;
+ /* We have to treat the root, "/", specially. */
+ if (p == &epath[1]) break;
+ p = strrchr(epath, '/');
+ if (p == epath) p++;
+ *p = '\0';
+ }
+
+ switch (error) {
+ case bad_path:
+ xlog(L_WARNING, "bad path in %s request from %s: \"%s\"",
+ what, inet_ntoa(addr), path);
+ break;
+
+ case unknown_host:
+ xlog(L_WARNING, "%s request from unknown host %s for %s (%s)",
+ what, inet_ntoa(addr), path, epath);
+ break;
+
+ case no_entry:
+ xlog(L_WARNING, "refused %s request from %s for %s (%s): no export entry",
+ what, hp->h_name, path, epath);
+ break;
+
+ case not_exported:
+ xlog(L_WARNING, "refused %s request from %s for %s (%s): not exported",
+ what, hp->h_name, path, epath);
+ break;
+
+ case illegal_port:
+ xlog(L_WARNING, "refused %s request from %s for %s (%s): illegal port %d",
+ what, hp->h_name, path, epath, ntohs(caller->sin_port));
+ break;
+
+ case faked_hostent:
+ xlog(L_WARNING, "refused %s request from %s for %s (%s): faked hostent",
+ what, inet_ntoa(addr), path, epath);
+ break;
+
+ case success:
+ xlog(L_NOTICE, "authenticated %s request from %s:%d for %s (%s)",
+ what, hp->h_name, ntohs(caller->sin_port), path, epath);
+ break;
+ default:
+ xlog(L_NOTICE, "%s request from %s:%d for %s (%s) gave %d",
+ what, hp->h_name, ntohs(caller->sin_port), path, epath, error);
+ }
+
+ if (hp)
+ free (hp);
+
+ return exp;
+}
+
+static void
+auth_fixpath(char *path)
+{
+ char *sp, *cp;
+
+ for (sp = cp = path; *sp; sp++) {
+ if (*sp != '/' || sp[1] != '/')
+ *cp++ = *sp;
+ }
+ while (cp > path+1 && cp[-1] == '/')
+ cp--;
+ *cp = '\0';
+}