1 | /* |
---|
2 | * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. |
---|
3 | * All rights reserved. |
---|
4 | * |
---|
5 | * By using this file, you agree to the terms and conditions set |
---|
6 | * forth in the LICENSE file which can be found at the top level of |
---|
7 | * the sendmail distribution. |
---|
8 | * |
---|
9 | */ |
---|
10 | |
---|
11 | #include <sm/gen.h> |
---|
12 | SM_RCSID("@(#)$Id: mpeix.c,v 1.1.1.1 2003-04-08 15:07:35 zacheiss Exp $") |
---|
13 | |
---|
14 | #ifdef MPE |
---|
15 | /* |
---|
16 | ** MPE lacks many common functions required across all sendmail programs |
---|
17 | ** so we define implementations for these functions here. |
---|
18 | */ |
---|
19 | |
---|
20 | # include <errno.h> |
---|
21 | # include <fcntl.h> |
---|
22 | # include <limits.h> |
---|
23 | # include <mpe.h> |
---|
24 | # include <netinet/in.h> |
---|
25 | # include <pwd.h> |
---|
26 | # include <sys/socket.h> |
---|
27 | # include <sys/stat.h> |
---|
28 | # include <unistd.h> |
---|
29 | # include <sm/conf.h> |
---|
30 | |
---|
31 | /* |
---|
32 | ** CHROOT -- dummy chroot() function |
---|
33 | ** |
---|
34 | ** The MPE documentation for sendmail says that chroot-based |
---|
35 | ** functionality is not implemented because MPE lacks chroot. But |
---|
36 | ** rather than mucking around with all the sendmail calls to chroot, |
---|
37 | ** we define this dummy function to return an ENOSYS failure just in |
---|
38 | ** case a sendmail user attempts to enable chroot-based functionality. |
---|
39 | ** |
---|
40 | ** Parameters: |
---|
41 | ** path -- pathname of new root (ignored). |
---|
42 | ** |
---|
43 | ** Returns: |
---|
44 | ** -1 and errno == ENOSYS (function not implemented) |
---|
45 | */ |
---|
46 | |
---|
47 | int |
---|
48 | chroot(path) |
---|
49 | char *path; |
---|
50 | { |
---|
51 | errno = ENOSYS; |
---|
52 | return -1; |
---|
53 | } |
---|
54 | |
---|
55 | /* |
---|
56 | ** ENDPWENT -- dummy endpwent() function |
---|
57 | ** |
---|
58 | ** Parameters: |
---|
59 | ** none |
---|
60 | ** |
---|
61 | ** Returns: |
---|
62 | ** none |
---|
63 | */ |
---|
64 | |
---|
65 | void |
---|
66 | endpwent() |
---|
67 | { |
---|
68 | return; |
---|
69 | } |
---|
70 | |
---|
71 | /* |
---|
72 | ** In addition to missing functions, certain existing MPE functions have |
---|
73 | ** slightly different semantics (or bugs) compared to normal Unix OSes. |
---|
74 | ** |
---|
75 | ** Here we define wrappers for these functions to make them behave in the |
---|
76 | ** manner expected by sendmail. |
---|
77 | */ |
---|
78 | |
---|
79 | /* |
---|
80 | ** SENDMAIL_MPE_BIND -- shadow function for the standard socket bind() |
---|
81 | ** |
---|
82 | ** MPE requires GETPRIVMODE() for AF_INET sockets less than port 1024. |
---|
83 | ** |
---|
84 | ** Parameters: |
---|
85 | ** sd -- socket descriptor. |
---|
86 | ** addr -- socket address. |
---|
87 | ** addrlen -- length of socket address. |
---|
88 | ** |
---|
89 | ** Results: |
---|
90 | ** 0 -- success |
---|
91 | ** != 0 -- failure |
---|
92 | */ |
---|
93 | |
---|
94 | #undef bind |
---|
95 | int |
---|
96 | sendmail_mpe_bind(sd, addr, addrlen) |
---|
97 | int sd; |
---|
98 | void *addr; |
---|
99 | int addrlen; |
---|
100 | { |
---|
101 | bool priv = false; |
---|
102 | int result; |
---|
103 | extern void GETPRIVMODE __P((void)); |
---|
104 | extern void GETUSERMODE __P((void)); |
---|
105 | |
---|
106 | if (addrlen == sizeof(struct sockaddr_in) && |
---|
107 | ((struct sockaddr_in *)addr)->sin_family == AF_INET) |
---|
108 | { |
---|
109 | /* AF_INET */ |
---|
110 | if (((struct sockaddr_in *)addr)->sin_port > 0 && |
---|
111 | ((struct sockaddr_in *)addr)->sin_port < 1024) |
---|
112 | { |
---|
113 | priv = true; |
---|
114 | GETPRIVMODE(); |
---|
115 | } |
---|
116 | ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0; |
---|
117 | result = bind(sd, addr, addrlen); |
---|
118 | if (priv) |
---|
119 | GETUSERMODE(); |
---|
120 | return result; |
---|
121 | } |
---|
122 | |
---|
123 | /* AF_UNIX */ |
---|
124 | return bind(sd, addr, addrlen); |
---|
125 | } |
---|
126 | |
---|
127 | /* |
---|
128 | ** SENDMAIL_MPE__EXIT -- wait for children to terminate, then _exit() |
---|
129 | ** |
---|
130 | ** Child processes cannot survive the death of their parent on MPE, so |
---|
131 | ** we must call wait() before _exit() in order to prevent this |
---|
132 | ** infanticide. |
---|
133 | ** |
---|
134 | ** Parameters: |
---|
135 | ** status -- _exit status value. |
---|
136 | ** |
---|
137 | ** Returns: |
---|
138 | ** none. |
---|
139 | */ |
---|
140 | |
---|
141 | #undef _exit |
---|
142 | void |
---|
143 | sendmail_mpe__exit(status) |
---|
144 | int status; |
---|
145 | { |
---|
146 | int result; |
---|
147 | |
---|
148 | /* Wait for all children to terminate. */ |
---|
149 | do |
---|
150 | { |
---|
151 | result = wait(NULL); |
---|
152 | } while (result > 0 || errno == EINTR); |
---|
153 | _exit(status); |
---|
154 | } |
---|
155 | |
---|
156 | /* |
---|
157 | ** SENDMAIL_MPE_EXIT -- wait for children to terminate, then exit() |
---|
158 | ** |
---|
159 | ** Child processes cannot survive the death of their parent on MPE, so |
---|
160 | ** we must call wait() before exit() in order to prevent this |
---|
161 | ** infanticide. |
---|
162 | ** |
---|
163 | ** Parameters: |
---|
164 | ** status -- exit status value. |
---|
165 | ** |
---|
166 | ** Returns: |
---|
167 | ** none. |
---|
168 | */ |
---|
169 | |
---|
170 | #undef exit |
---|
171 | void |
---|
172 | sendmail_mpe_exit(status) |
---|
173 | int status; |
---|
174 | { |
---|
175 | int result; |
---|
176 | |
---|
177 | /* Wait for all children to terminate. */ |
---|
178 | do |
---|
179 | { |
---|
180 | result = wait(NULL); |
---|
181 | } while (result > 0 || errno == EINTR); |
---|
182 | exit(status); |
---|
183 | } |
---|
184 | |
---|
185 | /* |
---|
186 | ** SENDMAIL_MPE_FCNTL -- shadow function for fcntl() |
---|
187 | ** |
---|
188 | ** MPE requires sfcntl() for sockets, and fcntl() for everything |
---|
189 | ** else. This shadow routine determines the descriptor type and |
---|
190 | ** makes the appropriate call. |
---|
191 | ** |
---|
192 | ** Parameters: |
---|
193 | ** same as fcntl(). |
---|
194 | ** |
---|
195 | ** Returns: |
---|
196 | ** same as fcntl(). |
---|
197 | */ |
---|
198 | |
---|
199 | #undef fcntl |
---|
200 | int |
---|
201 | sendmail_mpe_fcntl(int fildes, int cmd, ...) |
---|
202 | { |
---|
203 | int len, result; |
---|
204 | struct sockaddr sa; |
---|
205 | |
---|
206 | void *arg; |
---|
207 | va_list ap; |
---|
208 | |
---|
209 | va_start(ap, cmd); |
---|
210 | arg = va_arg(ap, void *); |
---|
211 | va_end(ap); |
---|
212 | |
---|
213 | len = sizeof sa; |
---|
214 | if (getsockname(fildes, &sa, &len) == -1) |
---|
215 | { |
---|
216 | if (errno == EAFNOSUPPORT) |
---|
217 | { |
---|
218 | /* AF_UNIX socket */ |
---|
219 | return sfcntl(fildes, cmd, arg); |
---|
220 | } |
---|
221 | else if (errno == ENOTSOCK) |
---|
222 | { |
---|
223 | /* file or pipe */ |
---|
224 | return fcntl(fildes, cmd, arg); |
---|
225 | } |
---|
226 | |
---|
227 | /* unknown getsockname() failure */ |
---|
228 | return (-1); |
---|
229 | } |
---|
230 | else |
---|
231 | { |
---|
232 | /* AF_INET socket */ |
---|
233 | if ((result = sfcntl(fildes, cmd, arg)) != -1 && |
---|
234 | cmd == F_GETFL) |
---|
235 | result |= O_RDWR; /* fill in some missing flags */ |
---|
236 | return result; |
---|
237 | } |
---|
238 | } |
---|
239 | |
---|
240 | /* |
---|
241 | ** SENDMAIL_MPE_GETPWNAM - shadow function for getpwnam() |
---|
242 | ** |
---|
243 | ** Several issues apply here: |
---|
244 | ** |
---|
245 | ** - MPE user names MUST have one '.' separator character |
---|
246 | ** - MPE user names MUST be in upper case |
---|
247 | ** - MPE does not initialize all fields in the passwd struct |
---|
248 | ** |
---|
249 | ** Parameters: |
---|
250 | ** name -- username string. |
---|
251 | ** |
---|
252 | ** Returns: |
---|
253 | ** pointer to struct passwd if found else NULL |
---|
254 | */ |
---|
255 | |
---|
256 | static char *sendmail_mpe_nullstr = ""; |
---|
257 | |
---|
258 | #undef getpwnam |
---|
259 | extern struct passwd *getpwnam(const char *); |
---|
260 | |
---|
261 | struct passwd * |
---|
262 | sendmail_mpe_getpwnam(name) |
---|
263 | const char *name; |
---|
264 | { |
---|
265 | int dots = 0; |
---|
266 | int err; |
---|
267 | int i = strlen(name); |
---|
268 | char *upper; |
---|
269 | struct passwd *result = NULL; |
---|
270 | |
---|
271 | if (i <= 0) |
---|
272 | { |
---|
273 | errno = EINVAL; |
---|
274 | return result; |
---|
275 | } |
---|
276 | |
---|
277 | if ((upper = (char *)malloc(i + 1)) != NULL) |
---|
278 | { |
---|
279 | /* upshift the username parameter and count the dots */ |
---|
280 | while (i >= 0) |
---|
281 | { |
---|
282 | if (name[i] == '.') |
---|
283 | { |
---|
284 | dots++; |
---|
285 | upper[i] = '.'; |
---|
286 | } |
---|
287 | else |
---|
288 | upper[i] = toupper(name[i]); |
---|
289 | i--; |
---|
290 | } |
---|
291 | |
---|
292 | if (dots != 1) |
---|
293 | { |
---|
294 | /* prevent bug when dots == 0 */ |
---|
295 | err = EINVAL; |
---|
296 | } |
---|
297 | else if ((result = getpwnam(upper)) != NULL) |
---|
298 | { |
---|
299 | /* init the uninitialized fields */ |
---|
300 | result->pw_gecos = sendmail_mpe_nullstr; |
---|
301 | result->pw_passwd = sendmail_mpe_nullstr; |
---|
302 | result->pw_age = sendmail_mpe_nullstr; |
---|
303 | result->pw_comment = sendmail_mpe_nullstr; |
---|
304 | result->pw_audid = 0; |
---|
305 | result->pw_audflg = 0; |
---|
306 | } |
---|
307 | err = errno; |
---|
308 | free(upper); |
---|
309 | } |
---|
310 | errno = err; |
---|
311 | return result; |
---|
312 | } |
---|
313 | |
---|
314 | /* |
---|
315 | ** SENDMAIL_MPE_GETPWUID -- shadow function for getpwuid() |
---|
316 | ** |
---|
317 | ** Initializes the uninitalized fields in the passwd struct. |
---|
318 | ** |
---|
319 | ** Parameters: |
---|
320 | ** uid -- uid to obtain passwd data for |
---|
321 | ** |
---|
322 | ** Returns: |
---|
323 | ** pointer to struct passwd or NULL if not found |
---|
324 | */ |
---|
325 | |
---|
326 | #undef getpwuid |
---|
327 | extern struct passwd *getpwuid __P((uid_t)); |
---|
328 | |
---|
329 | struct passwd * |
---|
330 | sendmail_mpe_getpwuid(uid) |
---|
331 | uid_t uid; |
---|
332 | { |
---|
333 | struct passwd *result; |
---|
334 | |
---|
335 | if ((result = getpwuid(uid)) != NULL) |
---|
336 | { |
---|
337 | /* initialize the uninitialized fields */ |
---|
338 | result->pw_gecos = sendmail_mpe_nullstr; |
---|
339 | result->pw_passwd = sendmail_mpe_nullstr; |
---|
340 | result->pw_age = sendmail_mpe_nullstr; |
---|
341 | result->pw_comment = sendmail_mpe_nullstr; |
---|
342 | result->pw_audid = 0; |
---|
343 | result->pw_audflg = 0; |
---|
344 | } |
---|
345 | return result; |
---|
346 | } |
---|
347 | |
---|
348 | /* |
---|
349 | ** OK boys and girls, time for some serious voodoo! |
---|
350 | ** |
---|
351 | ** MPE does not have a complete implementation of POSIX users and groups: |
---|
352 | ** |
---|
353 | ** - there is no uid 0 superuser |
---|
354 | ** - setuid/setgid file permission bits exist but have no-op functionality |
---|
355 | ** - setgid() exists, but only supports new gid == current gid (boring!) |
---|
356 | ** - setuid() forces a gid change to the new uid's primary (and only) gid |
---|
357 | ** |
---|
358 | ** ...all of which thoroughly annoys sendmail. |
---|
359 | ** |
---|
360 | ** So what to do? We can't go on an #ifdef MPE rampage throughout |
---|
361 | ** sendmail, because there are only about a zillion references to uid 0 |
---|
362 | ** and so success (and security) would probably be rather dubious by the |
---|
363 | ** time we finished. |
---|
364 | ** |
---|
365 | ** Instead we take the approach of defining wrapper functions for the |
---|
366 | ** gid/uid management functions getegid(), geteuid(), setgid(), and |
---|
367 | ** setuid() in order to implement the following model: |
---|
368 | ** |
---|
369 | ** - the sendmail program thinks it is a setuid-root (uid 0) program |
---|
370 | ** - uid 0 is recognized as being valid, but does not grant extra powers |
---|
371 | ** - MPE priv mode allows sendmail to call setuid(), not uid 0 |
---|
372 | ** - file access is still controlled by the real non-zero uid |
---|
373 | ** - the other programs (vacation, etc) have standard MPE POSIX behavior |
---|
374 | ** |
---|
375 | ** This emulation model is activated by use of the program file setgid and |
---|
376 | ** setuid mode bits which exist but are unused by MPE. If the setgid mode |
---|
377 | ** bit is on, then gid emulation will be enabled. If the setuid mode bit is |
---|
378 | ** on, then uid emulation will be enabled. So for the mail daemon, we need |
---|
379 | ** to do chmod u+s,g+s /SENDMAIL/CURRENT/SENDMAIL. |
---|
380 | ** |
---|
381 | ** The following flags determine the current emulation state: |
---|
382 | ** |
---|
383 | ** true == emulation enabled |
---|
384 | ** false == emulation disabled, use unmodified MPE semantics |
---|
385 | */ |
---|
386 | |
---|
387 | static bool sendmail_mpe_flaginit = false; |
---|
388 | static bool sendmail_mpe_gidflag = false; |
---|
389 | static bool sendmail_mpe_uidflag = false; |
---|
390 | |
---|
391 | /* |
---|
392 | ** SENDMAIL_MPE_GETMODE -- return the mode bits for the current process |
---|
393 | ** |
---|
394 | ** Parameters: |
---|
395 | ** none. |
---|
396 | ** |
---|
397 | ** Returns: |
---|
398 | ** file mode bits for the current process program file. |
---|
399 | */ |
---|
400 | |
---|
401 | mode_t |
---|
402 | sendmail_mpe_getmode() |
---|
403 | { |
---|
404 | int status = 666; |
---|
405 | int myprogram_length; |
---|
406 | int myprogram_syntax = 2; |
---|
407 | char formaldesig[28]; |
---|
408 | char myprogram[PATH_MAX + 2]; |
---|
409 | char path[PATH_MAX + 1]; |
---|
410 | struct stat st; |
---|
411 | extern HPMYPROGRAM __P((int parms, char *formaldesig, int *status, |
---|
412 | int *length, char *myprogram, |
---|
413 | int *myprogram_length, int *myprogram_syntax)); |
---|
414 | |
---|
415 | myprogram_length = sizeof(myprogram); |
---|
416 | HPMYPROGRAM(6, formaldesig, &status, NULL, myprogram, |
---|
417 | &myprogram_length, &myprogram_syntax); |
---|
418 | |
---|
419 | /* should not occur, do not attempt emulation */ |
---|
420 | if (status != 0) |
---|
421 | return 0; |
---|
422 | |
---|
423 | memcpy(&path, &myprogram[1], myprogram_length - 2); |
---|
424 | path[myprogram_length - 2] = '\0'; |
---|
425 | |
---|
426 | /* should not occur, do not attempt emulation */ |
---|
427 | if (stat(path, &st) < 0) |
---|
428 | return 0; |
---|
429 | |
---|
430 | return st.st_mode; |
---|
431 | } |
---|
432 | |
---|
433 | /* |
---|
434 | ** SENDMAIL_MPE_EMULGID -- should we perform gid emulation? |
---|
435 | ** |
---|
436 | ** If !sendmail_mpe_flaginit then obtain the mode bits to determine |
---|
437 | ** if the setgid bit is on, we want gid emulation and so set |
---|
438 | ** sendmail_mpe_gidflag to true. Otherwise we do not want gid emulation |
---|
439 | ** and so set sendmail_mpe_gidflag to false. |
---|
440 | ** |
---|
441 | ** Parameters: |
---|
442 | ** none. |
---|
443 | ** |
---|
444 | ** Returns: |
---|
445 | ** true -- perform gid emulation |
---|
446 | ** false -- do not perform gid emulation |
---|
447 | */ |
---|
448 | |
---|
449 | bool |
---|
450 | sendmail_mpe_emulgid() |
---|
451 | { |
---|
452 | if (!sendmail_mpe_flaginit) |
---|
453 | { |
---|
454 | mode_t mode; |
---|
455 | |
---|
456 | mode = sendmail_mpe_getmode(); |
---|
457 | sendmail_mpe_gidflag = ((mode & S_ISGID) == S_ISGID); |
---|
458 | sendmail_mpe_uidflag = ((mode & S_ISUID) == S_ISUID); |
---|
459 | sendmail_mpe_flaginit = true; |
---|
460 | } |
---|
461 | return sendmail_mpe_gidflag; |
---|
462 | } |
---|
463 | |
---|
464 | /* |
---|
465 | ** SENDMAIL_MPE_EMULUID -- should we perform uid emulation? |
---|
466 | ** |
---|
467 | ** If sendmail_mpe_uidflag == -1 then obtain the mode bits to determine |
---|
468 | ** if the setuid bit is on, we want uid emulation and so set |
---|
469 | ** sendmail_mpe_uidflag to true. Otherwise we do not want uid emulation |
---|
470 | ** and so set sendmail_mpe_uidflag to false. |
---|
471 | ** |
---|
472 | ** Parameters: |
---|
473 | ** none. |
---|
474 | ** |
---|
475 | ** Returns: |
---|
476 | ** true -- perform uid emulation |
---|
477 | ** false -- do not perform uid emulation |
---|
478 | */ |
---|
479 | |
---|
480 | bool |
---|
481 | sendmail_mpe_emuluid() |
---|
482 | { |
---|
483 | if (!sendmail_mpe_flaginit) |
---|
484 | { |
---|
485 | mode_t mode; |
---|
486 | |
---|
487 | mode = sendmail_mpe_getmode(); |
---|
488 | sendmail_mpe_gidflag = ((mode & S_ISGID) == S_ISGID); |
---|
489 | sendmail_mpe_uidflag = ((mode & S_ISUID) == S_ISUID); |
---|
490 | sendmail_mpe_flaginit = true; |
---|
491 | } |
---|
492 | return sendmail_mpe_uidflag; |
---|
493 | } |
---|
494 | |
---|
495 | /* |
---|
496 | ** SENDMAIL_MPE_GETEGID -- shadow function for getegid() |
---|
497 | ** |
---|
498 | ** If emulation mode is in effect and the saved egid has been |
---|
499 | ** initialized, return the saved egid; otherwise return the value of the |
---|
500 | ** real getegid() function. |
---|
501 | ** |
---|
502 | ** Parameters: |
---|
503 | ** none. |
---|
504 | ** |
---|
505 | ** Returns: |
---|
506 | ** emulated egid if present, else true egid. |
---|
507 | */ |
---|
508 | |
---|
509 | static uid_t sendmail_mpe_egid = -1; |
---|
510 | |
---|
511 | #undef getegid |
---|
512 | gid_t |
---|
513 | sendmail_mpe_getegid() |
---|
514 | { |
---|
515 | if (sendmail_mpe_emulgid() && sendmail_mpe_egid != -1) |
---|
516 | return sendmail_mpe_egid; |
---|
517 | return getegid(); |
---|
518 | } |
---|
519 | |
---|
520 | /* |
---|
521 | ** SENDMAIL_MPE_GETEUID -- shadow function for geteuid() |
---|
522 | ** |
---|
523 | ** If emulation mode is in effect, return the saved euid; otherwise |
---|
524 | ** return the value of the real geteuid() function. |
---|
525 | ** |
---|
526 | ** Note that the initial value of the saved euid is zero, to simulate |
---|
527 | ** a setuid-root program. |
---|
528 | ** |
---|
529 | ** Parameters: |
---|
530 | ** none |
---|
531 | ** |
---|
532 | ** Returns: |
---|
533 | ** emulated euid if in emulation mode, else true euid. |
---|
534 | */ |
---|
535 | |
---|
536 | static uid_t sendmail_mpe_euid = 0; |
---|
537 | |
---|
538 | #undef geteuid |
---|
539 | uid_t |
---|
540 | sendmail_mpe_geteuid() |
---|
541 | { |
---|
542 | if (sendmail_mpe_emuluid()) |
---|
543 | return sendmail_mpe_euid; |
---|
544 | return geteuid(); |
---|
545 | } |
---|
546 | |
---|
547 | /* |
---|
548 | ** SENDMAIL_MPE_SETGID -- shadow function for setgid() |
---|
549 | ** |
---|
550 | ** Simulate a call to setgid() without actually calling the real |
---|
551 | ** function. Implement the expected uid 0 semantics. |
---|
552 | ** |
---|
553 | ** Note that sendmail will also be calling setuid() which will force an |
---|
554 | ** implicit real setgid() to the proper primary gid. So it doesn't matter |
---|
555 | ** that we don't actually alter the real gid in this shadow function. |
---|
556 | ** |
---|
557 | ** Parameters: |
---|
558 | ** gid -- desired gid. |
---|
559 | ** |
---|
560 | ** Returns: |
---|
561 | ** 0 -- emulated success |
---|
562 | ** -1 -- emulated failure |
---|
563 | */ |
---|
564 | |
---|
565 | #undef setgid |
---|
566 | int |
---|
567 | sendmail_mpe_setgid(gid) |
---|
568 | gid_t gid; |
---|
569 | { |
---|
570 | if (sendmail_mpe_emulgid()) |
---|
571 | { |
---|
572 | if (gid == getgid() || sendmail_mpe_euid == 0) |
---|
573 | { |
---|
574 | sendmail_mpe_egid = gid; |
---|
575 | return 0; |
---|
576 | } |
---|
577 | errno = EINVAL; |
---|
578 | return -1; |
---|
579 | } |
---|
580 | return setgid(gid); |
---|
581 | } |
---|
582 | |
---|
583 | /* |
---|
584 | ** SENDMAIL_MPE_SETUID -- shadow function for setuid() |
---|
585 | ** |
---|
586 | ** setuid() is broken as of MPE 7.0 in that it changes the current |
---|
587 | ** working directory to be the home directory of the new uid. Thus |
---|
588 | ** we must obtain the cwd and restore it after the setuid(). |
---|
589 | ** |
---|
590 | ** Note that expected uid 0 semantics have been added, as well as |
---|
591 | ** remembering the new uid for later use by the other shadow functions. |
---|
592 | ** |
---|
593 | ** Parameters: |
---|
594 | ** uid -- desired uid. |
---|
595 | ** |
---|
596 | ** Returns: |
---|
597 | ** 0 -- success |
---|
598 | ** -1 -- failure |
---|
599 | ** |
---|
600 | ** Globals: |
---|
601 | ** sendmail_mpe_euid |
---|
602 | */ |
---|
603 | |
---|
604 | #undef setuid |
---|
605 | int |
---|
606 | sendmail_mpe_setuid(uid) |
---|
607 | uid_t uid; |
---|
608 | { |
---|
609 | char *cwd; |
---|
610 | char cwd_buf[PATH_MAX + 1]; |
---|
611 | int result; |
---|
612 | extern void GETPRIVMODE __P((void)); |
---|
613 | extern void GETUSERMODE __P((void)); |
---|
614 | |
---|
615 | if (sendmail_mpe_emuluid()) |
---|
616 | { |
---|
617 | if (uid == 0) |
---|
618 | { |
---|
619 | if (sendmail_mpe_euid != 0) |
---|
620 | { |
---|
621 | errno = EINVAL; |
---|
622 | return -1; |
---|
623 | } |
---|
624 | sendmail_mpe_euid = 0; |
---|
625 | return 0; |
---|
626 | } |
---|
627 | |
---|
628 | /* Preserve the current working directory */ |
---|
629 | if ((cwd = getcwd(cwd_buf, PATH_MAX + 1)) == NULL) |
---|
630 | return -1; |
---|
631 | |
---|
632 | GETPRIVMODE(); |
---|
633 | result = setuid(uid); |
---|
634 | GETUSERMODE(); |
---|
635 | |
---|
636 | /* Restore the current working directory */ |
---|
637 | chdir(cwd_buf); |
---|
638 | |
---|
639 | if (result == 0) |
---|
640 | sendmail_mpe_euid = uid; |
---|
641 | |
---|
642 | return result; |
---|
643 | } |
---|
644 | return setuid(uid); |
---|
645 | } |
---|
646 | #endif /* MPE */ |
---|