4 * Authentication procedures for mountd.
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
35 static void auth_fixpath(char *path);
36 static char *export_file = NULL;
37 static nfs_export my_exp;
38 static nfs_client my_client;
41 extern int use_ipaddr;
44 auth_init(char *exports)
47 export_file = exports;
53 * A client can match many different netgroups and it's tough to know
54 * beforehand whether it will. If the concatenated string of netgroup
55 * m_hostnames is >512 bytes, then enable the "use_ipaddr" mode. This
56 * makes mountd change how it matches a client ip address when a mount
57 * request comes in. It's more efficient at handling netgroups at the
58 * expense of larger kernel caches.
64 int old_use_ipaddr = use_ipaddr;
67 /* add length of m_hostname + 1 for the comma */
68 for (clp = clientlist[MCL_NETGROUP]; clp; clp = clp->m_next)
69 len += (strlen(clp->m_hostname) + 1);
71 if (len > (NFSCLNT_IDMAX / 2))
76 if (use_ipaddr != old_use_ipaddr)
84 static ino_t last_inode;
86 static unsigned int counter;
89 if ((fd = open(_PATH_ETAB, O_RDONLY)) < 0) {
90 xlog(L_FATAL, "couldn't open %s", _PATH_ETAB);
91 } else if (fstat(fd, &stb) < 0) {
92 xlog(L_FATAL, "couldn't stat %s", _PATH_ETAB);
93 } else if (stb.st_ino == last_inode) {
99 last_inode = stb.st_ino;
103 memset(&my_client, 0, sizeof(my_client));
113 static char *get_client_hostname(struct sockaddr_in *caller, struct hostent *hp, enum auth_error *error)
118 return strdup(inet_ntoa(caller->sin_addr));
119 n = client_compose(hp);
120 *error = unknown_host;
126 return strdup("DEFAULT");
129 /* return static nfs_export with details filled in */
131 auth_authenticate_newcache(char *what, struct sockaddr_in *caller,
132 char *path, struct hostent *hp,
133 enum auth_error *error)
138 free(my_client.m_hostname);
140 my_client.m_hostname = get_client_hostname(caller, hp, error);
141 if (my_client.m_hostname == NULL)
144 my_client.m_naddr = 1;
145 my_client.m_addrlist[0] = caller->sin_addr;
146 my_exp.m_client = &my_client;
149 for (i = 0; !exp && i < MCL_MAXTYPES; i++)
150 for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
151 if (strcmp(path, exp->m_export.e_path))
153 if (!use_ipaddr && !client_member(my_client.m_hostname, exp->m_client->m_hostname))
155 if (use_ipaddr && !client_check(exp->m_client, hp))
159 *error = not_exported;
163 my_exp.m_export = exp->m_export;
169 auth_authenticate_internal(char *what, struct sockaddr_in *caller,
170 char *path, struct hostent *hp,
171 enum auth_error *error)
176 exp = auth_authenticate_newcache(what, caller, path, hp, error);
180 if (!(exp = export_find(hp, path))) {
185 if (exp->m_export.e_flags & NFSEXP_V4ROOT) {
189 if (!(exp->m_export.e_flags & NFSEXP_INSECURE_PORT) &&
190 ntohs(caller->sin_port) >= IPPORT_RESERVED) {
191 *error = illegal_port;
200 auth_authenticate(char *what, struct sockaddr_in *caller, char *path)
202 nfs_export *exp = NULL;
203 char epath[MAXPATHLEN+1];
205 struct hostent *hp = NULL;
206 struct in_addr addr = caller->sin_addr;
207 enum auth_error error = bad_path;
209 if (path [0] != '/') {
210 xlog(L_WARNING, "bad path in %s request from %s: \"%s\"",
211 what, inet_ntoa(addr), path);
215 strncpy(epath, path, sizeof (epath) - 1);
216 epath[sizeof (epath) - 1] = '\0';
217 auth_fixpath(epath); /* strip duplicate '/' etc */
219 hp = client_resolve(caller->sin_addr);
223 /* Try the longest matching exported pathname. */
225 exp = auth_authenticate_internal(what, caller, epath,
227 if (exp || (error != not_exported && error != no_entry))
229 /* We have to treat the root, "/", specially. */
230 if (p == &epath[1]) break;
231 p = strrchr(epath, '/');
238 xlog(L_WARNING, "bad path in %s request from %s: \"%s\"",
239 what, inet_ntoa(addr), path);
243 xlog(L_WARNING, "refused %s request from %s for %s (%s): unmatched host",
244 what, inet_ntoa(addr), path, epath);
248 xlog(L_WARNING, "refused %s request from %s for %s (%s): no export entry",
249 what, hp->h_name, path, epath);
253 xlog(L_WARNING, "refused %s request from %s for %s (%s): not exported",
254 what, hp->h_name, path, epath);
258 xlog(L_WARNING, "refused %s request from %s for %s (%s): illegal port %d",
259 what, hp->h_name, path, epath, ntohs(caller->sin_port));
263 xlog(L_NOTICE, "authenticated %s request from %s:%d for %s (%s)",
264 what, hp->h_name, ntohs(caller->sin_port), path, epath);
267 xlog(L_NOTICE, "%s request from %s:%d for %s (%s) gave %d",
268 what, hp->h_name, ntohs(caller->sin_port), path, epath, error);
278 auth_fixpath(char *path)
282 for (sp = cp = path; *sp; sp++) {
283 if (*sp != '/' || sp[1] != '/')
286 while (cp > path+1 && cp[-1] == '/')