1 | /* |
---|
2 | * $Id: afs.c,v 1.8 1992-04-21 08:20:42 probe Exp $ |
---|
3 | * |
---|
4 | * Copyright (c) 1990,1992 by the Massachusetts Institute of Technology. |
---|
5 | */ |
---|
6 | |
---|
7 | static char *rcsid = "$Id: afs.c,v 1.8 1992-04-21 08:20:42 probe Exp $"; |
---|
8 | |
---|
9 | #include "attach.h" |
---|
10 | |
---|
11 | #ifdef AFS |
---|
12 | |
---|
13 | #include <sys/stat.h> |
---|
14 | #include <sys/wait.h> |
---|
15 | #include <sys/file.h> |
---|
16 | #include <sys/errno.h> |
---|
17 | |
---|
18 | #include <krb.h> |
---|
19 | |
---|
20 | extern char *krb_realmofhost(); /* <krb.h> doesn't declare this */ |
---|
21 | |
---|
22 | /* Flags to afs_auth_internal() */ |
---|
23 | #define AFSAUTH_DOAUTH 1 |
---|
24 | #define AFSAUTH_CELL 2 |
---|
25 | #define AFSAUTH_DOZEPHYR 4 |
---|
26 | |
---|
27 | #ifdef __STDC__ |
---|
28 | static int afs_auth_internal(char * errorname, char * afs_pathname, |
---|
29 | struct in_addr hostaddr[], int flags); |
---|
30 | #else |
---|
31 | static int afs_auth_internal(); |
---|
32 | #endif |
---|
33 | |
---|
34 | |
---|
35 | /* |
---|
36 | * The current implementation of AFS attaches is to make a symbolic |
---|
37 | * link. This is NOT GUARANTEED to always be the case. |
---|
38 | */ |
---|
39 | |
---|
40 | afs_attach(at, mopt, errorout) |
---|
41 | struct _attachtab *at; |
---|
42 | struct mntopts *mopt; |
---|
43 | int errorout; |
---|
44 | { |
---|
45 | struct stat statbuf; |
---|
46 | char buf[BUFSIZ]; |
---|
47 | int len; |
---|
48 | int afs_auth_flags = 0; |
---|
49 | |
---|
50 | if ((at->mode != 'n') && do_nfsid) |
---|
51 | afs_auth_flags |= AFSAUTH_DOAUTH; |
---|
52 | |
---|
53 | if (use_zephyr) |
---|
54 | afs_auth_flags |= AFSAUTH_DOZEPHYR; |
---|
55 | |
---|
56 | if (afs_auth_internal(at->hesiodname, at->hostdir, |
---|
57 | at->hostaddr, afs_auth_flags) == FAILURE) |
---|
58 | return(FAILURE); |
---|
59 | |
---|
60 | if (debug_flag) |
---|
61 | printf("lstating %s...\n", at->hostdir); |
---|
62 | setreuid(effective_uid, owner_uid); |
---|
63 | if (stat(at->hostdir, &statbuf)) { |
---|
64 | if (errno == ENOENT) |
---|
65 | fprintf(stderr, "%s: %s does not exist\n", |
---|
66 | at->hesiodname, at->hostdir); |
---|
67 | else |
---|
68 | perror(at->hostdir); |
---|
69 | error_status = ERR_ATTACHNOFILSYS; |
---|
70 | setreuid(real_uid, effective_uid); |
---|
71 | return(FAILURE); |
---|
72 | } |
---|
73 | if ((statbuf.st_mode & S_IFMT) != S_IFDIR) { |
---|
74 | fprintf(stderr, "%s: %s is not a directory\n", |
---|
75 | at->hesiodname, at->hostdir); |
---|
76 | setreuid(real_uid, effective_uid); |
---|
77 | error_status = ERR_ATTACHNOFILSYS; |
---|
78 | return(FAILURE); |
---|
79 | } |
---|
80 | |
---|
81 | if (debug_flag) |
---|
82 | printf("lstating %s....\n", at->mntpt); |
---|
83 | if (!lstat(at->mntpt, &statbuf)) { |
---|
84 | setreuid(real_uid, effective_uid); |
---|
85 | if ((statbuf.st_mode & S_IFMT) == S_IFLNK) { |
---|
86 | len = readlink(at->mntpt, buf, sizeof(buf)); |
---|
87 | buf[len] = '\0'; |
---|
88 | (void) strcpy(buf, path_canon(buf)); |
---|
89 | if (!strcmp(buf, path_canon(at->hostdir))) { |
---|
90 | if (!print_path && verbose) |
---|
91 | fprintf(stderr, |
---|
92 | "%s: %s already sym linked%s\n", |
---|
93 | at->hesiodname, at->hostdir, |
---|
94 | (afs_auth_flags & AFSAUTH_DOAUTH) ? |
---|
95 | ", authenticating..." : ""); |
---|
96 | if (keep_mount) |
---|
97 | at->flags |= FLAG_PERMANENT; |
---|
98 | return(SUCCESS); |
---|
99 | } else { |
---|
100 | if (keep_mount) { |
---|
101 | fprintf(stderr, |
---|
102 | "%s: Couldn't attach; symlink from %s to %s already exists.\n", |
---|
103 | at->hesiodname, at->mntpt, buf); |
---|
104 | error_status = ERR_ATTACHINUSE; |
---|
105 | return(FAILURE); |
---|
106 | } |
---|
107 | if ( |
---|
108 | #if defined(_AIX) && (AIXV==12) |
---|
109 | /* AIX 1.x */ |
---|
110 | rmslink(at->mntpt) == -1 && |
---|
111 | #endif |
---|
112 | unlink(at->mntpt) == -1) |
---|
113 | { |
---|
114 | fprintf(stderr, |
---|
115 | "%s: Couldn't remove existing symlink from %s to %s: %s\n", |
---|
116 | at->hesiodname, at->mntpt, buf, sys_errlist[errno]); |
---|
117 | error_status = ERR_ATTACHINUSE; |
---|
118 | return(FAILURE); |
---|
119 | } |
---|
120 | } |
---|
121 | } else if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { |
---|
122 | if (rmdir(at->mntpt)) { |
---|
123 | if (errno == ENOTEMPTY) |
---|
124 | fprintf(stderr, |
---|
125 | "%s: %s is a non-empty directory.\n", |
---|
126 | at->hesiodname, at->mntpt); |
---|
127 | else |
---|
128 | fprintf(stderr, |
---|
129 | "%s: Couldn't rmdir %s (%s)\n", |
---|
130 | at->hesiodname, at->mntpt, |
---|
131 | sys_errlist[errno]); |
---|
132 | error_status = ERR_ATTACHINUSE; |
---|
133 | return(FAILURE); |
---|
134 | } |
---|
135 | } else { |
---|
136 | fprintf(stderr, |
---|
137 | "%s: Couldn't attach; %s already exists.\n", |
---|
138 | at->hesiodname, at->mntpt); |
---|
139 | error_status = ERR_ATTACHINUSE; |
---|
140 | return(FAILURE); |
---|
141 | } |
---|
142 | } |
---|
143 | setreuid(real_uid, effective_uid); |
---|
144 | /* |
---|
145 | * Note: we do our own path canonicalization here, since |
---|
146 | * we have to check the sym link first. |
---|
147 | */ |
---|
148 | (void) strcpy(at->mntpt, path_canon(at->mntpt)); |
---|
149 | if (debug_flag) |
---|
150 | printf("Mountpoint canonicalized as: %s\n", at->mntpt); |
---|
151 | |
---|
152 | if (!override && !check_mountpt(at->mntpt, at->fs->type)) { |
---|
153 | error_status = ERR_ATTACHBADMNTPT; |
---|
154 | return(FAILURE); |
---|
155 | } |
---|
156 | |
---|
157 | if (debug_flag) |
---|
158 | printf("symlinking %s to %s\n", at->hostdir, at->mntpt); |
---|
159 | if (symlink(at->hostdir, at->mntpt) < 0) { |
---|
160 | fprintf(stderr, "%s: ", at->hesiodname); |
---|
161 | perror(at->hostdir); |
---|
162 | /* error_status = ERR_; */ |
---|
163 | return(FAILURE); |
---|
164 | } |
---|
165 | |
---|
166 | return (SUCCESS); |
---|
167 | } |
---|
168 | |
---|
169 | /* |
---|
170 | * afs_auth_internal --- authenticate oneself to the afs system |
---|
171 | * |
---|
172 | * Actually, it also does the zephyr subscriptions, but that's because |
---|
173 | * aklog does all of that stuff. |
---|
174 | */ |
---|
175 | static int afs_auth_internal(errorname, afs_pathname, hostlist, flags) |
---|
176 | char *errorname; |
---|
177 | char *afs_pathname; /* For future expansion */ |
---|
178 | struct in_addr hostlist[]; |
---|
179 | int flags; |
---|
180 | { |
---|
181 | #ifdef POSIX |
---|
182 | int waitb; |
---|
183 | #else |
---|
184 | union wait waitb; |
---|
185 | #endif |
---|
186 | int error_ret; |
---|
187 | int fds[2]; |
---|
188 | FILE *f; |
---|
189 | char buff[512]; |
---|
190 | int host_idx = 0; |
---|
191 | |
---|
192 | if (debug_flag) |
---|
193 | printf("performing an %s %s %s -hosts -zsubs %s\n", aklog_fn, |
---|
194 | flags & AFSAUTH_CELL ? "-cell" : "-path", |
---|
195 | afs_pathname, flags & AFSAUTH_DOAUTH ? "" : "-noauth"); |
---|
196 | |
---|
197 | if (pipe(fds)) { |
---|
198 | perror("afs_auth: pipe"); |
---|
199 | return(FAILURE); |
---|
200 | } |
---|
201 | |
---|
202 | switch(vfork()) { |
---|
203 | case -1: |
---|
204 | close(fds[0]); |
---|
205 | close(fds[1]); |
---|
206 | perror("vfork: to aklog"); |
---|
207 | error_status = ERR_AUTHFAIL; |
---|
208 | return(FAILURE); |
---|
209 | case 0: |
---|
210 | if (!debug_flag) { |
---|
211 | close(0); |
---|
212 | open("/dev/null", O_RDWR, 0644); |
---|
213 | } |
---|
214 | |
---|
215 | close(fds[0]); |
---|
216 | dup2(fds[1], 1); |
---|
217 | close(fds[1]); |
---|
218 | setuid(owner_uid); |
---|
219 | execl(aklog_fn, AKLOG_SHORTNAME, |
---|
220 | flags & AFSAUTH_CELL ? "-cell" : "-path", |
---|
221 | afs_pathname, "-hosts", "-zsubs", |
---|
222 | (flags & AFSAUTH_DOAUTH) ? 0 : "-noauth", 0); |
---|
223 | perror(aklog_fn); |
---|
224 | exit(1); |
---|
225 | /*NOTREACHED*/ |
---|
226 | default: |
---|
227 | close(fds[1]); |
---|
228 | if ((f = fdopen(fds[0], "r")) == NULL) { |
---|
229 | perror("fdopen: to aklog output"); |
---|
230 | return(FAILURE); |
---|
231 | } |
---|
232 | while (fgets(buff, sizeof(buff), f)) { |
---|
233 | char *cp; |
---|
234 | int len; |
---|
235 | |
---|
236 | if (debug_flag) |
---|
237 | fputs(buff, stdout); |
---|
238 | if (!(cp = index(buff, ':'))) |
---|
239 | continue; |
---|
240 | *cp = '\0'; |
---|
241 | #ifdef ZEPHYR |
---|
242 | if (!strcmp(buff, "zsub") && |
---|
243 | (flags & AFSAUTH_DOZEPHYR)) { |
---|
244 | cp++; |
---|
245 | while (*cp && isspace(*cp)) |
---|
246 | cp++; |
---|
247 | for (len=strlen(cp)-1; |
---|
248 | len>=0 && !isprint(cp[len]) |
---|
249 | ; len--) |
---|
250 | cp[len] = '\0'; |
---|
251 | zephyr_addsub(cp); |
---|
252 | } |
---|
253 | #endif |
---|
254 | if (hostlist && !strcmp(buff, "host")) { |
---|
255 | cp++; |
---|
256 | while (*cp && isspace(*cp)) |
---|
257 | cp++; |
---|
258 | for (len=strlen(cp)-1; |
---|
259 | len>=0 && !isprint(cp[len]) |
---|
260 | ; len--) |
---|
261 | cp[len] = '\0'; |
---|
262 | hostlist[host_idx++].s_addr = inet_addr(cp); |
---|
263 | } |
---|
264 | } |
---|
265 | fclose(f); |
---|
266 | if (wait(&waitb) < 0) { |
---|
267 | perror("wait: for aklog"); |
---|
268 | error_status = ERR_AUTHFAIL; |
---|
269 | return(FAILURE); |
---|
270 | } |
---|
271 | } |
---|
272 | |
---|
273 | #ifdef POSIX |
---|
274 | error_ret = waitb; |
---|
275 | #else |
---|
276 | error_ret = waitb.w_retcode; |
---|
277 | #endif |
---|
278 | if (error_ret && (flags & AFSAUTH_DOAUTH)) { |
---|
279 | error_status = ERR_AUTHFAIL; |
---|
280 | return (FAILURE); |
---|
281 | } |
---|
282 | return(SUCCESS); |
---|
283 | } |
---|
284 | |
---|
285 | int afs_auth(hesname, afsdir) |
---|
286 | const char *hesname, *afsdir; |
---|
287 | { |
---|
288 | return(afs_auth_internal(hesname, afsdir, 0, AFSAUTH_DOAUTH)); |
---|
289 | } |
---|
290 | |
---|
291 | /* |
---|
292 | * Parsing of explicit AFS file types |
---|
293 | */ |
---|
294 | char **afs_explicit(name) |
---|
295 | char *name; |
---|
296 | { |
---|
297 | char *dir; |
---|
298 | char newmntpt[BUFSIZ]; |
---|
299 | extern char *exp_hesptr[2]; |
---|
300 | |
---|
301 | if (*name != '/') |
---|
302 | { |
---|
303 | fprintf(stderr, "%s: Illegal explicit definition \"%s\" for type %s\n", |
---|
304 | progname, name, filsys_type); |
---|
305 | return (0); |
---|
306 | } |
---|
307 | |
---|
308 | dir = rindex(name, '/'); |
---|
309 | (void) strcpy(newmntpt, afs_mount_dir); |
---|
310 | (void) strcat(newmntpt, dir); |
---|
311 | |
---|
312 | sprintf(exp_hesline, "AFS %s %c %s", name, override_mode ? |
---|
313 | override_mode : 'w', mntpt ? mntpt : newmntpt); |
---|
314 | exp_hesptr[0] = exp_hesline; |
---|
315 | exp_hesptr[1] = 0; |
---|
316 | return exp_hesptr; |
---|
317 | } |
---|
318 | |
---|
319 | int afs_detach(at) |
---|
320 | struct _attachtab *at; |
---|
321 | { |
---|
322 | if(at->flags & FLAG_PERMANENT) |
---|
323 | return SUCCESS; |
---|
324 | |
---|
325 | if ( |
---|
326 | #if defined(_AIX) && (AIXV==12) |
---|
327 | /* AIX 1.x */ |
---|
328 | rmslink(at->mntpt) == -1 && |
---|
329 | #endif |
---|
330 | unlink(at->mntpt) == -1) |
---|
331 | { |
---|
332 | if(errno == ENOENT) |
---|
333 | { |
---|
334 | fprintf(stderr, "%s: filesystem %s already detached\n", |
---|
335 | progname, at->hesiodname); |
---|
336 | return SUCCESS; |
---|
337 | } |
---|
338 | fprintf(stderr, "%s: detach of filesystem %s failed, unable to remove mountpoint\n\terror is %s\n", |
---|
339 | progname, at->hesiodname, errstr(errno)); |
---|
340 | /* Set error_status? */ |
---|
341 | return FAILURE; |
---|
342 | } |
---|
343 | return SUCCESS; |
---|
344 | } |
---|
345 | |
---|
346 | int afs_auth_to_cell(cell) |
---|
347 | const char *cell; |
---|
348 | { |
---|
349 | return(afs_auth_internal(cell, cell, 0, AFSAUTH_DOAUTH | AFSAUTH_CELL)); |
---|
350 | } |
---|
351 | |
---|
352 | int afs_zinit(hesname, afsdir) |
---|
353 | const char *hesname, *afsdir; |
---|
354 | { |
---|
355 | return(afs_auth_internal(hesname, afsdir, 0, AFSAUTH_DOZEPHYR)); |
---|
356 | } |
---|
357 | #endif /* AFS */ |
---|
358 | |
---|
359 | |
---|