Imported Upstream version 1.8.5
[debian/sudo] / plugins / sudoers / logging.c
index 82f3e69095bdc7d363c8e0ecea4ddd28fb6f5230..4d3e13e47e0e9c82c20ee5021a2d87cdb6d5ca8c 100644 (file)
@@ -91,6 +91,7 @@ mysyslog(int pri, const char *fmt, ...)
 #endif
     char buf[MAXSYSLOGLEN+1];
     va_list ap;
+    debug_decl(mysyslog, SUDO_DEBUG_LOGGING)
 
     va_start(ap, fmt);
 #ifdef LOG_NFACILITIES
@@ -113,6 +114,7 @@ mysyslog(int pri, const char *fmt, ...)
 #endif /* BROKEN_SYSLOG */
     va_end(ap);
     closelog();
+    debug_return;
 }
 
 #define FMT_FIRST "%8s : %s"
@@ -128,6 +130,7 @@ do_syslog(int pri, char *msg)
     size_t len, maxlen;
     char *p, *tmp, save;
     const char *fmt;
+    debug_decl(do_syslog, SUDO_DEBUG_LOGGING)
 
 #ifdef HAVE_SETLOCALE
     const char *old_locale = estrdup(setlocale(LC_ALL, NULL));
@@ -138,8 +141,8 @@ do_syslog(int pri, char *msg)
     /*
      * Log the full line, breaking into multiple syslog(3) calls if necessary
      */
-    fmt = FMT_FIRST;
-    maxlen = MAXSYSLOGLEN - (sizeof(FMT_FIRST) - 6 + strlen(user_name));
+    fmt = _(FMT_FIRST);
+    maxlen = MAXSYSLOGLEN - (strlen(fmt) - 5 + strlen(user_name));
     for (p = msg; *p != '\0'; ) {
        len = strlen(p);
        if (len > maxlen) {
@@ -166,36 +169,38 @@ do_syslog(int pri, char *msg)
            mysyslog(pri, fmt, user_name, p);
            p += len;
        }
-       fmt = FMT_CONTD;
-       maxlen = MAXSYSLOGLEN - (sizeof(FMT_CONTD) - 6 + strlen(user_name));
+       fmt = _(FMT_CONTD);
+       maxlen = MAXSYSLOGLEN - (strlen(fmt) - 5 + strlen(user_name));
     }
 
 #ifdef HAVE_SETLOCALE
     setlocale(LC_ALL, old_locale);
     efree((void *)old_locale);
 #endif /* HAVE_SETLOCALE */
