# The following is a security patch for rxvt, it (hopefully) avoids problems # with unauthorized users obtaining root. # # Based upon code provided by Marc Ewing (marc@redhat.com) for a previous # version of rxvt. # # BSD utmp code fixed again by peter@freebsd.org *** rxvt.h Sat Feb 19 09:41:52 1994 --- rxvt.h Wed Jan 10 23:42:09 1996 *************** *** 21,23 **** --- 21,27 ---- extern void clean_exit(int); extern void cleanutent(void); extern void makeutent(char *); + + void save_privs(void); + void get_privs(void); + void release_privs(void); *** rxvt.c Fri Aug 5 23:52:07 1994 --- rxvt.c Sat Feb 24 22:03:27 1996 *************** *** 45,50 **** --- 45,54 ---- int i; char *shell; char **com_argv; + + /* Save and give up setuid/setgid privileges */ + save_privs(); + release_privs(); for (i = 0; i < argc; i++) if (strcmp(argv[i],"-e") == 0) *** command.c Sat Feb 24 22:03:27 1996 --- command.c Sat Feb 24 22:12:26 1996 *************** *** 222,227 **** --- 222,251 ---- } #endif + static uid_t saved_uid; + static gid_t saved_gid; + + void save_privs() + { + saved_uid = geteuid(); + saved_gid = getegid(); + } + + void get_privs() + { + if (seteuid(saved_uid) < 0) + perror("failed to restore saved uid"); + if (setegid(saved_gid) < 0) + perror("failed to restore saved gid"); + } + + void release_privs() + { + if (seteuid(getuid()) < 0) + perror("failed to release setuid"); + if (setegid(getgid()) < 0) + perror("failed to release setgid"); + } /* Catch a SIGCHLD signal and exit if the direct child has died. */ *************** *** 337,344 **** --- 361,370 ---- gid = gr->gr_gid; else gid = -1; + get_privs(); fchown(ttyfd,uid,gid); fchmod(ttyfd,0600); + release_privs(); #endif #ifdef TIOCCONS if (console) *** utmp.c Tue Oct 4 08:47:56 1994 --- utmp.c Sat Feb 24 22:21:30 1996 *************** *** 71,79 **** extern char ttynam[]; extern struct stat ttyfd_stat; ! chmod(ttynam,ttyfd_stat.st_mode); ! ! chown(ttynam,ttyfd_stat.st_uid,ttyfd_stat.st_gid); #endif if(madeutent) cleanutent(); --- 71,83 ---- extern char ttynam[]; extern struct stat ttyfd_stat; ! get_privs(); ! if (chmod(ttynam,ttyfd_stat.st_mode) < 0) ! perror("cant reset tty modes"); ! ! if (chown(ttynam,ttyfd_stat.st_uid,ttyfd_stat.st_gid) < 0) ! perror("cant reset tty owner"); ! release_privs(); #endif if(madeutent) cleanutent(); *************** *** 166,171 **** --- 170,176 ---- { FILE *utmp; + get_privs(); if((utmp = fopen(UTMP,"r+")) == NULL) return -1; utmp_pos = get_tslot(ttyname) * sizeof(struct utmp); *************** *** 174,179 **** --- 179,185 ---- fseek(utmp,utmp_pos,0); fwrite((char *)u, sizeof(struct utmp),1,utmp); fclose(utmp); + release_privs(); madeutent = 1; return(utmp_pos); } *************** *** 228,239 **** --- 234,247 ---- FILE *ut; struct utmp u; + get_privs(); if((ut = fopen(UTMP,"r+")) == NULL) return; fseek(ut,utmp_pos,0); memset(&u,0,sizeof(u)); fwrite((char *)&u,sizeof(struct utmp),1,ut); fclose(ut); + release_privs(); } *************** *** 250,259 **** --- 258,269 ---- int write_utmp(struct utmp * u) { int pos; + get_privs(); utmpname(UTMP); setutent(); pututline(u); endutent(); + release_privs(); pos = (int)NULL; madeutent = 1; return(pos); *************** *** 305,311 **** { int pid; struct utmp *u; ! utmpname(UTMP); setutent(); pid = getpid(); --- 315,322 ---- { int pid; struct utmp *u; ! ! get_privs(); utmpname(UTMP); setutent(); pid = getpid(); *************** *** 333,338 **** --- 344,350 ---- endutent(); } } + release_privs(); } #endif /* BSD */