190792Sgshapiro/* 2261370Sgshapiro * Copyright (c) 2001-2002 Proofpoint, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * 590792Sgshapiro * By using this file, you agree to the terms and conditions set 690792Sgshapiro * forth in the LICENSE file which can be found at the top level of 790792Sgshapiro * the sendmail distribution. 890792Sgshapiro * 990792Sgshapiro */ 1090792Sgshapiro 1190792Sgshapiro#include <sm/gen.h> 12266711SgshapiroSM_RCSID("@(#)$Id: mpeix.c,v 1.8 2013-11-22 20:51:43 ca Exp $") 1390792Sgshapiro 1490792Sgshapiro#ifdef MPE 1590792Sgshapiro/* 1690792Sgshapiro** MPE lacks many common functions required across all sendmail programs 1790792Sgshapiro** so we define implementations for these functions here. 1890792Sgshapiro*/ 1990792Sgshapiro 2090792Sgshapiro# include <errno.h> 2190792Sgshapiro# include <fcntl.h> 2290792Sgshapiro# include <limits.h> 2390792Sgshapiro# include <mpe.h> 2490792Sgshapiro# include <netinet/in.h> 2590792Sgshapiro# include <pwd.h> 2690792Sgshapiro# include <sys/socket.h> 2790792Sgshapiro# include <sys/stat.h> 2890792Sgshapiro# include <unistd.h> 2990792Sgshapiro# include <sm/conf.h> 3090792Sgshapiro 3190792Sgshapiro/* 3290792Sgshapiro** CHROOT -- dummy chroot() function 3390792Sgshapiro** 3490792Sgshapiro** The MPE documentation for sendmail says that chroot-based 3590792Sgshapiro** functionality is not implemented because MPE lacks chroot. But 3690792Sgshapiro** rather than mucking around with all the sendmail calls to chroot, 3790792Sgshapiro** we define this dummy function to return an ENOSYS failure just in 3890792Sgshapiro** case a sendmail user attempts to enable chroot-based functionality. 3990792Sgshapiro** 4090792Sgshapiro** Parameters: 4190792Sgshapiro** path -- pathname of new root (ignored). 4290792Sgshapiro** 4390792Sgshapiro** Returns: 4490792Sgshapiro** -1 and errno == ENOSYS (function not implemented) 4590792Sgshapiro*/ 4690792Sgshapiro 4790792Sgshapiroint 4890792Sgshapirochroot(path) 4990792Sgshapiro char *path; 5090792Sgshapiro{ 5190792Sgshapiro errno = ENOSYS; 5290792Sgshapiro return -1; 5390792Sgshapiro} 5490792Sgshapiro 5590792Sgshapiro/* 5690792Sgshapiro** ENDPWENT -- dummy endpwent() function 5790792Sgshapiro** 5890792Sgshapiro** Parameters: 5990792Sgshapiro** none 6090792Sgshapiro** 6190792Sgshapiro** Returns: 6290792Sgshapiro** none 6390792Sgshapiro*/ 6490792Sgshapiro 6590792Sgshapirovoid 6690792Sgshapiroendpwent() 6790792Sgshapiro{ 6890792Sgshapiro return; 6990792Sgshapiro} 7090792Sgshapiro 7190792Sgshapiro/* 7290792Sgshapiro** In addition to missing functions, certain existing MPE functions have 7390792Sgshapiro** slightly different semantics (or bugs) compared to normal Unix OSes. 7490792Sgshapiro** 7590792Sgshapiro** Here we define wrappers for these functions to make them behave in the 7690792Sgshapiro** manner expected by sendmail. 7790792Sgshapiro*/ 7890792Sgshapiro 7990792Sgshapiro/* 8090792Sgshapiro** SENDMAIL_MPE_BIND -- shadow function for the standard socket bind() 8190792Sgshapiro** 8290792Sgshapiro** MPE requires GETPRIVMODE() for AF_INET sockets less than port 1024. 8390792Sgshapiro** 8490792Sgshapiro** Parameters: 8590792Sgshapiro** sd -- socket descriptor. 8690792Sgshapiro** addr -- socket address. 8790792Sgshapiro** addrlen -- length of socket address. 8890792Sgshapiro** 8990792Sgshapiro** Results: 9090792Sgshapiro** 0 -- success 9190792Sgshapiro** != 0 -- failure 9290792Sgshapiro*/ 9390792Sgshapiro 9490792Sgshapiro#undef bind 9590792Sgshapiroint 9690792Sgshapirosendmail_mpe_bind(sd, addr, addrlen) 9790792Sgshapiro int sd; 9890792Sgshapiro void *addr; 9990792Sgshapiro int addrlen; 10090792Sgshapiro{ 10190792Sgshapiro bool priv = false; 10290792Sgshapiro int result; 10390792Sgshapiro extern void GETPRIVMODE __P((void)); 10490792Sgshapiro extern void GETUSERMODE __P((void)); 10590792Sgshapiro 10690792Sgshapiro if (addrlen == sizeof(struct sockaddr_in) && 10790792Sgshapiro ((struct sockaddr_in *)addr)->sin_family == AF_INET) 10890792Sgshapiro { 10990792Sgshapiro /* AF_INET */ 11090792Sgshapiro if (((struct sockaddr_in *)addr)->sin_port > 0 && 11190792Sgshapiro ((struct sockaddr_in *)addr)->sin_port < 1024) 11290792Sgshapiro { 11390792Sgshapiro priv = true; 11490792Sgshapiro GETPRIVMODE(); 11590792Sgshapiro } 11690792Sgshapiro ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0; 11790792Sgshapiro result = bind(sd, addr, addrlen); 11890792Sgshapiro if (priv) 11990792Sgshapiro GETUSERMODE(); 12090792Sgshapiro return result; 12190792Sgshapiro } 12290792Sgshapiro 12390792Sgshapiro /* AF_UNIX */ 12490792Sgshapiro return bind(sd, addr, addrlen); 12590792Sgshapiro} 12690792Sgshapiro 12790792Sgshapiro/* 12890792Sgshapiro** SENDMAIL_MPE__EXIT -- wait for children to terminate, then _exit() 12990792Sgshapiro** 13090792Sgshapiro** Child processes cannot survive the death of their parent on MPE, so 13190792Sgshapiro** we must call wait() before _exit() in order to prevent this 13290792Sgshapiro** infanticide. 13390792Sgshapiro** 13490792Sgshapiro** Parameters: 13590792Sgshapiro** status -- _exit status value. 13690792Sgshapiro** 13790792Sgshapiro** Returns: 13890792Sgshapiro** none. 13990792Sgshapiro*/ 14090792Sgshapiro 14190792Sgshapiro#undef _exit 14290792Sgshapirovoid 14390792Sgshapirosendmail_mpe__exit(status) 14490792Sgshapiro int status; 14590792Sgshapiro{ 14690792Sgshapiro int result; 14790792Sgshapiro 14890792Sgshapiro /* Wait for all children to terminate. */ 14990792Sgshapiro do 15090792Sgshapiro { 15190792Sgshapiro result = wait(NULL); 15290792Sgshapiro } while (result > 0 || errno == EINTR); 15390792Sgshapiro _exit(status); 15490792Sgshapiro} 15590792Sgshapiro 15690792Sgshapiro/* 15790792Sgshapiro** SENDMAIL_MPE_EXIT -- wait for children to terminate, then exit() 15890792Sgshapiro** 15990792Sgshapiro** Child processes cannot survive the death of their parent on MPE, so 16090792Sgshapiro** we must call wait() before exit() in order to prevent this 16190792Sgshapiro** infanticide. 16290792Sgshapiro** 16390792Sgshapiro** Parameters: 16490792Sgshapiro** status -- exit status value. 16590792Sgshapiro** 16690792Sgshapiro** Returns: 16790792Sgshapiro** none. 16890792Sgshapiro*/ 16990792Sgshapiro 17090792Sgshapiro#undef exit 17190792Sgshapirovoid 17290792Sgshapirosendmail_mpe_exit(status) 17390792Sgshapiro int status; 17490792Sgshapiro{ 17590792Sgshapiro int result; 17690792Sgshapiro 17790792Sgshapiro /* Wait for all children to terminate. */ 17890792Sgshapiro do 17990792Sgshapiro { 18090792Sgshapiro result = wait(NULL); 18190792Sgshapiro } while (result > 0 || errno == EINTR); 18290792Sgshapiro exit(status); 18390792Sgshapiro} 18490792Sgshapiro 18590792Sgshapiro/* 18690792Sgshapiro** SENDMAIL_MPE_FCNTL -- shadow function for fcntl() 18790792Sgshapiro** 18890792Sgshapiro** MPE requires sfcntl() for sockets, and fcntl() for everything 18990792Sgshapiro** else. This shadow routine determines the descriptor type and 19090792Sgshapiro** makes the appropriate call. 19190792Sgshapiro** 19290792Sgshapiro** Parameters: 19390792Sgshapiro** same as fcntl(). 19490792Sgshapiro** 19590792Sgshapiro** Returns: 19690792Sgshapiro** same as fcntl(). 19790792Sgshapiro*/ 19890792Sgshapiro 19990792Sgshapiro#undef fcntl 20090792Sgshapiroint 20190792Sgshapirosendmail_mpe_fcntl(int fildes, int cmd, ...) 20290792Sgshapiro{ 20390792Sgshapiro int len, result; 20490792Sgshapiro struct sockaddr sa; 20590792Sgshapiro 20690792Sgshapiro void *arg; 20790792Sgshapiro va_list ap; 20890792Sgshapiro 20990792Sgshapiro va_start(ap, cmd); 21090792Sgshapiro arg = va_arg(ap, void *); 21190792Sgshapiro va_end(ap); 21290792Sgshapiro 21390792Sgshapiro len = sizeof sa; 21490792Sgshapiro if (getsockname(fildes, &sa, &len) == -1) 21590792Sgshapiro { 21690792Sgshapiro if (errno == EAFNOSUPPORT) 21790792Sgshapiro { 21890792Sgshapiro /* AF_UNIX socket */ 21990792Sgshapiro return sfcntl(fildes, cmd, arg); 22090792Sgshapiro } 22190792Sgshapiro else if (errno == ENOTSOCK) 22290792Sgshapiro { 22390792Sgshapiro /* file or pipe */ 22490792Sgshapiro return fcntl(fildes, cmd, arg); 22590792Sgshapiro } 22690792Sgshapiro 22790792Sgshapiro /* unknown getsockname() failure */ 22890792Sgshapiro return (-1); 22990792Sgshapiro } 23090792Sgshapiro else 23190792Sgshapiro { 23290792Sgshapiro /* AF_INET socket */ 23390792Sgshapiro if ((result = sfcntl(fildes, cmd, arg)) != -1 && 23490792Sgshapiro cmd == F_GETFL) 23590792Sgshapiro result |= O_RDWR; /* fill in some missing flags */ 23690792Sgshapiro return result; 23790792Sgshapiro } 23890792Sgshapiro} 23990792Sgshapiro 24090792Sgshapiro/* 24190792Sgshapiro** SENDMAIL_MPE_GETPWNAM - shadow function for getpwnam() 24290792Sgshapiro** 24390792Sgshapiro** Several issues apply here: 24490792Sgshapiro** 24590792Sgshapiro** - MPE user names MUST have one '.' separator character 24690792Sgshapiro** - MPE user names MUST be in upper case 24790792Sgshapiro** - MPE does not initialize all fields in the passwd struct 24890792Sgshapiro** 24990792Sgshapiro** Parameters: 25090792Sgshapiro** name -- username string. 25190792Sgshapiro** 25290792Sgshapiro** Returns: 25390792Sgshapiro** pointer to struct passwd if found else NULL 25490792Sgshapiro*/ 25590792Sgshapiro 25690792Sgshapirostatic char *sendmail_mpe_nullstr = ""; 25790792Sgshapiro 25890792Sgshapiro#undef getpwnam 25990792Sgshapiroextern struct passwd *getpwnam(const char *); 26090792Sgshapiro 26190792Sgshapirostruct passwd * 26290792Sgshapirosendmail_mpe_getpwnam(name) 26390792Sgshapiro const char *name; 26490792Sgshapiro{ 26590792Sgshapiro int dots = 0; 26690792Sgshapiro int err; 26790792Sgshapiro int i = strlen(name); 26890792Sgshapiro char *upper; 26990792Sgshapiro struct passwd *result = NULL; 27090792Sgshapiro 27190792Sgshapiro if (i <= 0) 27290792Sgshapiro { 27390792Sgshapiro errno = EINVAL; 27490792Sgshapiro return result; 27590792Sgshapiro } 27690792Sgshapiro 27790792Sgshapiro if ((upper = (char *)malloc(i + 1)) != NULL) 27890792Sgshapiro { 27990792Sgshapiro /* upshift the username parameter and count the dots */ 28090792Sgshapiro while (i >= 0) 28190792Sgshapiro { 28290792Sgshapiro if (name[i] == '.') 28390792Sgshapiro { 28490792Sgshapiro dots++; 28590792Sgshapiro upper[i] = '.'; 28690792Sgshapiro } 28790792Sgshapiro else 28890792Sgshapiro upper[i] = toupper(name[i]); 28990792Sgshapiro i--; 29090792Sgshapiro } 29190792Sgshapiro 29290792Sgshapiro if (dots != 1) 29390792Sgshapiro { 29490792Sgshapiro /* prevent bug when dots == 0 */ 29590792Sgshapiro err = EINVAL; 29690792Sgshapiro } 29790792Sgshapiro else if ((result = getpwnam(upper)) != NULL) 29890792Sgshapiro { 29990792Sgshapiro /* init the uninitialized fields */ 30090792Sgshapiro result->pw_gecos = sendmail_mpe_nullstr; 30190792Sgshapiro result->pw_passwd = sendmail_mpe_nullstr; 30290792Sgshapiro result->pw_age = sendmail_mpe_nullstr; 30390792Sgshapiro result->pw_comment = sendmail_mpe_nullstr; 30490792Sgshapiro result->pw_audid = 0; 30590792Sgshapiro result->pw_audflg = 0; 30690792Sgshapiro } 30790792Sgshapiro err = errno; 30890792Sgshapiro free(upper); 30990792Sgshapiro } 31090792Sgshapiro errno = err; 31190792Sgshapiro return result; 31290792Sgshapiro} 31390792Sgshapiro 31490792Sgshapiro/* 31590792Sgshapiro** SENDMAIL_MPE_GETPWUID -- shadow function for getpwuid() 31690792Sgshapiro** 31790792Sgshapiro** Initializes the uninitalized fields in the passwd struct. 31890792Sgshapiro** 31990792Sgshapiro** Parameters: 32090792Sgshapiro** uid -- uid to obtain passwd data for 32190792Sgshapiro** 32290792Sgshapiro** Returns: 32390792Sgshapiro** pointer to struct passwd or NULL if not found 32490792Sgshapiro*/ 32590792Sgshapiro 32690792Sgshapiro#undef getpwuid 32790792Sgshapiroextern struct passwd *getpwuid __P((uid_t)); 32890792Sgshapiro 32990792Sgshapirostruct passwd * 33090792Sgshapirosendmail_mpe_getpwuid(uid) 33190792Sgshapiro uid_t uid; 33290792Sgshapiro{ 33390792Sgshapiro struct passwd *result; 33490792Sgshapiro 33590792Sgshapiro if ((result = getpwuid(uid)) != NULL) 33690792Sgshapiro { 33790792Sgshapiro /* initialize the uninitialized fields */ 33890792Sgshapiro result->pw_gecos = sendmail_mpe_nullstr; 33990792Sgshapiro result->pw_passwd = sendmail_mpe_nullstr; 34090792Sgshapiro result->pw_age = sendmail_mpe_nullstr; 34190792Sgshapiro result->pw_comment = sendmail_mpe_nullstr; 34290792Sgshapiro result->pw_audid = 0; 34390792Sgshapiro result->pw_audflg = 0; 34490792Sgshapiro } 34590792Sgshapiro return result; 34690792Sgshapiro} 34790792Sgshapiro 34890792Sgshapiro/* 34990792Sgshapiro** OK boys and girls, time for some serious voodoo! 35090792Sgshapiro** 35190792Sgshapiro** MPE does not have a complete implementation of POSIX users and groups: 35290792Sgshapiro** 35390792Sgshapiro** - there is no uid 0 superuser 35490792Sgshapiro** - setuid/setgid file permission bits exist but have no-op functionality 35590792Sgshapiro** - setgid() exists, but only supports new gid == current gid (boring!) 35690792Sgshapiro** - setuid() forces a gid change to the new uid's primary (and only) gid 35790792Sgshapiro** 35890792Sgshapiro** ...all of which thoroughly annoys sendmail. 35990792Sgshapiro** 36090792Sgshapiro** So what to do? We can't go on an #ifdef MPE rampage throughout 36190792Sgshapiro** sendmail, because there are only about a zillion references to uid 0 36290792Sgshapiro** and so success (and security) would probably be rather dubious by the 36390792Sgshapiro** time we finished. 36490792Sgshapiro** 36590792Sgshapiro** Instead we take the approach of defining wrapper functions for the 36690792Sgshapiro** gid/uid management functions getegid(), geteuid(), setgid(), and 36790792Sgshapiro** setuid() in order to implement the following model: 36890792Sgshapiro** 36990792Sgshapiro** - the sendmail program thinks it is a setuid-root (uid 0) program 37090792Sgshapiro** - uid 0 is recognized as being valid, but does not grant extra powers 37190792Sgshapiro** - MPE priv mode allows sendmail to call setuid(), not uid 0 37290792Sgshapiro** - file access is still controlled by the real non-zero uid 37390792Sgshapiro** - the other programs (vacation, etc) have standard MPE POSIX behavior 37490792Sgshapiro** 37590792Sgshapiro** This emulation model is activated by use of the program file setgid and 37690792Sgshapiro** setuid mode bits which exist but are unused by MPE. If the setgid mode 37790792Sgshapiro** bit is on, then gid emulation will be enabled. If the setuid mode bit is 37890792Sgshapiro** on, then uid emulation will be enabled. So for the mail daemon, we need 37990792Sgshapiro** to do chmod u+s,g+s /SENDMAIL/CURRENT/SENDMAIL. 38090792Sgshapiro** 38190792Sgshapiro** The following flags determine the current emulation state: 38290792Sgshapiro** 38390792Sgshapiro** true == emulation enabled 38490792Sgshapiro** false == emulation disabled, use unmodified MPE semantics 38590792Sgshapiro*/ 38690792Sgshapiro 38790792Sgshapirostatic bool sendmail_mpe_flaginit = false; 38890792Sgshapirostatic bool sendmail_mpe_gidflag = false; 38990792Sgshapirostatic bool sendmail_mpe_uidflag = false; 39090792Sgshapiro 39190792Sgshapiro/* 39290792Sgshapiro** SENDMAIL_MPE_GETMODE -- return the mode bits for the current process 39390792Sgshapiro** 39490792Sgshapiro** Parameters: 39590792Sgshapiro** none. 39690792Sgshapiro** 39790792Sgshapiro** Returns: 39890792Sgshapiro** file mode bits for the current process program file. 39990792Sgshapiro*/ 40090792Sgshapiro 40190792Sgshapiromode_t 40290792Sgshapirosendmail_mpe_getmode() 40390792Sgshapiro{ 40490792Sgshapiro int status = 666; 40590792Sgshapiro int myprogram_length; 40690792Sgshapiro int myprogram_syntax = 2; 40790792Sgshapiro char formaldesig[28]; 40890792Sgshapiro char myprogram[PATH_MAX + 2]; 40990792Sgshapiro char path[PATH_MAX + 1]; 41090792Sgshapiro struct stat st; 41190792Sgshapiro extern HPMYPROGRAM __P((int parms, char *formaldesig, int *status, 41290792Sgshapiro int *length, char *myprogram, 41390792Sgshapiro int *myprogram_length, int *myprogram_syntax)); 41490792Sgshapiro 41590792Sgshapiro myprogram_length = sizeof(myprogram); 41690792Sgshapiro HPMYPROGRAM(6, formaldesig, &status, NULL, myprogram, 41790792Sgshapiro &myprogram_length, &myprogram_syntax); 41890792Sgshapiro 41990792Sgshapiro /* should not occur, do not attempt emulation */ 42090792Sgshapiro if (status != 0) 42190792Sgshapiro return 0; 42290792Sgshapiro 42390792Sgshapiro memcpy(&path, &myprogram[1], myprogram_length - 2); 42490792Sgshapiro path[myprogram_length - 2] = '\0'; 42590792Sgshapiro 42690792Sgshapiro /* should not occur, do not attempt emulation */ 42790792Sgshapiro if (stat(path, &st) < 0) 42890792Sgshapiro return 0; 42990792Sgshapiro 43090792Sgshapiro return st.st_mode; 43190792Sgshapiro} 43290792Sgshapiro 43390792Sgshapiro/* 43490792Sgshapiro** SENDMAIL_MPE_EMULGID -- should we perform gid emulation? 43590792Sgshapiro** 43690792Sgshapiro** If !sendmail_mpe_flaginit then obtain the mode bits to determine 43790792Sgshapiro** if the setgid bit is on, we want gid emulation and so set 43890792Sgshapiro** sendmail_mpe_gidflag to true. Otherwise we do not want gid emulation 43990792Sgshapiro** and so set sendmail_mpe_gidflag to false. 44090792Sgshapiro** 44190792Sgshapiro** Parameters: 44290792Sgshapiro** none. 44390792Sgshapiro** 44490792Sgshapiro** Returns: 44590792Sgshapiro** true -- perform gid emulation 44690792Sgshapiro** false -- do not perform gid emulation 44790792Sgshapiro*/ 44890792Sgshapiro 44990792Sgshapirobool 45090792Sgshapirosendmail_mpe_emulgid() 45190792Sgshapiro{ 45290792Sgshapiro if (!sendmail_mpe_flaginit) 45390792Sgshapiro { 45490792Sgshapiro mode_t mode; 45590792Sgshapiro 45690792Sgshapiro mode = sendmail_mpe_getmode(); 45790792Sgshapiro sendmail_mpe_gidflag = ((mode & S_ISGID) == S_ISGID); 45890792Sgshapiro sendmail_mpe_uidflag = ((mode & S_ISUID) == S_ISUID); 45990792Sgshapiro sendmail_mpe_flaginit = true; 46090792Sgshapiro } 46190792Sgshapiro return sendmail_mpe_gidflag; 46290792Sgshapiro} 46390792Sgshapiro 46490792Sgshapiro/* 46590792Sgshapiro** SENDMAIL_MPE_EMULUID -- should we perform uid emulation? 46690792Sgshapiro** 46790792Sgshapiro** If sendmail_mpe_uidflag == -1 then obtain the mode bits to determine 46890792Sgshapiro** if the setuid bit is on, we want uid emulation and so set 46990792Sgshapiro** sendmail_mpe_uidflag to true. Otherwise we do not want uid emulation 47090792Sgshapiro** and so set sendmail_mpe_uidflag to false. 47190792Sgshapiro** 47290792Sgshapiro** Parameters: 47390792Sgshapiro** none. 47490792Sgshapiro** 47590792Sgshapiro** Returns: 47690792Sgshapiro** true -- perform uid emulation 47790792Sgshapiro** false -- do not perform uid emulation 47890792Sgshapiro*/ 47990792Sgshapiro 48090792Sgshapirobool 48190792Sgshapirosendmail_mpe_emuluid() 48290792Sgshapiro{ 48390792Sgshapiro if (!sendmail_mpe_flaginit) 48490792Sgshapiro { 48590792Sgshapiro mode_t mode; 48690792Sgshapiro 48790792Sgshapiro mode = sendmail_mpe_getmode(); 48890792Sgshapiro sendmail_mpe_gidflag = ((mode & S_ISGID) == S_ISGID); 48990792Sgshapiro sendmail_mpe_uidflag = ((mode & S_ISUID) == S_ISUID); 49090792Sgshapiro sendmail_mpe_flaginit = true; 49190792Sgshapiro } 49290792Sgshapiro return sendmail_mpe_uidflag; 49390792Sgshapiro} 49490792Sgshapiro 49590792Sgshapiro/* 49690792Sgshapiro** SENDMAIL_MPE_GETEGID -- shadow function for getegid() 49790792Sgshapiro** 49890792Sgshapiro** If emulation mode is in effect and the saved egid has been 49990792Sgshapiro** initialized, return the saved egid; otherwise return the value of the 50090792Sgshapiro** real getegid() function. 50190792Sgshapiro** 50290792Sgshapiro** Parameters: 50390792Sgshapiro** none. 50490792Sgshapiro** 50590792Sgshapiro** Returns: 50690792Sgshapiro** emulated egid if present, else true egid. 50790792Sgshapiro*/ 50890792Sgshapiro 509173340Sgshapirostatic gid_t sendmail_mpe_egid = -1; 51090792Sgshapiro 51190792Sgshapiro#undef getegid 51290792Sgshapirogid_t 51390792Sgshapirosendmail_mpe_getegid() 51490792Sgshapiro{ 51590792Sgshapiro if (sendmail_mpe_emulgid() && sendmail_mpe_egid != -1) 51690792Sgshapiro return sendmail_mpe_egid; 51790792Sgshapiro return getegid(); 51890792Sgshapiro} 51990792Sgshapiro 52090792Sgshapiro/* 52190792Sgshapiro** SENDMAIL_MPE_GETEUID -- shadow function for geteuid() 52290792Sgshapiro** 52390792Sgshapiro** If emulation mode is in effect, return the saved euid; otherwise 52490792Sgshapiro** return the value of the real geteuid() function. 52590792Sgshapiro** 52690792Sgshapiro** Note that the initial value of the saved euid is zero, to simulate 52790792Sgshapiro** a setuid-root program. 52890792Sgshapiro** 52990792Sgshapiro** Parameters: 53090792Sgshapiro** none 53190792Sgshapiro** 53290792Sgshapiro** Returns: 53390792Sgshapiro** emulated euid if in emulation mode, else true euid. 53490792Sgshapiro*/ 53590792Sgshapiro 53690792Sgshapirostatic uid_t sendmail_mpe_euid = 0; 53790792Sgshapiro 53890792Sgshapiro#undef geteuid 53990792Sgshapirouid_t 54090792Sgshapirosendmail_mpe_geteuid() 54190792Sgshapiro{ 54290792Sgshapiro if (sendmail_mpe_emuluid()) 54390792Sgshapiro return sendmail_mpe_euid; 54490792Sgshapiro return geteuid(); 54590792Sgshapiro} 54690792Sgshapiro 54790792Sgshapiro/* 54890792Sgshapiro** SENDMAIL_MPE_SETGID -- shadow function for setgid() 54990792Sgshapiro** 55090792Sgshapiro** Simulate a call to setgid() without actually calling the real 55190792Sgshapiro** function. Implement the expected uid 0 semantics. 55290792Sgshapiro** 55390792Sgshapiro** Note that sendmail will also be calling setuid() which will force an 55490792Sgshapiro** implicit real setgid() to the proper primary gid. So it doesn't matter 55590792Sgshapiro** that we don't actually alter the real gid in this shadow function. 55690792Sgshapiro** 55790792Sgshapiro** Parameters: 55890792Sgshapiro** gid -- desired gid. 55990792Sgshapiro** 56090792Sgshapiro** Returns: 56190792Sgshapiro** 0 -- emulated success 56290792Sgshapiro** -1 -- emulated failure 56390792Sgshapiro*/ 56490792Sgshapiro 56590792Sgshapiro#undef setgid 56690792Sgshapiroint 56790792Sgshapirosendmail_mpe_setgid(gid) 56890792Sgshapiro gid_t gid; 56990792Sgshapiro{ 57090792Sgshapiro if (sendmail_mpe_emulgid()) 57190792Sgshapiro { 57290792Sgshapiro if (gid == getgid() || sendmail_mpe_euid == 0) 57390792Sgshapiro { 57490792Sgshapiro sendmail_mpe_egid = gid; 57590792Sgshapiro return 0; 57690792Sgshapiro } 57790792Sgshapiro errno = EINVAL; 57890792Sgshapiro return -1; 57990792Sgshapiro } 58090792Sgshapiro return setgid(gid); 58190792Sgshapiro} 58290792Sgshapiro 58390792Sgshapiro/* 58490792Sgshapiro** SENDMAIL_MPE_SETUID -- shadow function for setuid() 58590792Sgshapiro** 58690792Sgshapiro** setuid() is broken as of MPE 7.0 in that it changes the current 58790792Sgshapiro** working directory to be the home directory of the new uid. Thus 58890792Sgshapiro** we must obtain the cwd and restore it after the setuid(). 58990792Sgshapiro** 59090792Sgshapiro** Note that expected uid 0 semantics have been added, as well as 59190792Sgshapiro** remembering the new uid for later use by the other shadow functions. 59290792Sgshapiro** 59390792Sgshapiro** Parameters: 59490792Sgshapiro** uid -- desired uid. 59590792Sgshapiro** 59690792Sgshapiro** Returns: 59790792Sgshapiro** 0 -- success 59890792Sgshapiro** -1 -- failure 59990792Sgshapiro** 60090792Sgshapiro** Globals: 60190792Sgshapiro** sendmail_mpe_euid 60290792Sgshapiro*/ 60390792Sgshapiro 60490792Sgshapiro#undef setuid 60590792Sgshapiroint 60690792Sgshapirosendmail_mpe_setuid(uid) 60790792Sgshapiro uid_t uid; 60890792Sgshapiro{ 60990792Sgshapiro char *cwd; 61098121Sgshapiro char cwd_buf[PATH_MAX + 1]; 61190792Sgshapiro int result; 61290792Sgshapiro extern void GETPRIVMODE __P((void)); 61390792Sgshapiro extern void GETUSERMODE __P((void)); 61490792Sgshapiro 61590792Sgshapiro if (sendmail_mpe_emuluid()) 61690792Sgshapiro { 61790792Sgshapiro if (uid == 0) 61890792Sgshapiro { 61990792Sgshapiro if (sendmail_mpe_euid != 0) 62090792Sgshapiro { 62190792Sgshapiro errno = EINVAL; 62290792Sgshapiro return -1; 62390792Sgshapiro } 62490792Sgshapiro sendmail_mpe_euid = 0; 62590792Sgshapiro return 0; 62690792Sgshapiro } 62790792Sgshapiro 62890792Sgshapiro /* Preserve the current working directory */ 62990792Sgshapiro if ((cwd = getcwd(cwd_buf, PATH_MAX + 1)) == NULL) 63090792Sgshapiro return -1; 63190792Sgshapiro 63290792Sgshapiro GETPRIVMODE(); 63390792Sgshapiro result = setuid(uid); 63490792Sgshapiro GETUSERMODE(); 63590792Sgshapiro 63690792Sgshapiro /* Restore the current working directory */ 63790792Sgshapiro chdir(cwd_buf); 63890792Sgshapiro 63990792Sgshapiro if (result == 0) 64090792Sgshapiro sendmail_mpe_euid = uid; 64190792Sgshapiro 64290792Sgshapiro return result; 64390792Sgshapiro } 64490792Sgshapiro return setuid(uid); 64590792Sgshapiro} 64690792Sgshapiro#endif /* MPE */ 647