Imported Upstream version 1.6.8p5
[debian/sudo] / logging.c
index 723d19e99fcdd3662d1ffacfab4cb9bf1bc6d1c5..1e1b997be6ad701bf2a03afe568039609fd5f60d 100644 (file)
--- a/logging.c
+++ b/logging.c
@@ -1,37 +1,27 @@
 /*
- * Copyright (c) 1994-1996,1998-2001 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
+ * Copyright (c) 1994-1996,1998-2004 Todd C. Miller <Todd.Miller@courtesan.com>
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
  *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * 4. Products derived from this software may not be called "Sudo" nor
- *    may "Sudo" appear in their names without specific prior written
- *    permission from the author.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
  */
 
+#ifdef __TANDEM
+# include <floss.h>
+#endif
+
 #include "config.h"
 
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif /* HAVE_UNISTD_H */
+#ifdef HAVE_ERR_H
+# include <err.h>
+#else
+# include "emul/err.h"
+#endif /* HAVE_ERR_H */
 #include <pwd.h>
 #include <signal.h>
 #include <time.h>
@@ -65,7 +60,7 @@
 #include "sudo.h"
 
 #ifndef lint
-static const char rcsid[] = "$Sudo: logging.c,v 1.153 2002/01/16 21:28:25 millert Exp $";
+static const char rcsid[] = "$Sudo: logging.c,v 1.168 2004/05/17 20:08:46 millert Exp $";
 #endif /* lint */
 
 static void do_syslog          __P((int, char *));
@@ -107,9 +102,9 @@ mysyslog(pri, fmt, va_alist)
     va_start(ap);
 #endif
 #ifdef LOG_NFACILITIES
-    openlog(Argv[0], 0, def_ival(I_LOGFAC));
+    openlog("sudo", 0, def_syslog);
 #else
-    openlog(Argv[0], 0);
+    openlog("sudo", 0);
 #endif
     vsnprintf(buf, sizeof(buf), fmt, ap);
 #ifdef BROKEN_SYSLOG
@@ -137,7 +132,7 @@ do_syslog(pri, msg)
     int pri;
     char *msg;
 {
-    int count;
+    size_t count;
     char *p;
     char *tmp;
     char save;
@@ -162,9 +157,9 @@ do_syslog(pri, msg)
            *tmp = '\0';
 
            if (count == 0)
-               mysyslog(pri, "%8.8s : %s", user_name, p);
+               mysyslog(pri, "%8s : %s", user_name, p);
            else
-               mysyslog(pri, "%8.8s : (command continued) %s", user_name, p);
+               mysyslog(pri, "%8s : (command continued) %s", user_name, p);
 
            *tmp = save;                        /* restore saved character */
 
@@ -173,9 +168,9 @@ do_syslog(pri, msg)
                ;
        } else {
            if (count == 0)
-               mysyslog(pri, "%8.8s : %s", user_name, p);
+               mysyslog(pri, "%8s : %s", user_name, p);
            else
-               mysyslog(pri, "%8.8s : (command continued) %s", user_name, p);
+               mysyslog(pri, "%8s : (command continued) %s", user_name, p);
        }
     }
 }
@@ -188,32 +183,33 @@ do_logfile(msg)
     char *beg, *oldend, *end;
     FILE *fp;
     mode_t oldmask;
-    int maxlen = def_ival(I_LOGLINELEN);
+    size_t maxlen;
 
     oldmask = umask(077);
