]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/mountd/auth.c
eb9cdebad2314093efba87b0e20bfb63e9b6da26
[nfs-utils.git] / utils / mountd / auth.c
1 /*
2  * utils/mountd/auth.c
3  *
4  * Authentication procedures for mountd.
5  *
6  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7  */
8
9 #include "config.h"
10
11 #include <sys/stat.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
14 #include <errno.h>
15 #include "misc.h"
16 #include "nfslib.h"
17 #include "exportfs.h"
18 #include "mountd.h"
19 #include "xmalloc.h"
20
21 enum auth_error
22 {
23   bad_path,
24   unknown_host,
25   no_entry,
26   not_exported,
27   illegal_port,
28   success
29 };
30
31 static void             auth_fixpath(char *path);
32 static char     *export_file = NULL;
33
34 void
35 auth_init(char *exports)
36 {
37
38         export_file = exports;
39         auth_reload();
40         xtab_mount_write();
41 }
42
43 int
44 auth_reload()
45 {
46         struct stat             stb;
47         static time_t           last_modified = 0;
48
49         if (stat(_PATH_ETAB, &stb) < 0)
50                 xlog(L_FATAL, "couldn't stat %s", _PATH_ETAB);
51         if (stb.st_mtime == last_modified)
52                 return 0;
53         last_modified = stb.st_mtime;
54
55         export_freeall();
56         // export_read(export_file);
57         xtab_export_read();
58
59         return 1;
60 }
61
62 static nfs_export *
63 auth_authenticate_internal(char *what, struct sockaddr_in *caller,
64                            char *path, struct hostent *hp,
65                            enum auth_error *error)
66 {
67         nfs_export              *exp;
68
69         if (!(exp = export_find(hp, path))) {
70                 *error = no_entry;
71                 return NULL;
72         }
73         if (!exp->m_mayexport) {
74                 *error = not_exported;
75                 return NULL;
76         }
77
78         if (!(exp->m_export.e_flags & NFSEXP_INSECURE_PORT) &&
79             (ntohs(caller->sin_port) <  IPPORT_RESERVED/2 ||
80              ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
81                 *error = illegal_port;
82                 return NULL;
83         }
84
85         *error = success;
86
87         return exp;
88 }
89
90 nfs_export *
91 auth_authenticate(char *what, struct sockaddr_in *caller, char *path)
92 {
93         nfs_export      *exp = NULL;
94         char            epath[MAXPATHLEN+1];
95         char            *p = NULL;
96         struct hostent  *hp = NULL;
97         struct in_addr  addr = caller->sin_addr;
98         enum auth_error error;
99
100         if (path [0] != '/') {
101                 xlog(L_WARNING, "bad path in %s request from %s: \"%s\"",
102                      what, inet_ntoa(addr), path);
103                 return exp;
104         }
105
106         strncpy(epath, path, sizeof (epath) - 1);
107         epath[sizeof (epath) - 1] = '\0';
108         auth_fixpath(epath); /* strip duplicate '/' etc */
109
110         hp = get_reliable_hostbyaddr((const char*)&caller->sin_addr, sizeof(struct in_addr),
111                                      AF_INET);
112         if (!hp)
113                 hp = get_hostent((const char*)&caller->sin_addr, sizeof(struct in_addr),
114                                      AF_INET);
115         if (!hp)
116                 return exp;
117
118         /* Try the longest matching exported pathname. */
119         while (1) {
120                 exp = auth_authenticate_internal(what, caller, epath,
121                                                  hp, &error);
122                 if (exp || (error != not_exported && error != no_entry))
123                         break;
124                 /* We have to treat the root, "/", specially. */
125                 if (p == &epath[1]) break;
126                 p = strrchr(epath, '/');
127                 if (p == epath) p++;
128                 *p = '\0';
129         }
130         free(hp);
131
132         switch (error) {
133         case bad_path:
134                 xlog(L_WARNING, "bad path in %s request from %s: \"%s\"",
135                      what, inet_ntoa(addr), path);
136                 break;
137
138         case unknown_host:
139                 xlog(L_WARNING, "%s request from unknown host %s for %s (%s)",
140                      what, inet_ntoa(addr), path, epath);
141                 break;
142
143         case no_entry:
144                 xlog(L_WARNING, "refused %s request from %s for %s (%s): no export entry",
145                      what, hp->h_name, path, epath);
146                 break;
147
148         case not_exported:
149                 xlog(L_WARNING, "refused %s request from %s for %s (%s): not exported",
150                      what, hp->h_name, path, epath);
151                 break;
152
153         case illegal_port:
154                 xlog(L_WARNING, "refused %s request from %s for %s (%s): illegal port %d",
155                      what, hp->h_name, path, epath, ntohs(caller->sin_port));
156                 break;
157
158         case success:
159                 xlog(L_NOTICE, "authenticated %s request from %s:%d for %s (%s)",
160                      what, hp->h_name, ntohs(caller->sin_port), path, epath);
161                 break;
162         default:
163                 xlog(L_NOTICE, "%s request from %s:%d for %s (%s) gave %d",
164                      what, hp->h_name, ntohs(caller->sin_port), path, epath, error);
165         }
166
167         if (hp)
168                 free (hp);
169
170         return exp;
171 }
172
173 static void
174 auth_fixpath(char *path)
175 {
176         char    *sp, *cp;
177
178         for (sp = cp = path; *sp; sp++) {
179                 if (*sp != '/' || sp[1] != '/')
180                         *cp++ = *sp;
181         }
182         while (cp > path+1 && cp[-1] == '/')
183                 cp--;
184         *cp = '\0';
185 }