/src/sudo/lib/iolog/iolog_legacy.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * SPDX-License-Identifier: ISC |
3 | | * |
4 | | * Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws> |
5 | | * |
6 | | * Permission to use, copy, modify, and distribute this software for any |
7 | | * purpose with or without fee is hereby granted, provided that the above |
8 | | * copyright notice and this permission notice appear in all copies. |
9 | | * |
10 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 | | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 | | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | | */ |
18 | | |
19 | | /* |
20 | | * This is an open source non-commercial project. Dear PVS-Studio, please check it. |
21 | | * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com |
22 | | */ |
23 | | |
24 | | #include <config.h> |
25 | | |
26 | | #include <stdio.h> |
27 | | #include <stdlib.h> |
28 | | #ifdef HAVE_STDBOOL_H |
29 | | # include <stdbool.h> |
30 | | #else |
31 | | # include <compat/stdbool.h> |
32 | | #endif /* HAVE_STDBOOL_H */ |
33 | | #include <string.h> |
34 | | #include <signal.h> |
35 | | #include <limits.h> |
36 | | #include <time.h> |
37 | | |
38 | | #include <sudo_compat.h> |
39 | | #include <sudo_debug.h> |
40 | | #include <sudo_eventlog.h> |
41 | | #include <sudo_fatal.h> |
42 | | #include <sudo_gettext.h> |
43 | | #include <sudo_iolog.h> |
44 | | #include <sudo_util.h> |
45 | | |
46 | | bool |
47 | | iolog_parse_loginfo_legacy(FILE *fp, const char *iolog_dir, |
48 | | struct eventlog *evlog) |
49 | 383 | { |
50 | 383 | char *buf = NULL, *cp, *ep; |
51 | 383 | const char *errstr; |
52 | 383 | size_t bufsize = 0, cwdsize = 0, cmdsize = 0; |
53 | 383 | bool ret = false; |
54 | 383 | debug_decl(iolog_parse_loginfo_legacy, SUDO_DEBUG_UTIL); |
55 | | |
56 | | /* |
57 | | * Info file has three lines: |
58 | | * 1) a log info line |
59 | | * 2) cwd |
60 | | * 3) command with args |
61 | | */ |
62 | 383 | if (getdelim(&buf, &bufsize, '\n', fp) == -1 || |
63 | 383 | getdelim(&evlog->cwd, &cwdsize, '\n', fp) == -1 || |
64 | 383 | getdelim(&evlog->command, &cmdsize, '\n', fp) == -1) { |
65 | 42 | sudo_warn(U_("%s: invalid log file"), iolog_dir); |
66 | 42 | goto done; |
67 | 42 | } |
68 | | |
69 | | /* Strip the newline from the cwd and command. */ |
70 | 341 | evlog->cwd[strcspn(evlog->cwd, "\n")] = '\0'; |
71 | 341 | evlog->command[strcspn(evlog->command, "\n")] = '\0'; |
72 | | |
73 | | /* |
74 | | * Crack the log line (lines and cols not present in old versions). |
75 | | * timestamp:user:runas_user:runas_group:tty:lines:cols |
76 | | * XXX - probably better to use strtok and switch on the state. |
77 | | */ |
78 | 341 | buf[strcspn(buf, "\n")] = '\0'; |
79 | 341 | cp = buf; |
80 | | |
81 | | /* timestamp */ |
82 | 341 | if ((ep = strchr(cp, ':')) == NULL) { |
83 | 19 | sudo_warn(U_("%s: time stamp field is missing"), iolog_dir); |
84 | 19 | goto done; |
85 | 19 | } |
86 | 322 | *ep = '\0'; |
87 | 322 | evlog->event_time.tv_sec = |
88 | 322 | (time_t)sudo_strtonum(cp, 0, TIME_T_MAX, &errstr); |
89 | 322 | if (errstr != NULL) { |
90 | 108 | sudo_warn(U_("%s: time stamp %s: %s"), iolog_dir, cp, errstr); |
91 | 108 | goto done; |
92 | 108 | } |
93 | | |
94 | | /* submit user */ |
95 | 214 | cp = ep + 1; |
96 | 214 | if ((ep = strchr(cp, ':')) == NULL) { |
97 | 129 | sudo_warn(U_("%s: user field is missing"), iolog_dir); |
98 | 129 | goto done; |
99 | 129 | } |
100 | 85 | if ((evlog->submituser = strndup(cp, (size_t)(ep - cp))) == NULL) { |
101 | 0 | sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
102 | 0 | goto done; |
103 | 0 | } |
104 | | |
105 | | /* runas user */ |
106 | 85 | cp = ep + 1; |
107 | 85 | if ((ep = strchr(cp, ':')) == NULL) { |
108 | 1 | sudo_warn(U_("%s: runas user field is missing"), iolog_dir); |
109 | 1 | goto done; |
110 | 1 | } |
111 | 84 | if ((evlog->runuser = strndup(cp, (size_t)(ep - cp))) == NULL) { |
112 | 0 | sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
113 | 0 | goto done; |
114 | 0 | } |
115 | | |
116 | | /* runas group */ |
117 | 84 | cp = ep + 1; |
118 | 84 | if ((ep = strchr(cp, ':')) == NULL) { |
119 | 1 | sudo_warn(U_("%s: runas group field is missing"), iolog_dir); |
120 | 1 | goto done; |
121 | 1 | } |
122 | 83 | if (cp != ep) { |
123 | 1 | if ((evlog->rungroup = strndup(cp, (size_t)(ep - cp))) == NULL) { |
124 | 0 | sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
125 | 0 | goto done; |
126 | 0 | } |
127 | 1 | } |
128 | | |
129 | | /* tty, followed by optional lines + cols */ |
130 | 83 | cp = ep + 1; |
131 | 83 | if ((ep = strchr(cp, ':')) == NULL) { |
132 | | /* just the tty */ |
133 | 2 | if ((evlog->ttyname = strdup(cp)) == NULL) { |
134 | 0 | sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
135 | 0 | goto done; |
136 | 0 | } |
137 | 81 | } else { |
138 | | /* tty followed by lines + cols */ |
139 | 81 | if ((evlog->ttyname = strndup(cp, (size_t)(ep - cp))) == NULL) { |
140 | 0 | sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
141 | 0 | goto done; |
142 | 0 | } |
143 | 81 | cp = ep + 1; |
144 | | /* need to NULL out separator to use sudo_strtonum() */ |
145 | | /* XXX - use sudo_strtonumx */ |
146 | 81 | if ((ep = strchr(cp, ':')) != NULL) { |
147 | 13 | *ep = '\0'; |
148 | 13 | } |
149 | 81 | evlog->lines = (int)sudo_strtonum(cp, 1, INT_MAX, &errstr); |
150 | 81 | if (errstr != NULL) { |
151 | 57 | sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, |
152 | 57 | "%s: tty lines %s: %s", iolog_dir, cp, errstr); |
153 | 57 | } |
154 | 81 | if (ep != NULL) { |
155 | 13 | cp = ep + 1; |
156 | 13 | evlog->columns = (int)sudo_strtonum(cp, 1, INT_MAX, &errstr); |
157 | 13 | if (errstr != NULL) { |
158 | 9 | sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, |
159 | 9 | "%s: tty cols %s: %s", iolog_dir, cp, errstr); |
160 | 9 | } |
161 | 13 | } |
162 | 81 | } |
163 | | |
164 | 83 | ret = true; |
165 | | |
166 | 383 | done: |
167 | 383 | free(buf); |
168 | 383 | debug_return_bool(ret); |
169 | 383 | } |