* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
*/
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <sys/stat.h>
#include <netinet/in.h>
#include "nfslib.h"
#include "exportfs.h"
#include "mountd.h"
+#include "xmalloc.h"
enum auth_error
{
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;
+static nfs_export my_exp;
+static nfs_client my_client;
+
+extern int new_cache;
void
auth_init(char *exports)
last_modified = stb.st_mtime;
export_freeall();
+ memset(&my_client, 0, sizeof(my_client));
// export_read(export_file);
xtab_export_read();
static nfs_export *
auth_authenticate_internal(char *what, struct sockaddr_in *caller,
- char *path, struct hostent **hpp,
+ char *path, struct hostent *hp,
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)
+ if (new_cache) {
+ int i;
+ /* return static nfs_export with details filled in */
+ if (my_client.m_naddr != 1 ||
+ my_client.m_addrlist[0].s_addr != caller->sin_addr.s_addr) {
+ /* different client to last time, so do a lookup */
+ char *n;
+ my_client.m_naddr = 0;
+ my_client.m_addrlist[0] = caller->sin_addr;
+ n = client_compose(caller->sin_addr);
+ *error = unknown_host;
+ if (!n)
+ return NULL;
+ strcpy(my_client.m_hostname, *n?n:"DEFAULT");
+ free(n);
+ my_client.m_naddr = 1;
+ }
+
+ my_exp.m_client = &my_client;
+
+ exp = NULL;
+ for (i = 0; !exp && i < MCL_MAXTYPES; i++)
+ for (exp = exportlist[i]; exp; exp = exp->m_next) {
+ if (!client_member(my_client.m_hostname, exp->m_client->m_hostname))
+ continue;
+ if (strcmp(path, exp->m_export.e_path))
+ continue;
break;
+ }
+ *error = not_exported;
+ if (!exp)
+ return exp;
+
+ my_exp.m_export = exp->m_export;
+ exp = &my_exp;
+
+ } else {
+ if (!(exp = export_find(hp, path))) {
+ *error = no_entry;
+ return NULL;
}
-
- if (!*sp) {
- free(name);
- /* it was a FAKE */
- *error = faked_hostent;
- *hpp = NULL;
+ if (!exp->m_mayexport) {
+ *error = not_exported;
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)) {
+ (ntohs(caller->sin_port) < IPPORT_RESERVED/2 ||
+ ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
*error = illegal_port;
return NULL;
}
-
*error = success;
return exp;
struct in_addr addr = caller->sin_addr;
enum auth_error error;
- if (path [0] != '/') return exp;
+ if (path [0] != '/') {
+ xlog(L_WARNING, "bad path in %s request from %s: \"%s\"",
+ what, inet_ntoa(addr), path);
+ return exp;
+ }
strncpy(epath, path, sizeof (epath) - 1);
epath[sizeof (epath) - 1] = '\0';
+ auth_fixpath(epath); /* strip duplicate '/' etc */
+
+ hp = get_reliable_hostbyaddr((const char*)&caller->sin_addr, sizeof(struct in_addr),
+ AF_INET);
+ if (!hp)
+ hp = get_hostent((const char*)&caller->sin_addr, sizeof(struct in_addr),
+ AF_INET);
+ if (!hp)
+ return exp;
/* Try the longest matching exported pathname. */
while (1) {
- if (hp) {
- free (hp);
- hp = NULL;
- }
exp = auth_authenticate_internal(what, caller, epath,
- &hp, &error);
+ hp, &error);
if (exp || (error != not_exported && error != no_entry))
break;
/* We have to treat the root, "/", specially. */
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);