+
+    debug_return;
 }
 
 static void
 do_logfile(char *msg)
 {
     char *full_line;
-    char *beg, *oldend, *end;
-    FILE *fp;
+    size_t len;
     mode_t oldmask;
-    size_t maxlen;
+    time_t now;
+    FILE *fp;
+    debug_decl(do_logfile, SUDO_DEBUG_LOGGING)
 
     oldmask = umask(077);
-    maxlen = def_loglinelen > 0 ? def_loglinelen : 0;
     fp = fopen(def_logfile, "a");
     (void) umask(oldmask);
     if (fp == NULL) {
-       send_mail("Can't open log file: %s: %s", def_logfile, strerror(errno));
+       send_mail(_("unable to open log file: %s: %s"),
+           def_logfile, strerror(errno));
     } else if (!lock_file(fileno(fp), SUDO_LOCK)) {
-       send_mail("Can't lock log file: %s: %s", def_logfile, strerror(errno));
+       send_mail(_("unable to lock log file: %s: %s"),
+           def_logfile, strerror(errno));
     } else {
-       time_t now;
-
 #ifdef HAVE_SETLOCALE
        const char *old_locale = estrdup(setlocale(LC_ALL, NULL));
        if (!setlocale(LC_ALL, def_sudoers_locale))
@@ -203,7 +208,7 @@ do_logfile(char *msg)
 #endif /* HAVE_SETLOCALE */
 
        now = time(NULL);
-       if (def_loglinelen == 0) {
+       if (def_loglinelen < sizeof(LOG_INDENT)) {
            /* Don't pretty-print long log file lines (hard to grep) */
            if (def_log_host)
                (void) fprintf(fp, "%s : %s : HOST=%s : %s\n",
@@ -213,59 +218,16 @@ do_logfile(char *msg)
                    get_timestr(now, def_log_year), user_name, msg);
        } else {
            if (def_log_host)
-               easprintf(&full_line, "%s : %s : HOST=%s : %s",
+               len = easprintf(&full_line, "%s : %s : HOST=%s : %s",
                    get_timestr(now, def_log_year), user_name, user_shost, msg);
            else
-               easprintf(&full_line, "%s : %s : %s",
+               len = easprintf(&full_line, "%s : %s : %s",
                    get_timestr(now, def_log_year), user_name, msg);
 
            /*
-            * Print out full_line with word wrap
+            * Print out full_line with word wrap around def_loglinelen chars.
             */
-           beg = end = full_line;
-           while (beg) {
-               oldend = end;
-               end = strchr(oldend, ' ');
-
-               if (maxlen > 0 && end) {
-                   *end = '\0';
-                   if (strlen(beg) > maxlen) {
-                       /* too far, need to back up & print the line */
-
-                       if (beg == (char *)full_line)
-                           maxlen -= 4;        /* don't indent first line */
-
-                       *end = ' ';
-                       if (oldend != beg) {
-                           /* rewind & print */
-                           end = oldend-1;
-                           while (*end == ' ')
-                               --end;
-                           *(++end) = '\0';
-                           (void) fprintf(fp, "%s\n    ", beg);
-                           *end = ' ';
-                       } else {
-                           (void) fprintf(fp, "%s\n    ", beg);
-                       }
-
-                       /* reset beg to point to the start of the new substr */
-                       beg = end;
-                       while (*beg == ' ')
-                           ++beg;
-                   } else {
-                       /* we still have room */
-                       *end = ' ';
-                   }
-
-                   /* remove leading whitespace */
-                   while (*end == ' ')
-                       ++end;
-               } else {
-                   /* final line */
-                   (void) fprintf(fp, "%s\n", beg);
-                   beg = NULL;                 /* exit condition */
-               }
-           }
+           writeln_wrap(fp, full_line, len, def_loglinelen);
            efree(full_line);
        }
        (void) fflush(fp);
@@ -277,6 +239,7 @@ do_logfile(char *msg)
        efree((void *)old_locale);
 #endif /* HAVE_SETLOCALE */
     }
+    debug_return;
 }
 
 /*
@@ -285,16 +248,16 @@ do_logfile(char *msg)
 void
 log_denial(int status, int inform_user)
 {
-    char *message;
-    char *logline;
+    char *logline, *message;
+    debug_decl(log_denial, SUDO_DEBUG_LOGGING)
 
     /* Set error message. */
     if (ISSET(status, FLAG_NO_USER))
-       message = "user NOT in sudoers";
+       message = _("user NOT in sudoers");
     else if (ISSET(status, FLAG_NO_HOST))
-       message = "user NOT authorized on host";
+       message = _("user NOT authorized on host");
     else
-       message = "command not allowed";
+       message = _("command not allowed");
 
     logline = new_logline(message, 0);
 
@@ -304,18 +267,18 @@ log_denial(int status, int inform_user)
     /* Inform the user if they failed to authenticate.  */
     if (inform_user) {
        if (ISSET(status, FLAG_NO_USER)) {
-           sudo_printf(SUDO_CONV_ERROR_MSG, "%s is not in the sudoers file.  "
-               "This incident will be reported.\n", user_name);
+           sudo_printf(SUDO_CONV_ERROR_MSG, _("%s is not in the sudoers "
+               "file.  This incident will be reported.\n"), user_name);
        } else if (ISSET(status, FLAG_NO_HOST)) {
-           sudo_printf(SUDO_CONV_ERROR_MSG, "%s is not allowed to run sudo "
-               "on %s.  This incident will be reported.\n",
+           sudo_printf(SUDO_CONV_ERROR_MSG, _("%s is not allowed to run sudo "
+               "on %s.  This incident will be reported.\n"),
                user_name, user_shost);
        } else if (ISSET(status, FLAG_NO_CHECK)) {
-           sudo_printf(SUDO_CONV_ERROR_MSG, "Sorry, user %s may not run "
-               "sudo on %s.\n", user_name, user_shost);
+           sudo_printf(SUDO_CONV_ERROR_MSG, _("Sorry, user %s may not run "
+               "sudo on %s.\n"), user_name, user_shost);
        } else {
-           sudo_printf(SUDO_CONV_ERROR_MSG, "Sorry, user %s is not allowed "
-               "to execute '%s%s%s' as %s%s%s on %s.\n",
+           sudo_printf(SUDO_CONV_ERROR_MSG, _("Sorry, user %s is not allowed "
+               "to execute '%s%s%s' as %s%s%s on %s.\n"),
                user_name, user_cmnd, user_args ? " " : "",
                user_args ? user_args : "",
                list_pw ? list_pw->pw_name : runas_pw ?
@@ -333,6 +296,7 @@ log_denial(int status, int inform_user)
        do_logfile(logline);
 
     efree(logline);
+    debug_return;
 }
 
 /*
@@ -342,6 +306,7 @@ void
 log_allowed(int status)
 {
     char *logline;
+    debug_decl(log_allowed, SUDO_DEBUG_LOGGING)
 
     logline = new_logline(NULL, 0);
 
@@ -357,20 +322,21 @@ log_allowed(int status)
        do_logfile(logline);
 
     efree(logline);
+    debug_return;
 }
 
-void
-log_error(int flags, const char *fmt, ...)
+/*
+ * Perform logging for log_error()/log_fatal()
+ */
+static void
+vlog_error(int flags, const char *fmt, va_list ap)
 {
     int serrno = errno;
-    char *message;
-    char *logline;
-    va_list ap;
+    char *logline, *message;
+    debug_decl(vlog_error, SUDO_DEBUG_LOGGING)
 
     /* Expand printf-style format + args. */
-    va_start(ap, fmt);
     evasprintf(&message, fmt, ap);
-    va_end(ap);
 
     /* Become root if we are not already to avoid user interference */
     set_perms(PERM_ROOT|PERM_NOEXIT);
@@ -410,10 +376,38 @@ log_error(int flags, const char *fmt, ...)
 
     restore_perms();
 
-    if (!ISSET(flags, NO_EXIT)) {
-       plugin_cleanup(0);
-       siglongjmp(error_jmp, 1);
-    }
+    debug_return;
+}
+
+void
+log_error(int flags, const char *fmt, ...)
+{
+    va_list ap;
+    debug_decl(log_error, SUDO_DEBUG_LOGGING)
+
+    /* Log the error. */
+    va_start(ap, fmt);
+    vlog_error(flags, fmt, ap);
+    va_end(ap);
+
+    debug_return;
+}
+
+void
+log_fatal(int flags, const char *fmt, ...)
+{
+    va_list ap;
+    debug_decl(log_error, SUDO_DEBUG_LOGGING)
+
+    /* Log the error. */
+    va_start(ap, fmt);
+    vlog_error(flags, fmt, ap);
+    va_end(ap);
+
+    /* Exit the plugin. */
+    plugin_cleanup(0);
+    sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
+    siglongjmp(error_jmp, 1);
 }
 
 #define MAX_MAILFLAGS  63
@@ -440,23 +434,26 @@ send_mail(const char *fmt, ...)
        NULL
     };
 #endif /* NO_ROOT_MAILER */
+    debug_decl(send_mail, SUDO_DEBUG_LOGGING)
 
     /* Just return if mailer is disabled. */
     if (!def_mailerpath || !def_mailto)
-       return;
+       debug_return;
 
     /* Fork and return, child will daemonize. */
-    switch (pid = fork()) {
+    switch (pid = sudo_debug_fork()) {
        case -1:
            /* Error. */
-           error(1, "cannot fork");
+           error(1, _("unable to fork"));
            break;
        case 0:
            /* Child. */
            switch (pid = fork()) {
                case -1:
                    /* Error. */
-                   mysyslog(LOG_ERR, "cannot fork: %m");
+                   mysyslog(LOG_ERR, _("unable to fork: %m"));
+                   sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to fork: %s",
+                       strerror(errno));
                    _exit(1);
                case 0:
                    /* Grandchild continues below. */
@@ -471,7 +468,7 @@ send_mail(const char *fmt, ...)
            do {
                rv = waitpid(pid, &status, 0);
            } while (rv == -1 && errno == EINTR);
-           return;
+           return; /* not debug */
     }
 
     /* Daemonize - disassociate from session/tty. */
@@ -506,14 +503,20 @@ send_mail(const char *fmt, ...)
     (void) sigaction(SIGPIPE, &sa, NULL);
 
     if (pipe(pfd) == -1) {
-       mysyslog(LOG_ERR, "cannot open pipe: %m");
+       mysyslog(LOG_ERR, _("unable to open pipe: %m"));
+       sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to open pipe: %s",
+           strerror(errno));
+       sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
        _exit(1);
     }
 
-    switch (pid = fork()) {
+    switch (pid = sudo_debug_fork()) {
        case -1:
            /* Error. */
-           mysyslog(LOG_ERR, "cannot fork: %m");
+           mysyslog(LOG_ERR, _("unable to fork: %m"));
+           sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to fork: %s",
+               strerror(errno));
+           sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
            _exit(1);
            break;
        case 0:
@@ -525,7 +528,9 @@ send_mail(const char *fmt, ...)
                /* Child, set stdin to output side of the pipe */
                if (pfd[0] != STDIN_FILENO) {
                    if (dup2(pfd[0], STDIN_FILENO) == -1) {
-                       mysyslog(LOG_ERR, "cannot dup stdin: %m");
+                       mysyslog(LOG_ERR, _("unable to dup stdin: %m"));
+                       sudo_debug_printf(SUDO_DEBUG_ERROR,
+                           "unable to dup stdin: %s", strerror(errno));
                        _exit(127);
                    }
                    (void) close(pfd[0]);
@@ -559,7 +564,9 @@ send_mail(const char *fmt, ...)
                set_perms(PERM_FULL_USER|PERM_NOEXIT);
                execv(mpath, argv);
 #endif /* NO_ROOT_MAILER */
-               mysyslog(LOG_ERR, "cannot execute %s: %m", mpath);
+               mysyslog(LOG_ERR, _("unable to execute %s: %m"), mpath);
+               sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to execute %s: %s",
+                   mpath, strerror(errno));
                _exit(127);
            }
            break;
@@ -605,6 +612,7 @@ send_mail(const char *fmt, ...)
     do {
         rv = waitpid(pid, &status, 0);
     } while (rv == -1 && errno == EINTR);
+    sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys);
     _exit(0);
 }
 
@@ -614,11 +622,12 @@ send_mail(const char *fmt, ...)
 static int
 should_mail(int status)
 {
+    debug_decl(should_mail, SUDO_DEBUG_LOGGING)
 
-    return def_mail_always || ISSET(status, VALIDATE_ERROR) ||
+    debug_return_bool(def_mail_always || ISSET(status, VALIDATE_ERROR) ||
        (def_mail_no_user && ISSET(status, FLAG_NO_USER)) ||
        (def_mail_no_host && ISSET(status, FLAG_NO_HOST)) ||
-       (def_mail_no_perms && !ISSET(status, VALIDATE_OK));
+       (def_mail_no_perms && !ISSET(status, VALIDATE_OK)));
 }
 
 #define        LL_TTY_STR      "TTY="
@@ -647,6 +656,7 @@ new_logline(const char *message, int serrno)
     char *errstr = NULL;
     char *evstr = NULL;
     char *line, sessid[7], *tsid = NULL;
+    debug_decl(new_logline, SUDO_DEBUG_LOGGING)
 
     /* A TSID may be a sudoers-style session ID or a free-form string. */
     if (sudo_user.iolog_file != NULL) {
@@ -767,7 +777,7 @@ new_logline(const char *message, int serrno)
        }
     }
 
-    return line;
+    debug_return_str(line);
 toobig:
-    errorx(1, "internal error: insufficient space for log line");
+    errorx(1, _("internal error: insufficient space for log line"));
 }