-    fp = fopen(def_str(I_LOGFILE), "a");
+    maxlen = def_loglinelen > 0 ? def_loglinelen : 0;
+    fp = fopen(def_logfile, "a");
     (void) umask(oldmask);
     if (fp == NULL) {
        easprintf(&full_line, "Can't open log file: %s: %s",
-           def_str(I_LOGFILE), strerror(errno));
+           def_logfile, strerror(errno));
        send_mail(full_line);
        free(full_line);
     } else if (!lock_file(fileno(fp), SUDO_LOCK)) {
        easprintf(&full_line, "Can't lock log file: %s: %s",
-           def_str(I_LOGFILE), strerror(errno));
+           def_logfile, strerror(errno));
        send_mail(full_line);
        free(full_line);
     } else {
-       if (def_ival(I_LOGLINELEN) == 0) {
+       if (def_loglinelen == 0) {
            /* Don't pretty-print long log file lines (hard to grep) */
-           if (def_flag(I_LOG_HOST))
+           if (def_log_host)
                (void) fprintf(fp, "%s : %s : HOST=%s : %s\n", get_timestr(),
                    user_name, user_shost, msg);
            else
                (void) fprintf(fp, "%s : %s : %s\n", get_timestr(),
                    user_name, msg);
        } else {
-           if (def_flag(I_LOG_HOST))
+           if (def_log_host)
                easprintf(&full_line, "%s : %s : HOST=%s : %s", get_timestr(),
                    user_name, user_shost, msg);
            else
@@ -288,19 +284,19 @@ log_auth(status, inform_user)
     char *logline;
     int pri;
 
-    if (status & VALIDATE_OK)
-       pri = def_ival(I_GOODPRI);
+    if (ISSET(status, VALIDATE_OK))
+       pri = def_syslog_goodpri;
     else
-       pri = def_ival(I_BADPRI);
+       pri = def_syslog_badpri;
 
     /* Set error message, if any. */
-    if (status & VALIDATE_OK)
+    if (ISSET(status, VALIDATE_OK))
        message = "";
-    else if (status & FLAG_NO_USER)
+    else if (ISSET(status, FLAG_NO_USER))
        message = "user NOT in sudoers ; ";
-    else if (status & FLAG_NO_HOST)
+    else if (ISSET(status, FLAG_NO_HOST))
        message = "user NOT authorized on host ; ";
-    else if (status & VALIDATE_NOT_OK)
+    else if (ISSET(status, VALIDATE_NOT_OK))
        message = "command not allowed ; ";
     else
        message = "unknown error ; ";
@@ -312,14 +308,14 @@ log_auth(status, inform_user)
     mail_auth(status, logline);                /* send mail based on status */
 
     /* Inform the user if they failed to authenticate.  */
-    if (inform_user && (status & VALIDATE_NOT_OK)) {
-       if (status & FLAG_NO_USER)
+    if (inform_user && ISSET(status, VALIDATE_NOT_OK)) {
+       if (ISSET(status, FLAG_NO_USER))
            (void) fprintf(stderr, "%s is not in the sudoers file.  %s",
                user_name, "This incident will be reported.\n");
-       else if (status & FLAG_NO_HOST)
+       else if (ISSET(status, FLAG_NO_HOST))
            (void) fprintf(stderr, "%s is not allowed to run sudo on %s.  %s",
                user_name, user_shost, "This incident will be reported.\n");
-       else if (status & FLAG_NO_CHECK)
+       else if (ISSET(status, FLAG_NO_CHECK))
            (void) fprintf(stderr, "Sorry, user %s may not run sudo on %s.\n",
                user_name, user_shost);
        else
@@ -332,9 +328,9 @@ log_auth(status, inform_user)
     /*
      * Log via syslog and/or a file.
      */
-    if (def_str(I_SYSLOG))
+    if (def_syslog)
        do_syslog(pri, logline);
-    if (def_str(I_LOGFILE))
+    if (def_logfile)
        do_logfile(logline);
 
     free(logline);
@@ -365,7 +361,7 @@ log_error(va_alist)
 
     /* Become root if we are not already to avoid user control */
     if (geteuid() != 0)
-       set_perms(PERM_ROOT, 0);
+       set_perms(PERM_ROOT);
 
     /* Expand printf-style format + args. */
     evasprintf(&message, fmt, ap);
@@ -399,10 +395,10 @@ log_error(va_alist)
     /*
      * Tell the user.
      */
-    (void) fprintf(stderr, "%s: %s", Argv[0], message);
     if (flags & USE_ERRNO)
-       (void) fprintf(stderr, ": %s", strerror(serrno));
-    (void) fputc('\n', stderr);
+       warn("%s", message);
+    else
+       warnx("%s", message);
 
     /*
      * Send a copy of the error via mail.
@@ -413,9 +409,9 @@ log_error(va_alist)
     /*
      * Log to syslog and/or a file.
      */
-    if (def_str(I_SYSLOG))
-       do_syslog(def_ival(I_BADPRI), logline);
-    if (def_str(I_LOGFILE))
+    if (def_syslog)
+       do_syslog(def_syslog_badpri, logline);
+    if (def_logfile)
        do_logfile(logline);
 
     free(message);
@@ -437,7 +433,8 @@ send_mail(line)
 {
     FILE *mail;
     char *p;
-    int pfd[2], pid, status;
+    int pfd[2];
+    pid_t pid;
     sigset_t set, oset;
 #ifndef NO_ROOT_MAILER
     static char *root_envp[] = {
@@ -450,25 +447,20 @@ send_mail(line)
 #endif
 
     /* Just return if mailer is disabled. */
-    if (!def_str(I_MAILERPATH) || !def_str(I_MAILTO))
+    if (!def_mailerpath || !def_mailto)
        return;
 
     (void) sigemptyset(&set);
     (void) sigaddset(&set, SIGCHLD);
     (void) sigprocmask(SIG_BLOCK, &set, &oset);
 
-    if (pipe(pfd) == -1) {
-       (void) fprintf(stderr, "%s: cannot open pipe: %s\n",
-           Argv[0], strerror(errno));
-       exit(1);
-    }
+    if (pipe(pfd) == -1)
+       err(1, "cannot open pipe");
 
     switch (pid = fork()) {
        case -1:
            /* Error. */
-           (void) fprintf(stderr, "%s: cannot fork: %s\n",
-               Argv[0], strerror(errno));
-           exit(1);
+           err(1, "cannot fork");
            break;
        case 0:
            {
@@ -484,8 +476,8 @@ send_mail(line)
                (void) close(pfd[1]);
 
                /* Build up an argv based the mailer path and flags */
-               mflags = estrdup(def_str(I_MAILERFLAGS));
-               mpath = estrdup(def_str(I_MAILERPATH));
+               mflags = estrdup(def_mailerflags);
+               mpath = estrdup(def_mailerpath);
                if ((argv[0] = strrchr(mpath, ' ')))
                    argv[0]++;
                else
@@ -507,10 +499,10 @@ send_mail(line)
                 * (so user cannot kill it) or as the user (for the paranoid).
                 */
 #ifndef NO_ROOT_MAILER
-               set_perms(PERM_FULL_ROOT, 0);
+               set_perms(PERM_FULL_ROOT);
                execve(mpath, argv, root_envp);
 #else
-               set_perms(PERM_FULL_USER, 0);
+               set_perms(PERM_FULL_USER);
                execv(mpath, argv);
 #endif /* NO_ROOT_MAILER */
                _exit(127);
@@ -523,8 +515,8 @@ send_mail(line)
 
     /* Pipes are all setup, send message via sendmail. */
     (void) fprintf(mail, "To: %s\nFrom: %s\nSubject: ",
-       def_str(I_MAILTO), user_name);
-    for (p = def_str(I_MAILSUB); *p; p++) {
+       def_mailto, user_name);
+    for (p = def_mailsub; *p; p++) {
        /* Expand escapes in the subject */
        if (*p == '%' && *(p+1) != '%') {
            switch (*(++p)) {
@@ -545,10 +537,8 @@ send_mail(line)
        get_timestr(), user_name, line);
     fclose(mail);
 
-    /* If mailer is done, wait for it now.  If not reapchild will get it.  */
-#ifdef sudo_waitpid
-    (void) sudo_waitpid(pid, &status, WNOHANG);
-#endif
+    /* If mailer is done, wait for it now.  If not, we'll get it later.  */
+    reapchild(SIGCHLD);
     (void) sigprocmask(SIG_SETMASK, &oset, NULL);
 }
 
@@ -563,17 +553,17 @@ mail_auth(status, line)
     int mail_mask;
 
     /* If any of these bits are set in status, we send mail. */
-    if (def_flag(I_MAIL_ALWAYS))
+    if (def_mail_always)
        mail_mask =
            VALIDATE_ERROR|VALIDATE_OK|FLAG_NO_USER|FLAG_NO_HOST|VALIDATE_NOT_OK;
     else {
        mail_mask = VALIDATE_ERROR;
-       if (def_flag(I_MAIL_NO_USER))
-           mail_mask |= FLAG_NO_USER;
-       if (def_flag(I_MAIL_NO_HOST))
-           mail_mask |= FLAG_NO_HOST;
-       if (def_flag(I_MAIL_NO_PERMS))
-           mail_mask |= VALIDATE_NOT_OK;
+       if (def_mail_no_user)
+           SET(mail_mask, FLAG_NO_USER);
+       if (def_mail_no_host)
+           SET(mail_mask, FLAG_NO_HOST);
+       if (def_mail_no_perms)
+           SET(mail_mask, VALIDATE_NOT_OK);
     }
 
     if ((status & mail_mask) != 0)
@@ -588,10 +578,12 @@ reapchild(sig)
     int sig;
 {
     int status, serrno = errno;
-
 #ifdef sudo_waitpid
-    while (sudo_waitpid(-1, &status, WNOHANG) != -1 && errno == EINTR)
-       ;
+    pid_t pid;
+
+    do {
+       pid = sudo_waitpid(-1, &status, WNOHANG);
+    } while (pid != 0 && (pid != -1 || errno == EINTR));
 #else
     (void) wait(&status);
 #endif
@@ -612,7 +604,7 @@ get_timestr()
     struct tm *timeptr;
 
     timeptr = localtime(&now);
-    if (def_flag(I_LOG_YEAR))
+    if (def_log_year)
        s = "%h %e %T %Y";
     else
        s = "%h %e %T";
@@ -625,7 +617,7 @@ get_timestr()
 #endif /* HAVE_STRFTIME */
 
     s = ctime(&now) + 4;               /* skip day of the week */
-    if (def_flag(I_LOG_YEAR))
+    if (def_log_year)
        s[20] = '\0';                   /* avoid the newline */
     else
        s[15] = '\0';                   /* don't care about year */