/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 | 367 | { |
50 | 367 | char *buf = NULL, *cp, *ep; |
51 | 367 | const char *errstr; |
52 | 367 | size_t bufsize = 0, cwdsize = 0, cmdsize = 0; |
53 | 367 | bool ret = false; |
54 | 367 | 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 | 367 | if (getdelim(&buf, &bufsize, '\n', fp) == -1 || |
63 | 367 | getdelim(&evlog->cwd, &cwdsize, '\n', fp) == -1 || |
64 | 367 | getdelim(&evlog->command, &cmdsize, '\n', fp) == -1) { |
65 | 41 | sudo_warn(U_("%s: invalid log file"), iolog_dir); |
66 | 41 | goto done; |
67 | 41 | } |
68 | | |
69 | | /* Strip the newline from the cwd and command. */ |
70 | 326 | evlog->cwd[strcspn(evlog->cwd, "\n")] = '\0'; |
71 | 326 | 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 | 326 | buf[strcspn(buf, "\n")] = '\0'; |
79 | 326 | cp = buf; |
80 | | |
81 | | /* timestamp */ |
82 | 326 | 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 | 307 | *ep = '\0'; |
87 | 307 | evlog->submit_time.tv_sec = sudo_strtonum(cp, 0, TIME_T_MAX, &errstr); |
88 | 307 | if (errstr != NULL) { |
89 | 94 | sudo_warn(U_("%s: time stamp %s: %s"), iolog_dir, cp, errstr); |
90 | 94 | goto done; |
91 | 94 | } |
92 | | |
93 | | /* submit user */ |
94 | 213 | cp = ep + 1; |
95 | 213 | if ((ep = strchr(cp, ':')) == NULL) { |
96 | 130 | sudo_warn(U_("%s: user field is missing"), iolog_dir); |
97 | 130 | goto done; |
98 | 130 | } |
99 | 83 | if ((evlog->submituser = strndup(cp, (size_t)(ep - cp))) == NULL) { |
100 | 0 | sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
101 | 0 | goto done; |
102 | 0 | } |
103 | | |
104 | | /* runas user */ |
105 | 83 | cp = ep + 1; |
106 | 83 | if ((ep = strchr(cp, ':')) == NULL) { |
107 | 1 | sudo_warn(U_("%s: runas user field is missing"), iolog_dir); |
108 | 1 | goto done; |
109 | 1 | } |
110 | 82 | if ((evlog->runuser = strndup(cp, (size_t)(ep - cp))) == NULL) { |
111 | 0 | sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
112 | 0 | goto done; |
113 | 0 | } |
114 | | |
115 | | /* runas group */ |
116 | 82 | cp = ep + 1; |
117 | 82 | if ((ep = strchr(cp, ':')) == NULL) { |
118 | 1 | sudo_warn(U_("%s: runas group field is missing"), iolog_dir); |
119 | 1 | goto done; |
120 | 1 | } |
121 | 81 | if (cp != ep) { |
122 | 1 | if ((evlog->rungroup = strndup(cp, (size_t)(ep - cp))) == NULL) { |
123 | 0 | sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
124 | 0 | goto done; |
125 | 0 | } |
126 | 1 | } |
127 | | |
128 | | /* tty, followed by optional lines + cols */ |
129 | 81 | cp = ep + 1; |
130 | 81 | if ((ep = strchr(cp, ':')) == NULL) { |
131 | | /* just the tty */ |
132 | 2 | if ((evlog->ttyname = strdup(cp)) == NULL) { |
133 | 0 | sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
134 | 0 | goto done; |
135 | 0 | } |
136 | 79 | } else { |
137 | | /* tty followed by lines + cols */ |
138 | 79 | if ((evlog->ttyname = strndup(cp, (size_t)(ep - cp))) == NULL) { |
139 | 0 | sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); |
140 | 0 | goto done; |
141 | 0 | } |
142 | 79 | cp = ep + 1; |
143 | | /* need to NULL out separator to use sudo_strtonum() */ |
144 | | /* XXX - use sudo_strtonumx */ |
145 | 79 | if ((ep = strchr(cp, ':')) != NULL) { |
146 | 12 | *ep = '\0'; |
147 | 12 | } |
148 | 79 | evlog->lines = sudo_strtonum(cp, 1, INT_MAX, &errstr); |
149 | 79 | if (errstr != NULL) { |
150 | 55 | sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, |
151 | 55 | "%s: tty lines %s: %s", iolog_dir, cp, errstr); |
152 | 55 | } |
153 | 79 | if (ep != NULL) { |
154 | 12 | cp = ep + 1; |
155 | 12 | evlog->columns = sudo_strtonum(cp, 1, INT_MAX, &errstr); |
156 | 12 | if (errstr != NULL) { |
157 | 8 | sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, |
158 | 8 | "%s: tty cols %s: %s", iolog_dir, cp, errstr); |
159 | 8 | } |
160 | 12 | } |
161 | 79 | } |
162 | | |
163 | 81 | ret = true; |
164 | | |
165 | 367 | done: |
166 | 367 | free(buf); |
167 | 367 | debug_return_bool(ret); |
168 | 367 | } |