Revert "usbd - Do not start moused by default when a usb mouse is connected"
[dragonfly.git] / contrib / sendmail-8.14 / libsm / mpeix.c
blob163dfbac6755eb61137f870c0530e539f555fb80
1 /*
2 * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
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.
9 */
11 #include <sm/gen.h>
12 SM_RCSID("@(#)$Id: mpeix.c,v 1.7 2007/05/11 18:51:22 gshapiro Exp $")
14 #ifdef MPE
16 ** MPE lacks many common functions required across all sendmail programs
17 ** so we define implementations for these functions here.
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>
32 ** CHROOT -- dummy chroot() function
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.
40 ** Parameters:
41 ** path -- pathname of new root (ignored).
43 ** Returns:
44 ** -1 and errno == ENOSYS (function not implemented)
47 int
48 chroot(path)
49 char *path;
51 errno = ENOSYS;
52 return -1;
56 ** ENDPWENT -- dummy endpwent() function
58 ** Parameters:
59 ** none
61 ** Returns:
62 ** none
65 void
66 endpwent()
68 return;
72 ** In addition to missing functions, certain existing MPE functions have
73 ** slightly different semantics (or bugs) compared to normal Unix OSes.
75 ** Here we define wrappers for these functions to make them behave in the
76 ** manner expected by sendmail.
80 ** SENDMAIL_MPE_BIND -- shadow function for the standard socket bind()
82 ** MPE requires GETPRIVMODE() for AF_INET sockets less than port 1024.
84 ** Parameters:
85 ** sd -- socket descriptor.
86 ** addr -- socket address.
87 ** addrlen -- length of socket address.
89 ** Results:
90 ** 0 -- success
91 ** != 0 -- failure
94 #undef bind
95 int
96 sendmail_mpe_bind(sd, addr, addrlen)
97 int sd;
98 void *addr;
99 int addrlen;
101 bool priv = false;
102 int result;
103 extern void GETPRIVMODE __P((void));
104 extern void GETUSERMODE __P((void));
106 if (addrlen == sizeof(struct sockaddr_in) &&
107 ((struct sockaddr_in *)addr)->sin_family == AF_INET)
109 /* AF_INET */
110 if (((struct sockaddr_in *)addr)->sin_port > 0 &&
111 ((struct sockaddr_in *)addr)->sin_port < 1024)
113 priv = true;
114 GETPRIVMODE();
116 ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0;
117 result = bind(sd, addr, addrlen);
118 if (priv)
119 GETUSERMODE();
120 return result;
123 /* AF_UNIX */
124 return bind(sd, addr, addrlen);
128 ** SENDMAIL_MPE__EXIT -- wait for children to terminate, then _exit()
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.
134 ** Parameters:
135 ** status -- _exit status value.
137 ** Returns:
138 ** none.
141 #undef _exit
142 void
143 sendmail_mpe__exit(status)
144 int status;
146 int result;
148 /* Wait for all children to terminate. */
151 result = wait(NULL);
152 } while (result > 0 || errno == EINTR);
153 _exit(status);
157 ** SENDMAIL_MPE_EXIT -- wait for children to terminate, then exit()
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.
163 ** Parameters:
164 ** status -- exit status value.
166 ** Returns:
167 ** none.
170 #undef exit
171 void
172 sendmail_mpe_exit(status)
173 int status;
175 int result;
177 /* Wait for all children to terminate. */
180 result = wait(NULL);
181 } while (result > 0 || errno == EINTR);
182 exit(status);
186 ** SENDMAIL_MPE_FCNTL -- shadow function for fcntl()
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.
192 ** Parameters:
193 ** same as fcntl().
195 ** Returns:
196 ** same as fcntl().
199 #undef fcntl
201 sendmail_mpe_fcntl(int fildes, int cmd, ...)
203 int len, result;
204 struct sockaddr sa;
206 void *arg;
207 va_list ap;
209 va_start(ap, cmd);
210 arg = va_arg(ap, void *);
211 va_end(ap);
213 len = sizeof sa;
214 if (getsockname(fildes, &sa, &len) == -1)
216 if (errno == EAFNOSUPPORT)
218 /* AF_UNIX socket */
219 return sfcntl(fildes, cmd, arg);
221 else if (errno == ENOTSOCK)
223 /* file or pipe */
224 return fcntl(fildes, cmd, arg);
227 /* unknown getsockname() failure */
228 return (-1);
230 else
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;
241 ** SENDMAIL_MPE_GETPWNAM - shadow function for getpwnam()
243 ** Several issues apply here:
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
249 ** Parameters:
250 ** name -- username string.
252 ** Returns:
253 ** pointer to struct passwd if found else NULL
256 static char *sendmail_mpe_nullstr = "";
258 #undef getpwnam
259 extern struct passwd *getpwnam(const char *);
261 struct passwd *
262 sendmail_mpe_getpwnam(name)
263 const char *name;
265 int dots = 0;
266 int err;
267 int i = strlen(name);
268 char *upper;
269 struct passwd *result = NULL;
271 if (i <= 0)
273 errno = EINVAL;
274 return result;
277 if ((upper = (char *)malloc(i + 1)) != NULL)
279 /* upshift the username parameter and count the dots */
280 while (i >= 0)
282 if (name[i] == '.')
284 dots++;
285 upper[i] = '.';
287 else
288 upper[i] = toupper(name[i]);
289 i--;
292 if (dots != 1)
294 /* prevent bug when dots == 0 */
295 err = EINVAL;
297 else if ((result = getpwnam(upper)) != NULL)
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;
307 err = errno;
308 free(upper);
310 errno = err;
311 return result;
315 ** SENDMAIL_MPE_GETPWUID -- shadow function for getpwuid()
317 ** Initializes the uninitalized fields in the passwd struct.
319 ** Parameters:
320 ** uid -- uid to obtain passwd data for
322 ** Returns:
323 ** pointer to struct passwd or NULL if not found
326 #undef getpwuid
327 extern struct passwd *getpwuid __P((uid_t));
329 struct passwd *
330 sendmail_mpe_getpwuid(uid)
331 uid_t uid;
333 struct passwd *result;
335 if ((result = getpwuid(uid)) != NULL)
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;
345 return result;
349 ** OK boys and girls, time for some serious voodoo!
351 ** MPE does not have a complete implementation of POSIX users and groups:
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
358 ** ...all of which thoroughly annoys sendmail.
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.
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:
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
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.
381 ** The following flags determine the current emulation state:
383 ** true == emulation enabled
384 ** false == emulation disabled, use unmodified MPE semantics
387 static bool sendmail_mpe_flaginit = false;
388 static bool sendmail_mpe_gidflag = false;
389 static bool sendmail_mpe_uidflag = false;
392 ** SENDMAIL_MPE_GETMODE -- return the mode bits for the current process
394 ** Parameters:
395 ** none.
397 ** Returns:
398 ** file mode bits for the current process program file.
401 mode_t
402 sendmail_mpe_getmode()
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));
415 myprogram_length = sizeof(myprogram);
416 HPMYPROGRAM(6, formaldesig, &status, NULL, myprogram,
417 &myprogram_length, &myprogram_syntax);
419 /* should not occur, do not attempt emulation */
420 if (status != 0)
421 return 0;
423 memcpy(&path, &myprogram[1], myprogram_length - 2);
424 path[myprogram_length - 2] = '\0';
426 /* should not occur, do not attempt emulation */
427 if (stat(path, &st) < 0)
428 return 0;
430 return st.st_mode;
434 ** SENDMAIL_MPE_EMULGID -- should we perform gid emulation?
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.
441 ** Parameters:
442 ** none.
444 ** Returns:
445 ** true -- perform gid emulation
446 ** false -- do not perform gid emulation
449 bool
450 sendmail_mpe_emulgid()
452 if (!sendmail_mpe_flaginit)
454 mode_t mode;
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;
461 return sendmail_mpe_gidflag;
465 ** SENDMAIL_MPE_EMULUID -- should we perform uid emulation?
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.
472 ** Parameters:
473 ** none.
475 ** Returns:
476 ** true -- perform uid emulation
477 ** false -- do not perform uid emulation
480 bool
481 sendmail_mpe_emuluid()
483 if (!sendmail_mpe_flaginit)
485 mode_t mode;
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;
492 return sendmail_mpe_uidflag;
496 ** SENDMAIL_MPE_GETEGID -- shadow function for getegid()
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.
502 ** Parameters:
503 ** none.
505 ** Returns:
506 ** emulated egid if present, else true egid.
509 static gid_t sendmail_mpe_egid = -1;
511 #undef getegid
512 gid_t
513 sendmail_mpe_getegid()
515 if (sendmail_mpe_emulgid() && sendmail_mpe_egid != -1)
516 return sendmail_mpe_egid;
517 return getegid();
521 ** SENDMAIL_MPE_GETEUID -- shadow function for geteuid()
523 ** If emulation mode is in effect, return the saved euid; otherwise
524 ** return the value of the real geteuid() function.
526 ** Note that the initial value of the saved euid is zero, to simulate
527 ** a setuid-root program.
529 ** Parameters:
530 ** none
532 ** Returns:
533 ** emulated euid if in emulation mode, else true euid.
536 static uid_t sendmail_mpe_euid = 0;
538 #undef geteuid
539 uid_t
540 sendmail_mpe_geteuid()
542 if (sendmail_mpe_emuluid())
543 return sendmail_mpe_euid;
544 return geteuid();
548 ** SENDMAIL_MPE_SETGID -- shadow function for setgid()
550 ** Simulate a call to setgid() without actually calling the real
551 ** function. Implement the expected uid 0 semantics.
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.
557 ** Parameters:
558 ** gid -- desired gid.
560 ** Returns:
561 ** 0 -- emulated success
562 ** -1 -- emulated failure
565 #undef setgid
567 sendmail_mpe_setgid(gid)
568 gid_t gid;
570 if (sendmail_mpe_emulgid())
572 if (gid == getgid() || sendmail_mpe_euid == 0)
574 sendmail_mpe_egid = gid;
575 return 0;
577 errno = EINVAL;
578 return -1;
580 return setgid(gid);
584 ** SENDMAIL_MPE_SETUID -- shadow function for setuid()
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().
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.
593 ** Parameters:
594 ** uid -- desired uid.
596 ** Returns:
597 ** 0 -- success
598 ** -1 -- failure
600 ** Globals:
601 ** sendmail_mpe_euid
604 #undef setuid
606 sendmail_mpe_setuid(uid)
607 uid_t uid;
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));
615 if (sendmail_mpe_emuluid())
617 if (uid == 0)
619 if (sendmail_mpe_euid != 0)
621 errno = EINVAL;
622 return -1;
624 sendmail_mpe_euid = 0;
625 return 0;
628 /* Preserve the current working directory */
629 if ((cwd = getcwd(cwd_buf, PATH_MAX + 1)) == NULL)
630 return -1;
632 GETPRIVMODE();
633 result = setuid(uid);
634 GETUSERMODE();
636 /* Restore the current working directory */
637 chdir(cwd_buf);
639 if (result == 0)
640 sendmail_mpe_euid = uid;
642 return result;
644 return setuid(uid);
646 #endif /* MPE */