140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 2001-2002 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro * All rights reserved.
440266059SGregory Neil Shapiro *
540266059SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro * the sendmail distribution.
840266059SGregory Neil Shapiro *
940266059SGregory Neil Shapiro */
1040266059SGregory Neil Shapiro
1140266059SGregory Neil Shapiro #include <sm/gen.h>
124313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: mpeix.c,v 1.8 2013-11-22 20:51:43 ca Exp $")
1340266059SGregory Neil Shapiro
1440266059SGregory Neil Shapiro #ifdef MPE
1540266059SGregory Neil Shapiro /*
1640266059SGregory Neil Shapiro ** MPE lacks many common functions required across all sendmail programs
1740266059SGregory Neil Shapiro ** so we define implementations for these functions here.
1840266059SGregory Neil Shapiro */
1940266059SGregory Neil Shapiro
2040266059SGregory Neil Shapiro # include <errno.h>
2140266059SGregory Neil Shapiro # include <fcntl.h>
2240266059SGregory Neil Shapiro # include <limits.h>
2340266059SGregory Neil Shapiro # include <mpe.h>
2440266059SGregory Neil Shapiro # include <netinet/in.h>
2540266059SGregory Neil Shapiro # include <pwd.h>
2640266059SGregory Neil Shapiro # include <sys/socket.h>
2740266059SGregory Neil Shapiro # include <sys/stat.h>
2840266059SGregory Neil Shapiro # include <unistd.h>
2940266059SGregory Neil Shapiro # include <sm/conf.h>
3040266059SGregory Neil Shapiro
3140266059SGregory Neil Shapiro /*
3240266059SGregory Neil Shapiro ** CHROOT -- dummy chroot() function
3340266059SGregory Neil Shapiro **
3440266059SGregory Neil Shapiro ** The MPE documentation for sendmail says that chroot-based
3540266059SGregory Neil Shapiro ** functionality is not implemented because MPE lacks chroot. But
3640266059SGregory Neil Shapiro ** rather than mucking around with all the sendmail calls to chroot,
3740266059SGregory Neil Shapiro ** we define this dummy function to return an ENOSYS failure just in
3840266059SGregory Neil Shapiro ** case a sendmail user attempts to enable chroot-based functionality.
3940266059SGregory Neil Shapiro **
4040266059SGregory Neil Shapiro ** Parameters:
4140266059SGregory Neil Shapiro ** path -- pathname of new root (ignored).
4240266059SGregory Neil Shapiro **
4340266059SGregory Neil Shapiro ** Returns:
4440266059SGregory Neil Shapiro ** -1 and errno == ENOSYS (function not implemented)
4540266059SGregory Neil Shapiro */
4640266059SGregory Neil Shapiro
4740266059SGregory Neil Shapiro int
4840266059SGregory Neil Shapiro chroot(path)
4940266059SGregory Neil Shapiro char *path;
5040266059SGregory Neil Shapiro {
5140266059SGregory Neil Shapiro errno = ENOSYS;
5240266059SGregory Neil Shapiro return -1;
5340266059SGregory Neil Shapiro }
5440266059SGregory Neil Shapiro
5540266059SGregory Neil Shapiro /*
5640266059SGregory Neil Shapiro ** ENDPWENT -- dummy endpwent() function
5740266059SGregory Neil Shapiro **
5840266059SGregory Neil Shapiro ** Parameters:
5940266059SGregory Neil Shapiro ** none
6040266059SGregory Neil Shapiro **
6140266059SGregory Neil Shapiro ** Returns:
6240266059SGregory Neil Shapiro ** none
6340266059SGregory Neil Shapiro */
6440266059SGregory Neil Shapiro
6540266059SGregory Neil Shapiro void
endpwent()6640266059SGregory Neil Shapiro endpwent()
6740266059SGregory Neil Shapiro {
6840266059SGregory Neil Shapiro return;
6940266059SGregory Neil Shapiro }
7040266059SGregory Neil Shapiro
7140266059SGregory Neil Shapiro /*
7240266059SGregory Neil Shapiro ** In addition to missing functions, certain existing MPE functions have
7340266059SGregory Neil Shapiro ** slightly different semantics (or bugs) compared to normal Unix OSes.
7440266059SGregory Neil Shapiro **
7540266059SGregory Neil Shapiro ** Here we define wrappers for these functions to make them behave in the
7640266059SGregory Neil Shapiro ** manner expected by sendmail.
7740266059SGregory Neil Shapiro */
7840266059SGregory Neil Shapiro
7940266059SGregory Neil Shapiro /*
8040266059SGregory Neil Shapiro ** SENDMAIL_MPE_BIND -- shadow function for the standard socket bind()
8140266059SGregory Neil Shapiro **
8240266059SGregory Neil Shapiro ** MPE requires GETPRIVMODE() for AF_INET sockets less than port 1024.
8340266059SGregory Neil Shapiro **
8440266059SGregory Neil Shapiro ** Parameters:
8540266059SGregory Neil Shapiro ** sd -- socket descriptor.
8640266059SGregory Neil Shapiro ** addr -- socket address.
8740266059SGregory Neil Shapiro ** addrlen -- length of socket address.
8840266059SGregory Neil Shapiro **
8940266059SGregory Neil Shapiro ** Results:
9040266059SGregory Neil Shapiro ** 0 -- success
9140266059SGregory Neil Shapiro ** != 0 -- failure
9240266059SGregory Neil Shapiro */
9340266059SGregory Neil Shapiro
9440266059SGregory Neil Shapiro #undef bind
9540266059SGregory Neil Shapiro int
sendmail_mpe_bind(sd,addr,addrlen)9640266059SGregory Neil Shapiro sendmail_mpe_bind(sd, addr, addrlen)
9740266059SGregory Neil Shapiro int sd;
9840266059SGregory Neil Shapiro void *addr;
9940266059SGregory Neil Shapiro int addrlen;
10040266059SGregory Neil Shapiro {
10140266059SGregory Neil Shapiro bool priv = false;
10240266059SGregory Neil Shapiro int result;
10340266059SGregory Neil Shapiro extern void GETPRIVMODE __P((void));
10440266059SGregory Neil Shapiro extern void GETUSERMODE __P((void));
10540266059SGregory Neil Shapiro
10640266059SGregory Neil Shapiro if (addrlen == sizeof(struct sockaddr_in) &&
10740266059SGregory Neil Shapiro ((struct sockaddr_in *)addr)->sin_family == AF_INET)
10840266059SGregory Neil Shapiro {
10940266059SGregory Neil Shapiro /* AF_INET */
11040266059SGregory Neil Shapiro if (((struct sockaddr_in *)addr)->sin_port > 0 &&
11140266059SGregory Neil Shapiro ((struct sockaddr_in *)addr)->sin_port < 1024)
11240266059SGregory Neil Shapiro {
11340266059SGregory Neil Shapiro priv = true;
11440266059SGregory Neil Shapiro GETPRIVMODE();
11540266059SGregory Neil Shapiro }
11640266059SGregory Neil Shapiro ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0;
11740266059SGregory Neil Shapiro result = bind(sd, addr, addrlen);
11840266059SGregory Neil Shapiro if (priv)
11940266059SGregory Neil Shapiro GETUSERMODE();
12040266059SGregory Neil Shapiro return result;
12140266059SGregory Neil Shapiro }
12240266059SGregory Neil Shapiro
12340266059SGregory Neil Shapiro /* AF_UNIX */
12440266059SGregory Neil Shapiro return bind(sd, addr, addrlen);
12540266059SGregory Neil Shapiro }
12640266059SGregory Neil Shapiro
12740266059SGregory Neil Shapiro /*
12840266059SGregory Neil Shapiro ** SENDMAIL_MPE__EXIT -- wait for children to terminate, then _exit()
12940266059SGregory Neil Shapiro **
13040266059SGregory Neil Shapiro ** Child processes cannot survive the death of their parent on MPE, so
13140266059SGregory Neil Shapiro ** we must call wait() before _exit() in order to prevent this
13240266059SGregory Neil Shapiro ** infanticide.
13340266059SGregory Neil Shapiro **
13440266059SGregory Neil Shapiro ** Parameters:
13540266059SGregory Neil Shapiro ** status -- _exit status value.
13640266059SGregory Neil Shapiro **
13740266059SGregory Neil Shapiro ** Returns:
13840266059SGregory Neil Shapiro ** none.
13940266059SGregory Neil Shapiro */
14040266059SGregory Neil Shapiro
14140266059SGregory Neil Shapiro #undef _exit
14240266059SGregory Neil Shapiro void
sendmail_mpe__exit(status)14340266059SGregory Neil Shapiro sendmail_mpe__exit(status)
14440266059SGregory Neil Shapiro int status;
14540266059SGregory Neil Shapiro {
14640266059SGregory Neil Shapiro int result;
14740266059SGregory Neil Shapiro
14840266059SGregory Neil Shapiro /* Wait for all children to terminate. */
14940266059SGregory Neil Shapiro do
15040266059SGregory Neil Shapiro {
15140266059SGregory Neil Shapiro result = wait(NULL);
15240266059SGregory Neil Shapiro } while (result > 0 || errno == EINTR);
15340266059SGregory Neil Shapiro _exit(status);
15440266059SGregory Neil Shapiro }
15540266059SGregory Neil Shapiro
15640266059SGregory Neil Shapiro /*
15740266059SGregory Neil Shapiro ** SENDMAIL_MPE_EXIT -- wait for children to terminate, then exit()
15840266059SGregory Neil Shapiro **
15940266059SGregory Neil Shapiro ** Child processes cannot survive the death of their parent on MPE, so
16040266059SGregory Neil Shapiro ** we must call wait() before exit() in order to prevent this
16140266059SGregory Neil Shapiro ** infanticide.
16240266059SGregory Neil Shapiro **
16340266059SGregory Neil Shapiro ** Parameters:
16440266059SGregory Neil Shapiro ** status -- exit status value.
16540266059SGregory Neil Shapiro **
16640266059SGregory Neil Shapiro ** Returns:
16740266059SGregory Neil Shapiro ** none.
16840266059SGregory Neil Shapiro */
16940266059SGregory Neil Shapiro
17040266059SGregory Neil Shapiro #undef exit
17140266059SGregory Neil Shapiro void
sendmail_mpe_exit(status)17240266059SGregory Neil Shapiro sendmail_mpe_exit(status)
17340266059SGregory Neil Shapiro int status;
17440266059SGregory Neil Shapiro {
17540266059SGregory Neil Shapiro int result;
17640266059SGregory Neil Shapiro
17740266059SGregory Neil Shapiro /* Wait for all children to terminate. */
17840266059SGregory Neil Shapiro do
17940266059SGregory Neil Shapiro {
18040266059SGregory Neil Shapiro result = wait(NULL);
18140266059SGregory Neil Shapiro } while (result > 0 || errno == EINTR);
18240266059SGregory Neil Shapiro exit(status);
18340266059SGregory Neil Shapiro }
18440266059SGregory Neil Shapiro
18540266059SGregory Neil Shapiro /*
18640266059SGregory Neil Shapiro ** SENDMAIL_MPE_FCNTL -- shadow function for fcntl()
18740266059SGregory Neil Shapiro **
18840266059SGregory Neil Shapiro ** MPE requires sfcntl() for sockets, and fcntl() for everything
18940266059SGregory Neil Shapiro ** else. This shadow routine determines the descriptor type and
19040266059SGregory Neil Shapiro ** makes the appropriate call.
19140266059SGregory Neil Shapiro **
19240266059SGregory Neil Shapiro ** Parameters:
19340266059SGregory Neil Shapiro ** same as fcntl().
19440266059SGregory Neil Shapiro **
19540266059SGregory Neil Shapiro ** Returns:
19640266059SGregory Neil Shapiro ** same as fcntl().
19740266059SGregory Neil Shapiro */
19840266059SGregory Neil Shapiro
19940266059SGregory Neil Shapiro #undef fcntl
20040266059SGregory Neil Shapiro int
sendmail_mpe_fcntl(int fildes,int cmd,...)20140266059SGregory Neil Shapiro sendmail_mpe_fcntl(int fildes, int cmd, ...)
20240266059SGregory Neil Shapiro {
20340266059SGregory Neil Shapiro int len, result;
20440266059SGregory Neil Shapiro struct sockaddr sa;
20540266059SGregory Neil Shapiro
20640266059SGregory Neil Shapiro void *arg;
20740266059SGregory Neil Shapiro va_list ap;
20840266059SGregory Neil Shapiro
20940266059SGregory Neil Shapiro va_start(ap, cmd);
21040266059SGregory Neil Shapiro arg = va_arg(ap, void *);
21140266059SGregory Neil Shapiro va_end(ap);
21240266059SGregory Neil Shapiro
21340266059SGregory Neil Shapiro len = sizeof sa;
21440266059SGregory Neil Shapiro if (getsockname(fildes, &sa, &len) == -1)
21540266059SGregory Neil Shapiro {
21640266059SGregory Neil Shapiro if (errno == EAFNOSUPPORT)
21740266059SGregory Neil Shapiro {
21840266059SGregory Neil Shapiro /* AF_UNIX socket */
21940266059SGregory Neil Shapiro return sfcntl(fildes, cmd, arg);
22040266059SGregory Neil Shapiro }
22140266059SGregory Neil Shapiro else if (errno == ENOTSOCK)
22240266059SGregory Neil Shapiro {
22340266059SGregory Neil Shapiro /* file or pipe */
22440266059SGregory Neil Shapiro return fcntl(fildes, cmd, arg);
22540266059SGregory Neil Shapiro }
22640266059SGregory Neil Shapiro
22740266059SGregory Neil Shapiro /* unknown getsockname() failure */
22840266059SGregory Neil Shapiro return (-1);
22940266059SGregory Neil Shapiro }
23040266059SGregory Neil Shapiro else
23140266059SGregory Neil Shapiro {
23240266059SGregory Neil Shapiro /* AF_INET socket */
23340266059SGregory Neil Shapiro if ((result = sfcntl(fildes, cmd, arg)) != -1 &&
23440266059SGregory Neil Shapiro cmd == F_GETFL)
23540266059SGregory Neil Shapiro result |= O_RDWR; /* fill in some missing flags */
23640266059SGregory Neil Shapiro return result;
23740266059SGregory Neil Shapiro }
23840266059SGregory Neil Shapiro }
23940266059SGregory Neil Shapiro
24040266059SGregory Neil Shapiro /*
24140266059SGregory Neil Shapiro ** SENDMAIL_MPE_GETPWNAM - shadow function for getpwnam()
24240266059SGregory Neil Shapiro **
24340266059SGregory Neil Shapiro ** Several issues apply here:
24440266059SGregory Neil Shapiro **
24540266059SGregory Neil Shapiro ** - MPE user names MUST have one '.' separator character
24640266059SGregory Neil Shapiro ** - MPE user names MUST be in upper case
24740266059SGregory Neil Shapiro ** - MPE does not initialize all fields in the passwd struct
24840266059SGregory Neil Shapiro **
24940266059SGregory Neil Shapiro ** Parameters:
25040266059SGregory Neil Shapiro ** name -- username string.
25140266059SGregory Neil Shapiro **
25240266059SGregory Neil Shapiro ** Returns:
25340266059SGregory Neil Shapiro ** pointer to struct passwd if found else NULL
25440266059SGregory Neil Shapiro */
25540266059SGregory Neil Shapiro
25640266059SGregory Neil Shapiro static char *sendmail_mpe_nullstr = "";
25740266059SGregory Neil Shapiro
25840266059SGregory Neil Shapiro #undef getpwnam
25940266059SGregory Neil Shapiro extern struct passwd *getpwnam(const char *);
26040266059SGregory Neil Shapiro
26140266059SGregory Neil Shapiro struct passwd *
sendmail_mpe_getpwnam(name)26240266059SGregory Neil Shapiro sendmail_mpe_getpwnam(name)
26340266059SGregory Neil Shapiro const char *name;
26440266059SGregory Neil Shapiro {
26540266059SGregory Neil Shapiro int dots = 0;
26640266059SGregory Neil Shapiro int err;
26740266059SGregory Neil Shapiro int i = strlen(name);
26840266059SGregory Neil Shapiro char *upper;
26940266059SGregory Neil Shapiro struct passwd *result = NULL;
27040266059SGregory Neil Shapiro
27140266059SGregory Neil Shapiro if (i <= 0)
27240266059SGregory Neil Shapiro {
27340266059SGregory Neil Shapiro errno = EINVAL;
27440266059SGregory Neil Shapiro return result;
27540266059SGregory Neil Shapiro }
27640266059SGregory Neil Shapiro
27740266059SGregory Neil Shapiro if ((upper = (char *)malloc(i + 1)) != NULL)
27840266059SGregory Neil Shapiro {
27940266059SGregory Neil Shapiro /* upshift the username parameter and count the dots */
28040266059SGregory Neil Shapiro while (i >= 0)
28140266059SGregory Neil Shapiro {
28240266059SGregory Neil Shapiro if (name[i] == '.')
28340266059SGregory Neil Shapiro {
28440266059SGregory Neil Shapiro dots++;
28540266059SGregory Neil Shapiro upper[i] = '.';
28640266059SGregory Neil Shapiro }
28740266059SGregory Neil Shapiro else
28840266059SGregory Neil Shapiro upper[i] = toupper(name[i]);
28940266059SGregory Neil Shapiro i--;
29040266059SGregory Neil Shapiro }
29140266059SGregory Neil Shapiro
29240266059SGregory Neil Shapiro if (dots != 1)
29340266059SGregory Neil Shapiro {
29440266059SGregory Neil Shapiro /* prevent bug when dots == 0 */
29540266059SGregory Neil Shapiro err = EINVAL;
29640266059SGregory Neil Shapiro }
29740266059SGregory Neil Shapiro else if ((result = getpwnam(upper)) != NULL)
29840266059SGregory Neil Shapiro {
29940266059SGregory Neil Shapiro /* init the uninitialized fields */
30040266059SGregory Neil Shapiro result->pw_gecos = sendmail_mpe_nullstr;
30140266059SGregory Neil Shapiro result->pw_passwd = sendmail_mpe_nullstr;
30240266059SGregory Neil Shapiro result->pw_age = sendmail_mpe_nullstr;
30340266059SGregory Neil Shapiro result->pw_comment = sendmail_mpe_nullstr;
30440266059SGregory Neil Shapiro result->pw_audid = 0;
30540266059SGregory Neil Shapiro result->pw_audflg = 0;
30640266059SGregory Neil Shapiro }
30740266059SGregory Neil Shapiro err = errno;
30840266059SGregory Neil Shapiro free(upper);
30940266059SGregory Neil Shapiro }
31040266059SGregory Neil Shapiro errno = err;
31140266059SGregory Neil Shapiro return result;
31240266059SGregory Neil Shapiro }
31340266059SGregory Neil Shapiro
31440266059SGregory Neil Shapiro /*
31540266059SGregory Neil Shapiro ** SENDMAIL_MPE_GETPWUID -- shadow function for getpwuid()
31640266059SGregory Neil Shapiro **
317*d39bd2c1SGregory Neil Shapiro ** Initializes the uninitialized fields in the passwd struct.
31840266059SGregory Neil Shapiro **
31940266059SGregory Neil Shapiro ** Parameters:
32040266059SGregory Neil Shapiro ** uid -- uid to obtain passwd data for
32140266059SGregory Neil Shapiro **
32240266059SGregory Neil Shapiro ** Returns:
32340266059SGregory Neil Shapiro ** pointer to struct passwd or NULL if not found
32440266059SGregory Neil Shapiro */
32540266059SGregory Neil Shapiro
32640266059SGregory Neil Shapiro #undef getpwuid
32740266059SGregory Neil Shapiro extern struct passwd *getpwuid __P((uid_t));
32840266059SGregory Neil Shapiro
32940266059SGregory Neil Shapiro struct passwd *
sendmail_mpe_getpwuid(uid)33040266059SGregory Neil Shapiro sendmail_mpe_getpwuid(uid)
33140266059SGregory Neil Shapiro uid_t uid;
33240266059SGregory Neil Shapiro {
33340266059SGregory Neil Shapiro struct passwd *result;
33440266059SGregory Neil Shapiro
33540266059SGregory Neil Shapiro if ((result = getpwuid(uid)) != NULL)
33640266059SGregory Neil Shapiro {
33740266059SGregory Neil Shapiro /* initialize the uninitialized fields */
33840266059SGregory Neil Shapiro result->pw_gecos = sendmail_mpe_nullstr;
33940266059SGregory Neil Shapiro result->pw_passwd = sendmail_mpe_nullstr;
34040266059SGregory Neil Shapiro result->pw_age = sendmail_mpe_nullstr;
34140266059SGregory Neil Shapiro result->pw_comment = sendmail_mpe_nullstr;
34240266059SGregory Neil Shapiro result->pw_audid = 0;
34340266059SGregory Neil Shapiro result->pw_audflg = 0;
34440266059SGregory Neil Shapiro }
34540266059SGregory Neil Shapiro return result;
34640266059SGregory Neil Shapiro }
34740266059SGregory Neil Shapiro
34840266059SGregory Neil Shapiro /*
34940266059SGregory Neil Shapiro ** OK boys and girls, time for some serious voodoo!
35040266059SGregory Neil Shapiro **
35140266059SGregory Neil Shapiro ** MPE does not have a complete implementation of POSIX users and groups:
35240266059SGregory Neil Shapiro **
35340266059SGregory Neil Shapiro ** - there is no uid 0 superuser
35440266059SGregory Neil Shapiro ** - setuid/setgid file permission bits exist but have no-op functionality
35540266059SGregory Neil Shapiro ** - setgid() exists, but only supports new gid == current gid (boring!)
35640266059SGregory Neil Shapiro ** - setuid() forces a gid change to the new uid's primary (and only) gid
35740266059SGregory Neil Shapiro **
35840266059SGregory Neil Shapiro ** ...all of which thoroughly annoys sendmail.
35940266059SGregory Neil Shapiro **
36040266059SGregory Neil Shapiro ** So what to do? We can't go on an #ifdef MPE rampage throughout
36140266059SGregory Neil Shapiro ** sendmail, because there are only about a zillion references to uid 0
36240266059SGregory Neil Shapiro ** and so success (and security) would probably be rather dubious by the
36340266059SGregory Neil Shapiro ** time we finished.
36440266059SGregory Neil Shapiro **
36540266059SGregory Neil Shapiro ** Instead we take the approach of defining wrapper functions for the
36640266059SGregory Neil Shapiro ** gid/uid management functions getegid(), geteuid(), setgid(), and
36740266059SGregory Neil Shapiro ** setuid() in order to implement the following model:
36840266059SGregory Neil Shapiro **
36940266059SGregory Neil Shapiro ** - the sendmail program thinks it is a setuid-root (uid 0) program
37040266059SGregory Neil Shapiro ** - uid 0 is recognized as being valid, but does not grant extra powers
37140266059SGregory Neil Shapiro ** - MPE priv mode allows sendmail to call setuid(), not uid 0
37240266059SGregory Neil Shapiro ** - file access is still controlled by the real non-zero uid
37340266059SGregory Neil Shapiro ** - the other programs (vacation, etc) have standard MPE POSIX behavior
37440266059SGregory Neil Shapiro **
37540266059SGregory Neil Shapiro ** This emulation model is activated by use of the program file setgid and
37640266059SGregory Neil Shapiro ** setuid mode bits which exist but are unused by MPE. If the setgid mode
37740266059SGregory Neil Shapiro ** bit is on, then gid emulation will be enabled. If the setuid mode bit is
37840266059SGregory Neil Shapiro ** on, then uid emulation will be enabled. So for the mail daemon, we need
37940266059SGregory Neil Shapiro ** to do chmod u+s,g+s /SENDMAIL/CURRENT/SENDMAIL.
38040266059SGregory Neil Shapiro **
38140266059SGregory Neil Shapiro ** The following flags determine the current emulation state:
38240266059SGregory Neil Shapiro **
38340266059SGregory Neil Shapiro ** true == emulation enabled
38440266059SGregory Neil Shapiro ** false == emulation disabled, use unmodified MPE semantics
38540266059SGregory Neil Shapiro */
38640266059SGregory Neil Shapiro
38740266059SGregory Neil Shapiro static bool sendmail_mpe_flaginit = false;
38840266059SGregory Neil Shapiro static bool sendmail_mpe_gidflag = false;
38940266059SGregory Neil Shapiro static bool sendmail_mpe_uidflag = false;
39040266059SGregory Neil Shapiro
39140266059SGregory Neil Shapiro /*
39240266059SGregory Neil Shapiro ** SENDMAIL_MPE_GETMODE -- return the mode bits for the current process
39340266059SGregory Neil Shapiro **
39440266059SGregory Neil Shapiro ** Parameters:
39540266059SGregory Neil Shapiro ** none.
39640266059SGregory Neil Shapiro **
39740266059SGregory Neil Shapiro ** Returns:
39840266059SGregory Neil Shapiro ** file mode bits for the current process program file.
39940266059SGregory Neil Shapiro */
40040266059SGregory Neil Shapiro
40140266059SGregory Neil Shapiro mode_t
sendmail_mpe_getmode()40240266059SGregory Neil Shapiro sendmail_mpe_getmode()
40340266059SGregory Neil Shapiro {
40440266059SGregory Neil Shapiro int status = 666;
40540266059SGregory Neil Shapiro int myprogram_length;
40640266059SGregory Neil Shapiro int myprogram_syntax = 2;
40740266059SGregory Neil Shapiro char formaldesig[28];
40840266059SGregory Neil Shapiro char myprogram[PATH_MAX + 2];
40940266059SGregory Neil Shapiro char path[PATH_MAX + 1];
41040266059SGregory Neil Shapiro struct stat st;
41140266059SGregory Neil Shapiro extern HPMYPROGRAM __P((int parms, char *formaldesig, int *status,
41240266059SGregory Neil Shapiro int *length, char *myprogram,
41340266059SGregory Neil Shapiro int *myprogram_length, int *myprogram_syntax));
41440266059SGregory Neil Shapiro
41540266059SGregory Neil Shapiro myprogram_length = sizeof(myprogram);
41640266059SGregory Neil Shapiro HPMYPROGRAM(6, formaldesig, &status, NULL, myprogram,
41740266059SGregory Neil Shapiro &myprogram_length, &myprogram_syntax);
41840266059SGregory Neil Shapiro
41940266059SGregory Neil Shapiro /* should not occur, do not attempt emulation */
42040266059SGregory Neil Shapiro if (status != 0)
42140266059SGregory Neil Shapiro return 0;
42240266059SGregory Neil Shapiro
42340266059SGregory Neil Shapiro memcpy(&path, &myprogram[1], myprogram_length - 2);
42440266059SGregory Neil Shapiro path[myprogram_length - 2] = '\0';
42540266059SGregory Neil Shapiro
42640266059SGregory Neil Shapiro /* should not occur, do not attempt emulation */
42740266059SGregory Neil Shapiro if (stat(path, &st) < 0)
42840266059SGregory Neil Shapiro return 0;
42940266059SGregory Neil Shapiro
43040266059SGregory Neil Shapiro return st.st_mode;
43140266059SGregory Neil Shapiro }
43240266059SGregory Neil Shapiro
43340266059SGregory Neil Shapiro /*
43440266059SGregory Neil Shapiro ** SENDMAIL_MPE_EMULGID -- should we perform gid emulation?
43540266059SGregory Neil Shapiro **
43640266059SGregory Neil Shapiro ** If !sendmail_mpe_flaginit then obtain the mode bits to determine
43740266059SGregory Neil Shapiro ** if the setgid bit is on, we want gid emulation and so set
43840266059SGregory Neil Shapiro ** sendmail_mpe_gidflag to true. Otherwise we do not want gid emulation
43940266059SGregory Neil Shapiro ** and so set sendmail_mpe_gidflag to false.
44040266059SGregory Neil Shapiro **
44140266059SGregory Neil Shapiro ** Parameters:
44240266059SGregory Neil Shapiro ** none.
44340266059SGregory Neil Shapiro **
44440266059SGregory Neil Shapiro ** Returns:
44540266059SGregory Neil Shapiro ** true -- perform gid emulation
44640266059SGregory Neil Shapiro ** false -- do not perform gid emulation
44740266059SGregory Neil Shapiro */
44840266059SGregory Neil Shapiro
44940266059SGregory Neil Shapiro bool
sendmail_mpe_emulgid()45040266059SGregory Neil Shapiro sendmail_mpe_emulgid()
45140266059SGregory Neil Shapiro {
45240266059SGregory Neil Shapiro if (!sendmail_mpe_flaginit)
45340266059SGregory Neil Shapiro {
45440266059SGregory Neil Shapiro mode_t mode;
45540266059SGregory Neil Shapiro
45640266059SGregory Neil Shapiro mode = sendmail_mpe_getmode();
45740266059SGregory Neil Shapiro sendmail_mpe_gidflag = ((mode & S_ISGID) == S_ISGID);
45840266059SGregory Neil Shapiro sendmail_mpe_uidflag = ((mode & S_ISUID) == S_ISUID);
45940266059SGregory Neil Shapiro sendmail_mpe_flaginit = true;
46040266059SGregory Neil Shapiro }
46140266059SGregory Neil Shapiro return sendmail_mpe_gidflag;
46240266059SGregory Neil Shapiro }
46340266059SGregory Neil Shapiro
46440266059SGregory Neil Shapiro /*
46540266059SGregory Neil Shapiro ** SENDMAIL_MPE_EMULUID -- should we perform uid emulation?
46640266059SGregory Neil Shapiro **
46740266059SGregory Neil Shapiro ** If sendmail_mpe_uidflag == -1 then obtain the mode bits to determine
46840266059SGregory Neil Shapiro ** if the setuid bit is on, we want uid emulation and so set
46940266059SGregory Neil Shapiro ** sendmail_mpe_uidflag to true. Otherwise we do not want uid emulation
47040266059SGregory Neil Shapiro ** and so set sendmail_mpe_uidflag to false.
47140266059SGregory Neil Shapiro **
47240266059SGregory Neil Shapiro ** Parameters:
47340266059SGregory Neil Shapiro ** none.
47440266059SGregory Neil Shapiro **
47540266059SGregory Neil Shapiro ** Returns:
47640266059SGregory Neil Shapiro ** true -- perform uid emulation
47740266059SGregory Neil Shapiro ** false -- do not perform uid emulation
47840266059SGregory Neil Shapiro */
47940266059SGregory Neil Shapiro
48040266059SGregory Neil Shapiro bool
sendmail_mpe_emuluid()48140266059SGregory Neil Shapiro sendmail_mpe_emuluid()
48240266059SGregory Neil Shapiro {
48340266059SGregory Neil Shapiro if (!sendmail_mpe_flaginit)
48440266059SGregory Neil Shapiro {
48540266059SGregory Neil Shapiro mode_t mode;
48640266059SGregory Neil Shapiro
48740266059SGregory Neil Shapiro mode = sendmail_mpe_getmode();
48840266059SGregory Neil Shapiro sendmail_mpe_gidflag = ((mode & S_ISGID) == S_ISGID);
48940266059SGregory Neil Shapiro sendmail_mpe_uidflag = ((mode & S_ISUID) == S_ISUID);
49040266059SGregory Neil Shapiro sendmail_mpe_flaginit = true;
49140266059SGregory Neil Shapiro }
49240266059SGregory Neil Shapiro return sendmail_mpe_uidflag;
49340266059SGregory Neil Shapiro }
49440266059SGregory Neil Shapiro
49540266059SGregory Neil Shapiro /*
49640266059SGregory Neil Shapiro ** SENDMAIL_MPE_GETEGID -- shadow function for getegid()
49740266059SGregory Neil Shapiro **
49840266059SGregory Neil Shapiro ** If emulation mode is in effect and the saved egid has been
49940266059SGregory Neil Shapiro ** initialized, return the saved egid; otherwise return the value of the
50040266059SGregory Neil Shapiro ** real getegid() function.
50140266059SGregory Neil Shapiro **
50240266059SGregory Neil Shapiro ** Parameters:
50340266059SGregory Neil Shapiro ** none.
50440266059SGregory Neil Shapiro **
50540266059SGregory Neil Shapiro ** Returns:
50640266059SGregory Neil Shapiro ** emulated egid if present, else true egid.
50740266059SGregory Neil Shapiro */
50840266059SGregory Neil Shapiro
509ffb83623SGregory Neil Shapiro static gid_t sendmail_mpe_egid = -1;
51040266059SGregory Neil Shapiro
51140266059SGregory Neil Shapiro #undef getegid
51240266059SGregory Neil Shapiro gid_t
sendmail_mpe_getegid()51340266059SGregory Neil Shapiro sendmail_mpe_getegid()
51440266059SGregory Neil Shapiro {
51540266059SGregory Neil Shapiro if (sendmail_mpe_emulgid() && sendmail_mpe_egid != -1)
51640266059SGregory Neil Shapiro return sendmail_mpe_egid;
51740266059SGregory Neil Shapiro return getegid();
51840266059SGregory Neil Shapiro }
51940266059SGregory Neil Shapiro
52040266059SGregory Neil Shapiro /*
52140266059SGregory Neil Shapiro ** SENDMAIL_MPE_GETEUID -- shadow function for geteuid()
52240266059SGregory Neil Shapiro **
52340266059SGregory Neil Shapiro ** If emulation mode is in effect, return the saved euid; otherwise
52440266059SGregory Neil Shapiro ** return the value of the real geteuid() function.
52540266059SGregory Neil Shapiro **
52640266059SGregory Neil Shapiro ** Note that the initial value of the saved euid is zero, to simulate
52740266059SGregory Neil Shapiro ** a setuid-root program.
52840266059SGregory Neil Shapiro **
52940266059SGregory Neil Shapiro ** Parameters:
53040266059SGregory Neil Shapiro ** none
53140266059SGregory Neil Shapiro **
53240266059SGregory Neil Shapiro ** Returns:
53340266059SGregory Neil Shapiro ** emulated euid if in emulation mode, else true euid.
53440266059SGregory Neil Shapiro */
53540266059SGregory Neil Shapiro
53640266059SGregory Neil Shapiro static uid_t sendmail_mpe_euid = 0;
53740266059SGregory Neil Shapiro
53840266059SGregory Neil Shapiro #undef geteuid
53940266059SGregory Neil Shapiro uid_t
sendmail_mpe_geteuid()54040266059SGregory Neil Shapiro sendmail_mpe_geteuid()
54140266059SGregory Neil Shapiro {
54240266059SGregory Neil Shapiro if (sendmail_mpe_emuluid())
54340266059SGregory Neil Shapiro return sendmail_mpe_euid;
54440266059SGregory Neil Shapiro return geteuid();
54540266059SGregory Neil Shapiro }
54640266059SGregory Neil Shapiro
54740266059SGregory Neil Shapiro /*
54840266059SGregory Neil Shapiro ** SENDMAIL_MPE_SETGID -- shadow function for setgid()
54940266059SGregory Neil Shapiro **
55040266059SGregory Neil Shapiro ** Simulate a call to setgid() without actually calling the real
55140266059SGregory Neil Shapiro ** function. Implement the expected uid 0 semantics.
55240266059SGregory Neil Shapiro **
55340266059SGregory Neil Shapiro ** Note that sendmail will also be calling setuid() which will force an
55440266059SGregory Neil Shapiro ** implicit real setgid() to the proper primary gid. So it doesn't matter
55540266059SGregory Neil Shapiro ** that we don't actually alter the real gid in this shadow function.
55640266059SGregory Neil Shapiro **
55740266059SGregory Neil Shapiro ** Parameters:
55840266059SGregory Neil Shapiro ** gid -- desired gid.
55940266059SGregory Neil Shapiro **
56040266059SGregory Neil Shapiro ** Returns:
56140266059SGregory Neil Shapiro ** 0 -- emulated success
56240266059SGregory Neil Shapiro ** -1 -- emulated failure
56340266059SGregory Neil Shapiro */
56440266059SGregory Neil Shapiro
56540266059SGregory Neil Shapiro #undef setgid
56640266059SGregory Neil Shapiro int
sendmail_mpe_setgid(gid)56740266059SGregory Neil Shapiro sendmail_mpe_setgid(gid)
56840266059SGregory Neil Shapiro gid_t gid;
56940266059SGregory Neil Shapiro {
57040266059SGregory Neil Shapiro if (sendmail_mpe_emulgid())
57140266059SGregory Neil Shapiro {
57240266059SGregory Neil Shapiro if (gid == getgid() || sendmail_mpe_euid == 0)
57340266059SGregory Neil Shapiro {
57440266059SGregory Neil Shapiro sendmail_mpe_egid = gid;
57540266059SGregory Neil Shapiro return 0;
57640266059SGregory Neil Shapiro }
57740266059SGregory Neil Shapiro errno = EINVAL;
57840266059SGregory Neil Shapiro return -1;
57940266059SGregory Neil Shapiro }
58040266059SGregory Neil Shapiro return setgid(gid);
58140266059SGregory Neil Shapiro }
58240266059SGregory Neil Shapiro
58340266059SGregory Neil Shapiro /*
58440266059SGregory Neil Shapiro ** SENDMAIL_MPE_SETUID -- shadow function for setuid()
58540266059SGregory Neil Shapiro **
58640266059SGregory Neil Shapiro ** setuid() is broken as of MPE 7.0 in that it changes the current
58740266059SGregory Neil Shapiro ** working directory to be the home directory of the new uid. Thus
58840266059SGregory Neil Shapiro ** we must obtain the cwd and restore it after the setuid().
58940266059SGregory Neil Shapiro **
59040266059SGregory Neil Shapiro ** Note that expected uid 0 semantics have been added, as well as
59140266059SGregory Neil Shapiro ** remembering the new uid for later use by the other shadow functions.
59240266059SGregory Neil Shapiro **
59340266059SGregory Neil Shapiro ** Parameters:
59440266059SGregory Neil Shapiro ** uid -- desired uid.
59540266059SGregory Neil Shapiro **
59640266059SGregory Neil Shapiro ** Returns:
59740266059SGregory Neil Shapiro ** 0 -- success
59840266059SGregory Neil Shapiro ** -1 -- failure
59940266059SGregory Neil Shapiro **
60040266059SGregory Neil Shapiro ** Globals:
60140266059SGregory Neil Shapiro ** sendmail_mpe_euid
60240266059SGregory Neil Shapiro */
60340266059SGregory Neil Shapiro
60440266059SGregory Neil Shapiro #undef setuid
60540266059SGregory Neil Shapiro int
sendmail_mpe_setuid(uid)60640266059SGregory Neil Shapiro sendmail_mpe_setuid(uid)
60740266059SGregory Neil Shapiro uid_t uid;
60840266059SGregory Neil Shapiro {
60940266059SGregory Neil Shapiro char *cwd;
61040266059SGregory Neil Shapiro char cwd_buf[PATH_MAX + 1];
61140266059SGregory Neil Shapiro int result;
61240266059SGregory Neil Shapiro extern void GETPRIVMODE __P((void));
61340266059SGregory Neil Shapiro extern void GETUSERMODE __P((void));
61440266059SGregory Neil Shapiro
61540266059SGregory Neil Shapiro if (sendmail_mpe_emuluid())
61640266059SGregory Neil Shapiro {
61740266059SGregory Neil Shapiro if (uid == 0)
61840266059SGregory Neil Shapiro {
61940266059SGregory Neil Shapiro if (sendmail_mpe_euid != 0)
62040266059SGregory Neil Shapiro {
62140266059SGregory Neil Shapiro errno = EINVAL;
62240266059SGregory Neil Shapiro return -1;
62340266059SGregory Neil Shapiro }
62440266059SGregory Neil Shapiro sendmail_mpe_euid = 0;
62540266059SGregory Neil Shapiro return 0;
62640266059SGregory Neil Shapiro }
62740266059SGregory Neil Shapiro
62840266059SGregory Neil Shapiro /* Preserve the current working directory */
62940266059SGregory Neil Shapiro if ((cwd = getcwd(cwd_buf, PATH_MAX + 1)) == NULL)
63040266059SGregory Neil Shapiro return -1;
63140266059SGregory Neil Shapiro
63240266059SGregory Neil Shapiro GETPRIVMODE();
63340266059SGregory Neil Shapiro result = setuid(uid);
63440266059SGregory Neil Shapiro GETUSERMODE();
63540266059SGregory Neil Shapiro
63640266059SGregory Neil Shapiro /* Restore the current working directory */
63740266059SGregory Neil Shapiro chdir(cwd_buf);
63840266059SGregory Neil Shapiro
63940266059SGregory Neil Shapiro if (result == 0)
64040266059SGregory Neil Shapiro sendmail_mpe_euid = uid;
64140266059SGregory Neil Shapiro
64240266059SGregory Neil Shapiro return result;
64340266059SGregory Neil Shapiro }
64440266059SGregory Neil Shapiro return setuid(uid);
64540266059SGregory Neil Shapiro }
64640266059SGregory Neil Shapiro #endif /* MPE */
647