From: Todd C. Miller Date: Thu, 30 Sep 2004 17:22:37 +0000 (+0000) Subject: Define Err() and Errx() that are like err() and errx() but call Exit() X-Git-Tag: SUDO_1_7_0~916 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2b020f9999f56d9bf5c69f71ce65e288a12d9834;p=sudo Define Err() and Errx() that are like err() and errx() but call Exit() instead of exit(). Build private copy of alloc.o for visudo that calls Err() and Errx(). --- diff --git a/Makefile.in b/Makefile.in index e9ed2507d..d4ddd41cb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -118,15 +118,17 @@ HDRS = compat.h def_data.h defaults.h ins_2001.h ins_classic.h ins_csops.h \ AUTH_OBJS = sudo_auth.o @AUTH_OBJS@ -PARSEOBJS = sudo.tab.o lex.yy.o alloc.o defaults.o +PARSEOBJS = sudo.tab.o lex.yy.o defaults.o -SUDOBJS = check.o env.o getspwuid.o gettime.o goodpath.o fileops.o find_path.o \ - interfaces.o logging.o parse.o set_perms.o sudo.o sudo_edit.o \ - tgetpass.o zero_bytes.o @SUDO_OBJS@ $(AUTH_OBJS) $(PARSEOBJS) +SUDOBJS = alloc.o check.o env.o getspwuid.o gettime.o goodpath.o fileops.o \ + find_path.o interfaces.o logging.o parse.o set_perms.o sudo.o \ + sudo_edit.o tgetpass.o zero_bytes.o @SUDO_OBJS@ $(AUTH_OBJS) \ + $(PARSEOBJS) -VISUDOBJS = visudo.o fileops.o gettime.o goodpath.o find_path.o $(PARSEOBJS) +VISUDOBJS = visudo.o fileops.o gettime.o goodpath.o find_path.o vsalloc.o \ + $(PARSEOBJS) -TESTOBJS = interfaces.o testsudoers.o $(PARSEOBJS) +TESTOBJS = alloc.o interfaces.o testsudoers.o $(PARSEOBJS) LIBOBJS = @LIBOBJS@ @ALLOCA@ @@ -233,6 +235,10 @@ strerror.o: strerror.c config.h utime.o: utime.c config.h pathnames.h compat.h emul/utime.h ldap.o: ldap.c $(SUDODEP) parse.h +# Build special copy of alloc.c for visudo that calls Exit() +vsalloc.o: alloc.c $(SUDODEP) + $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) '-Derr=Err' '-Derrx=Errx' $(srcdir)/alloc.c + # Authentication functions live in "auth" dir and so need extra care sudo_auth.o: $(authdir)/sudo_auth.c $(AUTHDEP) $(INSDEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/sudo_auth.c diff --git a/visudo.c b/visudo.c index 909c4421c..a2eb71884 100644 --- a/visudo.c +++ b/visudo.c @@ -68,6 +68,11 @@ #include #include #include +#ifdef __STDC__ +# include +#else +# include +#endif #include "sudo.h" #include "parse.h" @@ -97,6 +102,7 @@ static int run_command __P((char *, char **)); static int check_syntax __P((char *)); static int edit_sudoers __P((struct sudoersfile *, char *, int)); static int reparse_sudoers __P((char *editor)); +static int install_sudoers __P((struct sudoersfile *)); static char *get_editor __P((void)); int command_matches __P((char *, char *)); int addr_matches __P((char *)); @@ -106,6 +112,8 @@ int usergr_matches __P((char *, char *, struct passwd *)); int userpw_matches __P((char *, char *, struct passwd *)); void yyerror __P((const char *)); void yyrestart __P((FILE *)); +void Err __P((int, const char *, ...)); +void Errx __P((int, const char *, ...)); /* * External globals exported by the parser @@ -183,7 +191,7 @@ main(argc, argv) /* Mock up a fake sudo_user struct. */ user_host = user_shost = user_cmnd = ""; if ((sudo_user.pw = getpwuid(getuid())) == NULL) - errx(1, "you don't exist in the passwd database"); + Errx(1, "you don't exist in the passwd database"); /* Setup defaults data structures. */ init_defaults(); @@ -196,9 +204,9 @@ main(argc, argv) * existing errors and to pull in editor and env_editor conf values. */ if ((yyin = open_sudoers(sudoers_path, NULL)) == NULL) - err(1, "%s", sudoers_path); + Err(1, "%s", sudoers_path); if (!lock_file(fileno(yyin), SUDO_TLOCK)) - errx(1, "%s busy, try again later", sudoers_path); + Errx(1, "%s busy, try again later", sudoers_path); yyout = stdout; ch = quiet; quiet = 1; @@ -225,6 +233,14 @@ main(argc, argv) /* Check edited files for a parse error and re-edit any that fail. */ reparse_sudoers(editor); + /* Install the sudoers temp files. */ + for (sp = sudoerslist.first; sp != NULL; sp = sp->next) { + if (!sp->modified) + (void) unlink(sp->tpath); + else + install_sudoers(sp); /* XXX rval */ + } + exit(0); } @@ -254,7 +270,7 @@ edit_sudoers(sp, editor, lineno) #else if (stat(sp->path, &sb) == -1) #endif - err(1, "can't stat %s", sp->path); + Err(1, "can't stat %s", sp->path); orig_size = sb.st_size; orig_mtim.tv_sec = mtim_getsec(sb); orig_mtim.tv_nsec = mtim_getnsec(sb); @@ -264,14 +280,14 @@ edit_sudoers(sp, editor, lineno) easprintf(&sp->tpath, "%s.tmp", sp->path); tfd = open(sp->tpath, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (tfd < 0) - err(1, "%s", sp->tpath); + Err(1, "%s", sp->tpath); /* Copy sp->path -> sp->tpath and reset the mtime. */ if (orig_size != 0) { (void) lseek(sp->fd, (off_t)0, SEEK_SET); while ((n = read(sp->fd, buf, sizeof(buf))) > 0) if (write(tfd, buf, n) != n) - err(1, "write error"); + Err(1, "write error"); /* Add missing newline at EOF if needed. */ if (n > 0 && buf[n - 1] != '\n') { @@ -351,6 +367,7 @@ edit_sudoers(sp, editor, lineno) /* * Parse sudoers after editing and re-edit any ones that caused a parse error. + * Returns TRUE on success, else FALSE. */ static int reparse_sudoers(editor) @@ -370,7 +387,7 @@ reparse_sudoers(editor) if (fp == NULL) { warnx("can't re-open temporary file (%s), %s unchanged.", sp->tpath, sp->path); - return(FALSE); + Exit(-1); } /* Clean slate for each parse */ @@ -395,9 +412,7 @@ reparse_sudoers(editor) switch (whatnow()) { case 'Q' : parse_error = FALSE; /* ignore parse error */ break; - case 'x' : /* if (orig_size == 0) - unlink(sp->path);*/ /* XXX rm new file */ - return(TRUE); /* XXX */ + case 'x' : Exit(0); break; } } @@ -410,7 +425,7 @@ reparse_sudoers(editor) } } if (sp == NULL) - errx(1, "internal error, can't find %s in list!", sudoers); + Errx(1, "internal error, can't find %s in list!", sudoers); } /* If any new #include directives were added, edit them too. */ @@ -422,65 +437,69 @@ reparse_sudoers(editor) } } while (parse_error); - for (sp = sudoerslist.first; sp != NULL; sp = sp->next) { - if (!sp->modified) { - (void) unlink(sp->tpath); - continue; - } + return(TRUE); +} - /* - * Change mode and ownership of temp file so when - * we move it to sp->path things are kosher. - */ - if (chown(sp->tpath, SUDOERS_UID, SUDOERS_GID) != 0) { - warn("unable to set (uid, gid) of %s to (%d, %d)", - sp->tpath, SUDOERS_UID, SUDOERS_GID); - return(FALSE); - } - if (chmod(sp->tpath, SUDOERS_MODE) != 0) { - warn("unable to change mode of %s to 0%o", sp->tpath, SUDOERS_MODE); - return(FALSE); - } +/* + * Set the owner and mode on a sudoers temp file and + * move it into place. Returns TRUE on success, else FALSE. + */ +static int +install_sudoers(sp) + struct sudoersfile *sp; +{ + /* + * Change mode and ownership of temp file so when + * we move it to sp->path things are kosher. + */ + if (chown(sp->tpath, SUDOERS_UID, SUDOERS_GID) != 0) { + warn("unable to set (uid, gid) of %s to (%d, %d)", + sp->tpath, SUDOERS_UID, SUDOERS_GID); + return(FALSE); + } + if (chmod(sp->tpath, SUDOERS_MODE) != 0) { + warn("unable to change mode of %s to 0%o", sp->tpath, SUDOERS_MODE); + return(FALSE); + } - /* - * Now that sp->tpath is sane (parses ok) it needs to be - * rename(2)'d to sp->path. If the rename(2) fails we try using - * mv(1) in case sp->tpath and sp->path are on different file systems. - */ - if (rename(sp->tpath, sp->path) == 0) { - free(sp->tpath); - sp->tpath = NULL; - } else { - if (errno == EXDEV) { - char *av[4]; - warnx("%s and %s not on the same file system, using mv to rename", - sp->tpath, sp->path); - - /* Build up argument vector for the command */ - if ((av[0] = strrchr(_PATH_MV, '/')) != NULL) - av[0]++; - else - av[0] = _PATH_MV; - av[1] = sp->tpath; - av[2] = sp->path; - av[3] = NULL; - - /* And run it... */ - if (run_command(_PATH_MV, av)) { - warnx("command failed: '%s %s %s', %s unchanged", - _PATH_MV, sp->tpath, sp->path, sp->path); - (void) unlink(sp->tpath); - free(sp->tpath); - sp->tpath = NULL; - return(FALSE); - } + /* + * Now that sp->tpath is sane (parses ok) it needs to be + * rename(2)'d to sp->path. If the rename(2) fails we try using + * mv(1) in case sp->tpath and sp->path are on different file systems. + */ + if (rename(sp->tpath, sp->path) == 0) { + free(sp->tpath); + sp->tpath = NULL; + } else { + if (errno == EXDEV) { + char *av[4]; + warnx("%s and %s not on the same file system, using mv to rename", + sp->tpath, sp->path); + + /* Build up argument vector for the command */ + if ((av[0] = strrchr(_PATH_MV, '/')) != NULL) + av[0]++; + else + av[0] = _PATH_MV; + av[1] = sp->tpath; + av[2] = sp->path; + av[3] = NULL; + + /* And run it... */ + if (run_command(_PATH_MV, av)) { + warnx("command failed: '%s %s %s', %s unchanged", + _PATH_MV, sp->tpath, sp->path, sp->path); + (void) unlink(sp->tpath); free(sp->tpath); sp->tpath = NULL; - } else { - warn("error renaming %s, %s unchanged", sp->tpath, sp->path); - (void) unlink(sp->tpath); return(FALSE); } + free(sp->tpath); + sp->tpath = NULL; + } else { + warn("error renaming %s, %s unchanged", sp->tpath, sp->path); + (void) unlink(sp->tpath); + return(FALSE); } } return(TRUE); @@ -702,7 +721,6 @@ open_sudoers(path, keepopen) break; } if (entry == NULL) { - /* XXX - better cleanup on failure! */ entry = emalloc(sizeof(*entry)); entry->path = estrdup(path); entry->modified = 0; @@ -711,13 +729,13 @@ open_sudoers(path, keepopen) entry->tpath = NULL; if (entry->fd == -1) { warn("%s", entry->path); + free(entry); return(NULL); } - /* XXX - wrap errx */ if (!lock_file(entry->fd, SUDO_TLOCK)) - errx(1, "%s busy, try again later", entry->path); + Errx(1, "%s busy, try again later", entry->path); if ((fp = fdopen(entry->fd, "r")) == NULL) - err(1, "%s", entry->path); + Err(1, "%s", entry->path); if (sudoerslist.last == NULL) sudoerslist.first = sudoerslist.last = entry; else { @@ -730,11 +748,10 @@ open_sudoers(path, keepopen) /* Already exists, open .tmp version if there is one. */ if (entry->tpath != NULL) { if ((fp = fopen(entry->tpath, "r")) == NULL) - err(1, "%s", entry->tpath); + Err(1, "%s", entry->tpath); } else { if ((fp = fdopen(entry->fd, "r")) == NULL) - err(1, "%s", entry->path); - + Err(1, "%s", entry->path); } } return(fp); @@ -864,6 +881,54 @@ Exit(sig) exit(-sig); } +/* + * Like err() but calls Exit() + */ +void +#ifdef __STDC__ +Err(int eval, const char *fmt, ...) +#else +Err(eval, fmt, va_alist) + int eval; + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + vwarn(fmt, ap); + va_end(ap); + Exit(eval); +} + +/* + * Like errx() but calls Exit() + */ +void +#ifdef __STDC__ +Errx(int eval, const char *fmt, ...) +#else +Errx(eval, fmt, va_alist) + int eval; + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + vwarnx(fmt, ap); + va_end(ap); + Exit(eval); +} + static void usage() {