fix typo in changelog
[debian/sudo] / logging.c
1 /*
2  * Copyright (c) 1994-1996,1998-2007 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * Sponsored in part by the Defense Advanced Research Projects
17  * Agency (DARPA) and Air Force Research Laboratory, Air Force
18  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
19  */
20
21 #ifdef __TANDEM
22 # include <floss.h>
23 #endif
24
25 #include <config.h>
26
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <sys/stat.h>
30 #include <sys/ioctl.h>
31 #include <sys/wait.h>
32 #include <stdio.h>
33 #ifdef STDC_HEADERS
34 # include <stdlib.h>
35 # include <stddef.h>
36 #else
37 # ifdef HAVE_STDLIB_H
38 #  include <stdlib.h>
39 # endif
40 #endif /* STDC_HEADERS */
41 #ifdef HAVE_STRING_H
42 # include <string.h>
43 #else
44 # ifdef HAVE_STRINGS_H
45 #  include <strings.h>
46 # endif
47 #endif /* HAVE_STRING_H */
48 #ifdef HAVE_UNISTD_H
49 # include <unistd.h>
50 #endif /* HAVE_UNISTD_H */
51 #ifdef HAVE_ERR_H
52 # include <err.h>
53 #else
54 # include "emul/err.h"
55 #endif /* HAVE_ERR_H */
56 #include <pwd.h>
57 #include <signal.h>
58 #include <time.h>
59 #include <errno.h>
60 #include <fcntl.h>
61
62 #include "sudo.h"
63
64 #ifndef lint
65 __unused static const char rcsid[] = "$Sudo: logging.c,v 1.168.2.16 2008/06/22 20:23:57 millert Exp $";
66 #endif /* lint */
67
68 static void do_syslog           __P((int, char *));
69 static void do_logfile          __P((char *));
70 static void send_mail           __P((char *));
71 static void mail_auth           __P((int, char *));
72 static char *get_timestr        __P((void));
73 static void mysyslog            __P((int, const char *, ...));
74
75 #define MAXSYSLOGTRIES  16      /* num of retries for broken syslogs */
76
77 /*
78  * We do an openlog(3)/closelog(3) for each message because some
79  * authentication methods (notably PAM) use syslog(3) for their
80  * own nefarious purposes and may call openlog(3) and closelog(3).
81  * Note that because we don't want to assume that all systems have
82  * vsyslog(3) (HP-UX doesn't) "%m" will not be expanded.
83  * Sadly this is a maze of #ifdefs.
84  */
85 static void
86 #ifdef __STDC__
87 mysyslog(int pri, const char *fmt, ...)
88 #else
89 mysyslog(pri, fmt, va_alist)
90     int pri;
91     const char *fmt;
92     va_dcl
93 #endif
94 {
95 #ifdef BROKEN_SYSLOG
96     int i;
97 #endif
98     char buf[MAXSYSLOGLEN+1];
99     va_list ap;
100
101 #ifdef __STDC__
102     va_start(ap, fmt);
103 #else
104     va_start(ap);
105 #endif
106 #ifdef LOG_NFACILITIES
107     openlog("sudo", 0, def_syslog);
108 #else
109     openlog("sudo", 0);
110 #endif
111     vsnprintf(buf, sizeof(buf), fmt, ap);
112 #ifdef BROKEN_SYSLOG
113     /*
114      * Some versions of syslog(3) don't guarantee success and return
115      * an int (notably HP-UX < 10.0).  So, if at first we don't succeed,
116      * try, try again...
117      */
118     for (i = 0; i < MAXSYSLOGTRIES; i++)
119         if (syslog(pri, "%s", buf) == 0)
120             break;
121 #else
122     syslog(pri, "%s", buf);
123 #endif /* BROKEN_SYSLOG */
124     va_end(ap);
125     closelog();
126 }
127
128 /*
129  * Log a message to syslog, pre-pending the username and splitting the
130  * message into parts if it is longer than MAXSYSLOGLEN.
131  */
132 static void
133 do_syslog(pri, msg)
134     int pri;
135     char *msg;
136 {
137     size_t len, maxlen;
138     char *p, *tmp, save;
139     const char *fmt;
140     const char *fmt_first = "%8s : %s";
141     const char *fmt_contd = "%8s : (command continued) %s";
142
143     /*
144      * Log the full line, breaking into multiple syslog(3) calls if necessary
145      */
146     fmt = fmt_first;
147     maxlen = MAXSYSLOGLEN - (sizeof(fmt_first) - 6 + strlen(user_name));
148     for (p = msg; *p != '\0'; ) {
149         len = strlen(p);
150         if (len > maxlen) {
151             /*
152              * Break up the line into what will fit on one syslog(3) line
153              * Try to avoid breaking words into several lines if possible.
154              */
155             tmp = memrchr(p, ' ', maxlen);
156             if (tmp == NULL)
157                 tmp = p + maxlen;
158
159             /* NULL terminate line, but save the char to restore later */
160             save = *tmp;
161             *tmp = '\0';
162
163             mysyslog(pri, fmt, user_name, p);
164
165             *tmp = save;                        /* restore saved character */
166
167             /* Advance p and eliminate leading whitespace */
168             for (p = tmp; *p == ' '; p++)
169                 ;
170         } else {
171             mysyslog(pri, fmt, user_name, p);
172             p += len;
173         }
174         fmt = fmt_contd;
175         maxlen = MAXSYSLOGLEN - (sizeof(fmt_contd) - 6 + strlen(user_name));
176     }
177 }
178
179 static void
180 do_logfile(msg)
181     char *msg;
182 {
183     char *full_line;
184     char *beg, *oldend, *end;
185     FILE *fp;
186     mode_t oldmask;
187     size_t maxlen;
188
189     oldmask = umask(077);
190     maxlen = def_loglinelen > 0 ? def_loglinelen : 0;
191     fp = fopen(def_logfile, "a");
192     (void) umask(oldmask);
193     if (fp == NULL) {
194         easprintf(&full_line, "Can't open log file: %s: %s",
195             def_logfile, strerror(errno));
196         send_mail(full_line);
197         efree(full_line);
198     } else if (!lock_file(fileno(fp), SUDO_LOCK)) {
199         easprintf(&full_line, "Can't lock log file: %s: %s",
200             def_logfile, strerror(errno));
201         send_mail(full_line);
202         efree(full_line);
203     } else {
204         if (def_loglinelen == 0) {
205             /* Don't pretty-print long log file lines (hard to grep) */
206             if (def_log_host)
207                 (void) fprintf(fp, "%s : %s : HOST=%s : %s\n", get_timestr(),
208                     user_name, user_shost, msg);
209             else
210                 (void) fprintf(fp, "%s : %s : %s\n", get_timestr(),
211                     user_name, msg);
212         } else {
213             if (def_log_host)
214                 easprintf(&full_line, "%s : %s : HOST=%s : %s", get_timestr(),
215                     user_name, user_shost, msg);
216             else
217                 easprintf(&full_line, "%s : %s : %s", get_timestr(),
218                     user_name, msg);
219
220             /*
221              * Print out full_line with word wrap
222              */
223             beg = end = full_line;
224             while (beg) {
225                 oldend = end;
226                 end = strchr(oldend, ' ');
227
228                 if (maxlen > 0 && end) {
229                     *end = '\0';
230                     if (strlen(beg) > maxlen) {
231                         /* too far, need to back up & print the line */
232
233                         if (beg == (char *)full_line)
234                             maxlen -= 4;        /* don't indent first line */
235
236                         *end = ' ';
237                         if (oldend != beg) {
238                             /* rewind & print */
239                             end = oldend-1;
240                             while (*end == ' ')
241                                 --end;
242                             *(++end) = '\0';
243                             (void) fprintf(fp, "%s\n    ", beg);
244                             *end = ' ';
245                         } else {
246                             (void) fprintf(fp, "%s\n    ", beg);
247                         }
248
249                         /* reset beg to point to the start of the new substr */
250                         beg = end;
251                         while (*beg == ' ')
252                             ++beg;
253                     } else {
254                         /* we still have room */
255                         *end = ' ';
256                     }
257
258                     /* remove leading whitespace */
259                     while (*end == ' ')
260                         ++end;
261                 } else {
262                     /* final line */
263                     (void) fprintf(fp, "%s\n", beg);
264                     beg = NULL;                 /* exit condition */
265                 }
266             }
267             efree(full_line);
268         }
269         (void) fflush(fp);
270         (void) lock_file(fileno(fp), SUDO_UNLOCK);
271         (void) fclose(fp);
272     }
273 }
274
275 /*
276  * Two main functions, log_error() to log errors and log_auth() to
277  * log allow/deny messages.
278  */
279 void
280 log_auth(status, inform_user)
281     int status;
282     int inform_user;
283 {
284     char *evstr = NULL;
285     char *message;
286     char *logline;
287     int pri;
288
289     if (ISSET(status, VALIDATE_OK))
290         pri = def_syslog_goodpri;
291     else
292         pri = def_syslog_badpri;
293
294     /* Set error message, if any. */
295     if (ISSET(status, VALIDATE_OK))
296         message = "";
297     else if (ISSET(status, FLAG_NO_USER))
298         message = "user NOT in sudoers ; ";
299     else if (ISSET(status, FLAG_NO_HOST))
300         message = "user NOT authorized on host ; ";
301     else if (ISSET(status, VALIDATE_NOT_OK))
302         message = "command not allowed ; ";
303     else
304         message = "unknown error ; ";
305
306     if (sudo_user.env_vars != NULL) {
307         size_t len = 7; /* " ; ENV=" */
308         struct list_member *cur;
309         for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next)
310             len += strlen(cur->value) + 1;
311         evstr = emalloc(len);
312         strlcpy(evstr, " ; ENV=", len);
313         for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) {
314             strlcat(evstr, cur->value, len);
315             strlcat(evstr, " ", len);           /* NOTE: last one will fail */
316         }
317     }
318     easprintf(&logline, "%sTTY=%s ; PWD=%s ; USER=%s%s ; COMMAND=%s%s%s",
319         message, user_tty, user_cwd, *user_runas, evstr ? evstr : "",
320         user_cmnd, user_args ? " " : "", user_args ? user_args : "");
321
322     mail_auth(status, logline);         /* send mail based on status */
323
324     /* Inform the user if they failed to authenticate.  */
325     if (inform_user && ISSET(status, VALIDATE_NOT_OK)) {
326         if (ISSET(status, FLAG_NO_USER))
327             (void) fprintf(stderr, "%s is not in the sudoers file.  %s",
328                 user_name, "This incident will be reported.\n");
329         else if (ISSET(status, FLAG_NO_HOST))
330             (void) fprintf(stderr, "%s is not allowed to run sudo on %s.  %s",
331                 user_name, user_shost, "This incident will be reported.\n");
332         else if (ISSET(status, FLAG_NO_CHECK))
333             (void) fprintf(stderr, "Sorry, user %s may not run sudo on %s.\n",
334                 user_name, user_shost);
335         else
336             (void) fprintf(stderr,
337                 "Sorry, user %s is not allowed to execute '%s%s%s' as %s on %s.\n",
338                 user_name, user_cmnd, user_args ? " " : "",
339                 user_args ? user_args : "", *user_runas, user_host);
340     }
341
342     /*
343      * Log via syslog and/or a file.
344      */
345     if (def_syslog)
346         do_syslog(pri, logline);
347     if (def_logfile)
348         do_logfile(logline);
349
350     efree(evstr);
351     efree(logline);
352 }
353
354 void
355 #ifdef __STDC__
356 log_error(int flags, const char *fmt, ...)
357 #else
358 log_error(flags, fmt, va_alist)
359     int flags;
360     const char *fmt;
361     va_dcl
362 #endif
363 {
364     int serrno = errno;
365     char *message;
366     char *logline;
367     char *evstr = NULL;
368     va_list ap;
369 #ifdef __STDC__
370     va_start(ap, fmt);
371 #else
372     va_start(ap);
373 #endif
374
375     /* Become root if we are not already to avoid user interference */
376     set_perms(PERM_ROOT);
377
378     /* Expand printf-style format + args. */
379     evasprintf(&message, fmt, ap);
380     va_end(ap);
381
382     if (sudo_user.env_vars != NULL) {
383         size_t len = 7; /* " ; ENV=" */
384         struct list_member *cur;
385         for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next)
386             len += strlen(cur->value) + 1;
387         evstr = emalloc(len);
388         strlcpy(evstr, " ; ENV=", len);
389         for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) {
390             strlcat(evstr, cur->value, len);
391             strlcat(evstr, " ", len);           /* NOTE: last one will fail */
392         }
393     }
394
395     if (ISSET(flags, MSG_ONLY))
396         logline = message;
397     else if (ISSET(flags, USE_ERRNO)) {
398         if (user_args) {
399             easprintf(&logline,
400                 "%s: %s ; TTY=%s ; PWD=%s ; USER=%s%s ; COMMAND=%s %s",
401                 message, strerror(serrno), user_tty, user_cwd, *user_runas,
402                 evstr ? evstr : "", user_cmnd, user_args);
403         } else {
404             easprintf(&logline,
405                 "%s: %s ; TTY=%s ; PWD=%s ; USER=%s%s ; COMMAND=%s", message,
406                 strerror(serrno), user_tty, user_cwd, *user_runas,
407                 evstr ? evstr : "", user_cmnd);
408         }
409     } else {
410         if (user_args) {
411             easprintf(&logline,
412                 "%s ; TTY=%s ; PWD=%s ; USER=%s%s ; COMMAND=%s %s", message,
413                 user_tty, user_cwd, *user_runas, evstr ? evstr : "",
414                 user_cmnd, user_args);
415         } else {
416             easprintf(&logline,
417                 "%s ; TTY=%s ; PWD=%s ; USER=%s%s ; COMMAND=%s", message,
418                 user_tty, user_cwd, *user_runas, evstr ? evstr : "", user_cmnd);
419         }
420     }
421
422     /*
423      * Tell the user.
424      */
425     if (ISSET(flags, USE_ERRNO))
426         warn("%s", message);
427     else
428         warnx("%s", message);
429
430     /*
431      * Send a copy of the error via mail.
432      */
433     if (!ISSET(flags, NO_MAIL))
434         send_mail(logline);
435
436     /*
437      * Log to syslog and/or a file.
438      */
439     if (def_syslog)
440         do_syslog(def_syslog_badpri, logline);
441     if (def_logfile)
442         do_logfile(logline);
443
444     efree(message);
445     if (logline != message)
446         efree(logline);
447
448     if (!ISSET(flags, NO_EXIT))
449         exit(1);
450 }
451
452 #define MAX_MAILFLAGS   63
453
454 /*
455  * Send a message to MAILTO user
456  */
457 static void
458 send_mail(line)
459     char *line;
460 {
461     FILE *mail;
462     char *p;
463     int fd, pfd[2], status;
464     pid_t pid, rv;
465     sigaction_t sa;
466 #ifndef NO_ROOT_MAILER
467     static char *root_envp[] = {
468         "HOME=/",
469         "PATH=/usr/bin:/bin",
470         "LOGNAME=root",
471         "USERNAME=root",
472         "USER=root",
473         NULL
474     };
475 #endif
476
477     /* Just return if mailer is disabled. */
478     if (!def_mailerpath || !def_mailto)
479         return;
480
481     /* Fork and return, child will daemonize. */
482     switch (pid = fork()) {
483         case -1:
484             /* Error */
485             err(1, "cannot fork");
486             break;
487         case 0:
488             /* Child */
489             switch (pid = fork()) {
490                 case -1:
491                     /* Error. */
492                     mysyslog(LOG_ERR, "cannot fork: %m");
493                     _exit(1);
494                 case 0:
495                     /* Grandchild continues below. */
496                     break;
497                 default:
498                     /* Parent will wait for us. */
499                     _exit(0);
500             }
501             break;
502         default:
503             /* Parent */
504             do {
505 #ifdef HAVE_WAITPID
506                 rv = waitpid(pid, &status, 0);
507 #else
508                 rv = wait(&status);
509 #endif
510             } while (rv == -1 && errno == EINTR);
511             return;
512     }
513
514     /* Daemonize - disassociate from session/tty. */
515 #ifdef HAVE_SETSID
516     if (setsid() == -1)
517       warn("setsid");
518 #else
519     setpgrp(0, 0);
520 # ifdef TIOCNOTTY
521     if ((fd = open(_PATH_TTY, O_RDWR, 0644)) != -1) {
522         ioctl(fd, TIOCNOTTY, NULL);
523         close(fd);
524     }
525 # endif
526 #endif
527     chdir("/");
528     if ((fd = open(_PATH_DEVNULL, O_RDWR, 0644)) != -1) {
529         (void) dup2(fd, STDIN_FILENO);
530         (void) dup2(fd, STDOUT_FILENO);
531         (void) dup2(fd, STDERR_FILENO);
532     }
533
534     /* Close password and other fds so we don't leak. */
535     endpwent();
536     closefrom(STDERR_FILENO + 1);
537
538     /* Ignore SIGPIPE in case mailer exits prematurely (or is missing). */
539     sigemptyset(&sa.sa_mask);
540     sa.sa_flags = 0;
541     sa.sa_handler = SIG_IGN;
542     (void) sigaction(SIGPIPE, &sa, NULL);
543
544     if (pipe(pfd) == -1) {
545         mysyslog(LOG_ERR, "cannot open pipe: %m");
546         _exit(1);
547     }
548
549     switch (pid = fork()) {
550         case -1:
551             /* Error. */
552             mysyslog(LOG_ERR, "cannot fork: %m");
553             _exit(1);
554             break;
555         case 0:
556             {
557                 char *argv[MAX_MAILFLAGS + 1];
558                 char *mpath, *mflags;
559                 int i;
560
561                 /* Child, set stdin to output side of the pipe */
562                 if (pfd[0] != STDIN_FILENO) {
563                     (void) dup2(pfd[0], STDIN_FILENO);
564                     (void) close(pfd[0]);
565                 }
566                 (void) close(pfd[1]);
567
568                 /* Build up an argv based the mailer path and flags */
569                 mflags = estrdup(def_mailerflags);
570                 mpath = estrdup(def_mailerpath);
571                 if ((argv[0] = strrchr(mpath, ' ')))
572                     argv[0]++;
573                 else
574                     argv[0] = mpath;
575
576                 i = 1;
577                 if ((p = strtok(mflags, " \t"))) {
578                     do {
579                         argv[i] = p;
580                     } while (++i < MAX_MAILFLAGS && (p = strtok(NULL, " \t")));
581                 }
582                 argv[i] = NULL;
583
584                 /*
585                  * Depending on the config, either run the mailer as root
586                  * (so user cannot kill it) or as the user (for the paranoid).
587                  */
588 #ifndef NO_ROOT_MAILER
589                 set_perms(PERM_ROOT);
590                 execve(mpath, argv, root_envp);
591 #else
592                 set_perms(PERM_FULL_USER);
593                 execv(mpath, argv);
594 #endif /* NO_ROOT_MAILER */
595                 mysyslog(LOG_ERR, "cannot execute %s: %m", mpath);
596                 _exit(127);
597             }
598             break;
599     }
600
601     (void) close(pfd[0]);
602     mail = fdopen(pfd[1], "w");
603
604     /* Pipes are all setup, send message via sendmail. */
605     (void) fprintf(mail, "To: %s\nFrom: %s\nAuto-Submitted: %s\nSubject: ",
606         def_mailto, user_name, "auto-generated");
607     for (p = def_mailsub; *p; p++) {
608         /* Expand escapes in the subject */
609         if (*p == '%' && *(p+1) != '%') {
610             switch (*(++p)) {
611                 case 'h':
612                     (void) fputs(user_host, mail);
613                     break;
614                 case 'u':
615                     (void) fputs(user_name, mail);
616                     break;
617                 default:
618                     p--;
619                     break;
620             }
621         } else
622             (void) fputc(*p, mail);
623     }
624     (void) fprintf(mail, "\n\n%s : %s : %s : %s\n\n", user_host,
625         get_timestr(), user_name, line);
626     fclose(mail);
627     do {
628 #ifdef HAVE_WAITPID
629         rv = waitpid(pid, &status, 0);
630 #else
631         rv = wait(&status);
632 #endif
633     } while (rv == -1 && errno == EINTR);
634     _exit(0);
635 }
636
637 /*
638  * Send mail based on the value of "status" and compile-time options.
639  */
640 static void
641 mail_auth(status, line)
642     int status;
643     char *line;
644 {
645     int mail_mask;
646
647     /* If any of these bits are set in status, we send mail. */
648     if (def_mail_always)
649         mail_mask =
650             VALIDATE_ERROR|VALIDATE_OK|FLAG_NO_USER|FLAG_NO_HOST|VALIDATE_NOT_OK;
651     else {
652         mail_mask = VALIDATE_ERROR;
653         if (def_mail_no_user)
654             SET(mail_mask, FLAG_NO_USER);
655         if (def_mail_no_host)
656             SET(mail_mask, FLAG_NO_HOST);
657         if (def_mail_no_perms)
658             SET(mail_mask, VALIDATE_NOT_OK);
659     }
660
661     if ((status & mail_mask) != 0)
662         send_mail(line);
663 }
664
665 /*
666  * Return an ascii string with the current date + time
667  * Uses strftime() if available, else falls back to ctime().
668  */
669 static char *
670 get_timestr()
671 {
672     char *s;
673     time_t now = time((time_t) 0);
674 #ifdef HAVE_STRFTIME
675     static char buf[128];
676     struct tm *timeptr;
677
678     timeptr = localtime(&now);
679     if (def_log_year)
680         s = "%h %e %T %Y";
681     else
682         s = "%h %e %T";
683
684     /* strftime() does not guarantee to NUL-terminate so we must check. */
685     buf[sizeof(buf) - 1] = '\0';
686     if (strftime(buf, sizeof(buf), s, timeptr) && buf[sizeof(buf) - 1] == '\0')
687         return(buf);
688
689 #endif /* HAVE_STRFTIME */
690
691     s = ctime(&now) + 4;                /* skip day of the week */
692     if (def_log_year)
693         s[20] = '\0';                   /* avoid the newline */
694     else
695         s[15] = '\0';                   /* don't care about year */
696
697     return(s);
698 }