4 * Authentication procedures for mountd.
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
33 static void auth_fixpath(char *path);
34 static nfs_export* auth_authenticate_internal
35 (char *what, struct sockaddr_in *caller, char *path,
36 struct hostent **hpp, enum auth_error *error);
37 static char *export_file = NULL;
40 auth_init(char *exports)
43 export_file = exports;
52 static time_t last_modified = 0;
54 if (stat(_PATH_ETAB, &stb) < 0)
55 xlog(L_FATAL, "couldn't stat %s", _PATH_ETAB);
56 if (stb.st_mtime == last_modified)
58 last_modified = stb.st_mtime;
61 // export_read(export_file);
68 auth_authenticate_internal(char *what, struct sockaddr_in *caller,
69 char *path, struct hostent **hpp,
70 enum auth_error *error)
72 struct in_addr addr = caller->sin_addr;
81 /* First try it w/o doing a hostname lookup... */
82 *hpp = get_hostent((const char *)&addr, sizeof(addr), AF_INET);
83 exp = export_find(*hpp, path);
86 /* Ok, that didn't fly. Try it with a reverse lookup. */
88 *hpp = gethostbyaddr((const char *)&addr, sizeof(addr),
92 *hpp = get_hostent((const char *)&addr, sizeof(addr), AF_INET);
95 /* must make sure the hostent is authorative. */
97 struct hostent *forward = NULL;
100 *hpp = hostent_dup (*hpp);
101 tmpname = xstrdup((*hpp)->h_name);
103 forward = gethostbyname(tmpname);
107 /* now make sure the "addr" is in the list */
108 for (sp = forward->h_addr_list ; *sp ; sp++) {
109 if (memcmp(*sp, &addr, forward->h_length)==0)
115 *error = faked_hostent;
119 *hpp = hostent_dup (forward);
122 /* never heard of it. misconfigured DNS? */
123 *error = no_forward_dns;
128 if (!(exp = export_find(*hpp, path))) {
134 if (!exp->m_mayexport) {
135 *error = not_exported;
139 if (!(exp->m_export.e_flags & NFSEXP_INSECURE_PORT) &&
140 (ntohs(caller->sin_port) < IPPORT_RESERVED/2 ||
141 ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
142 *error = illegal_port;
152 auth_authenticate(char *what, struct sockaddr_in *caller, char *path)
154 nfs_export *exp = NULL;
155 char epath[MAXPATHLEN+1];
157 struct hostent *hp = NULL;
158 struct in_addr addr = caller->sin_addr;
159 enum auth_error error;
161 if (path [0] != '/') return exp;
163 strncpy(epath, path, sizeof (epath) - 1);
164 epath[sizeof (epath) - 1] = '\0';
166 /* Try the longest matching exported pathname. */
172 exp = auth_authenticate_internal(what, caller, epath,
174 if (exp || (error != not_exported && error != no_entry))
176 /* We have to treat the root, "/", specially. */
177 if (p == &epath[1]) break;
178 p = strrchr(epath, '/');
185 xlog(L_WARNING, "bad path in %s request from %s: \"%s\"",
186 what, inet_ntoa(addr), path);
190 xlog(L_WARNING, "%s request from unknown host %s for %s (%s)",
191 what, inet_ntoa(addr), path, epath);
195 xlog(L_WARNING, "refused %s request from %s for %s (%s): no export entry",
196 what, hp->h_name, path, epath);
200 xlog(L_WARNING, "refused %s request from %s for %s (%s): not exported",
201 what, hp->h_name, path, epath);
205 xlog(L_WARNING, "refused %s request from %s for %s (%s): illegal port %d",
206 what, hp->h_name, path, epath, ntohs(caller->sin_port));
210 xlog(L_WARNING, "refused %s request from %s (%s) for %s (%s): DNS forward lookup does't match with reverse",
211 what, inet_ntoa(addr), hp->h_name, path, epath);
215 xlog(L_WARNING, "refused %s request from %s (%s) for %s (%s): no DNS forward lookup",
216 what, inet_ntoa(addr), hp->h_name, path, epath);
220 xlog(L_NOTICE, "authenticated %s request from %s:%d for %s (%s)",
221 what, hp->h_name, ntohs(caller->sin_port), path, epath);
224 xlog(L_NOTICE, "%s request from %s:%d for %s (%s) gave %d",
225 what, hp->h_name, ntohs(caller->sin_port), path, epath, error);
235 auth_fixpath(char *path)
239 for (sp = cp = path; *sp; sp++) {
240 if (*sp != '/' || sp[1] != '/')
243 while (cp > path+1 && cp[-1] == '/')