diff options
author | hjl <hjl> | 1999-10-18 23:21:12 +0000 |
---|---|---|
committer | hjl <hjl> | 1999-10-18 23:21:12 +0000 |
commit | 8b7ad01b14df1e7529b9ba8a1ea17df0d6004ef9 (patch) | |
tree | 0904ef8554ed680fe3244fa618685e1fb7ea148b /utils/mountd/auth.c | |
download | nfs-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.c | 215 |
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'; +} |