summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--support/export/hostname.c52
-rw-r--r--support/include/misc.h1
-rw-r--r--utils/mountd/auth.c79
4 files changed, 77 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index ba0545d..c181e21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2003-05-21 NeilBrown <neilb@cse.unsw.edu.au>
+
+ * support/export/hostname.c(get_reliable_hostbyaddr): new function
+ to get host name from address with full checking of authenticity.
+ * support/include/misc.h: declare above function
+ * utils/mountd/auth.c(auth_authenticate_internal): remove all
+ logic for authenticating address.
+ * utils/mountd/auth.c(auth_authenticate): call new
+ get_reliable_hostbyaddr to to hostname lookup before calling _internal.
+
+
2003-03-30 NeilBrown <neilb@cse.unsw.edu.au>
* tools/rpcgen/rpc_main.c(find_cpp): removed
diff --git a/support/export/hostname.c b/support/export/hostname.c
index 299fe99..f88e0a4 100644
--- a/support/export/hostname.c
+++ b/support/export/hostname.c
@@ -16,6 +16,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
+#include <xlog.h>
#ifdef TEST
#define xmalloc malloc
#else
@@ -216,6 +217,57 @@ matchhostname (const char *h1, const char *h2)
return status;
}
+
+/* Map IP to hostname, and then map back to addr to make sure it is a
+ * reliable hostname
+ */
+struct hostent *
+get_reliable_hostbyaddr(const char *addr, int len, int type)
+{
+ struct hostent *hp;
+
+ char **sp;
+ struct hostent *forward = NULL;
+ char *tmpname;
+
+ hp = gethostbyaddr(addr, len , type);
+ if (!hp)
+ return hp;
+
+ /* must make sure the hostent is authorative. */
+
+ hp = hostent_dup (hp);
+ tmpname = xstrdup((hp)->h_name);
+ if (tmpname) {
+ forward = gethostbyname(tmpname);
+ free(tmpname);
+ }
+ if (forward) {
+ /* now make sure the "addr" is in the list */
+ for (sp = forward->h_addr_list ; *sp ; sp++) {
+ if (memcmp(*sp, addr, forward->h_length)==0)
+ break;
+ }
+
+ if (!*sp) {
+ /* it was a FAKE */
+ xlog(L_WARNING, "Fake hostname %s for %s - forward lookup doesn't match reverse",
+ forward->h_name, inet_ntoa(*(struct in_addr*)addr));
+ return NULL;
+ }
+ free (hp);
+ hp = hostent_dup (forward);
+ }
+ else {
+ /* never heard of it. misconfigured DNS? */
+ xlog(L_WARNING, "Fake hostname %s for %s - forward lookup doesn't exist",
+ forward->h_name, inet_ntoa(*(struct in_addr*)addr));
+ return NULL;
+ }
+ return hp;
+}
+
+
#ifdef TEST
void
print_host (struct hostent *hp)
diff --git a/support/include/misc.h b/support/include/misc.h
index a3cdcfd..7d099d0 100644
--- a/support/include/misc.h
+++ b/support/include/misc.h
@@ -20,5 +20,6 @@ int matchhostname(const char *h1, const char *h2);
struct hostent;
struct hostent *hostent_dup(struct hostent *hp);
struct hostent *get_hostent (const char *addr, int len, int type);
+struct hostent *get_reliable_hostbyaddr(const char *addr, int len, int type);
#endif /* MISC_H */
diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c
index d88c46f..eb9cdeb 100644
--- a/utils/mountd/auth.c
+++ b/utils/mountd/auth.c
@@ -25,15 +25,10 @@ enum auth_error
no_entry,
not_exported,
illegal_port,
- faked_hostent,
- no_forward_dns,
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
@@ -66,56 +61,12 @@ auth_reload()
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 **sp;
- struct hostent *forward = NULL;
- char *tmpname;
-
- *hpp = hostent_dup (*hpp);
- tmpname = xstrdup((*hpp)->h_name);
- if (tmpname) {
- forward = gethostbyname(tmpname);
- free(tmpname);
- }
- if (forward) {
- /* now make sure the "addr" is in the list */
- for (sp = forward->h_addr_list ; *sp ; sp++) {
- if (memcmp(*sp, &addr, forward->h_length)==0)
- break;
- }
-
- if (!*sp) {
- /* it was a FAKE */
- *error = faked_hostent;
- return NULL;
- }
- free (*hpp);
- *hpp = hostent_dup (forward);
- }
- else {
- /* never heard of it. misconfigured DNS? */
- *error = no_forward_dns;
- return NULL;
- }
- }
-
- if (!(exp = export_find(*hpp, path))) {
+ if (!(exp = export_find(hp, path))) {
*error = no_entry;
return NULL;
}
@@ -154,15 +105,20 @@ auth_authenticate(char *what, struct sockaddr_in *caller, char *path)
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. */
@@ -171,6 +127,7 @@ auth_authenticate(char *what, struct sockaddr_in *caller, char *path)
if (p == epath) p++;
*p = '\0';
}
+ free(hp);
switch (error) {
case bad_path:
@@ -198,16 +155,6 @@ auth_authenticate(char *what, struct sockaddr_in *caller, char *path)
what, hp->h_name, path, epath, ntohs(caller->sin_port));
break;
- case faked_hostent:
- xlog(L_WARNING, "refused %s request from %s (%s) for %s (%s): DNS forward lookup does't match with reverse",
- what, inet_ntoa(addr), hp->h_name, path, epath);
- break;
-
- case no_forward_dns:
- xlog(L_WARNING, "refused %s request from %s (%s) for %s (%s): no DNS forward lookup",
- what, inet_ntoa(addr), hp->h_name, 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);