Imported Upstream version 1.8.6p8
[debian/sudo] / plugins / sudoers / regress / iolog_path / check_iolog_path.c
1 /*
2  * Copyright (c) 2011 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
17 #include <config.h>
18
19 #include <sys/types.h>
20 #include <stdio.h>
21 #ifdef STDC_HEADERS
22 # include <stdlib.h>
23 # include <stddef.h>
24 #else
25 # ifdef HAVE_STDLIB_H
26 #  include <stdlib.h>
27 # endif
28 #endif /* STDC_HEADERS */
29 #ifdef HAVE_STRING_H
30 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
31 #  include <memory.h>
32 # endif
33 # include <string.h>
34 #endif /* HAVE_STRING_H */
35 #ifdef HAVE_STRINGS_H
36 # include <strings.h>
37 #endif /* HAVE_STRINGS_H */
38 #ifdef HAVE_SETLOCALE
39 # include <locale.h>
40 #endif
41 #include <pwd.h>
42 #include <grp.h>
43 #include <time.h>
44
45 #define SUDO_ERROR_WRAP 0
46
47 #define _SUDO_MAIN
48 #include "sudoers.h"
49 #include "def_data.c"
50
51 struct sudo_user sudo_user;
52 struct passwd *list_pw;
53 sudo_conv_t sudo_conv;          /* NULL in non-plugin */
54
55 static char sessid[7];
56
57 static void
58 usage(void)
59 {
60     fprintf(stderr, "usage: check_iolog_path datafile\n");
61     exit(1);
62 }
63
64 static int
65 do_check(char *dir_in, char *file_in, char *tdir_out, char *tfile_out)
66 {
67     char *path, *slash;
68     char dir_out[4096], file_out[4096];
69     struct tm *timeptr;
70     time_t now;
71     int error = 0;
72
73     /*
74      * Expand any strftime(3) escapes
75      * XXX - want to pass timeptr to expand_iolog_path
76      */
77     time(&now);
78     timeptr = localtime(&now);
79     strftime(dir_out, sizeof(dir_out), tdir_out, timeptr);
80     strftime(file_out, sizeof(file_out), tfile_out, timeptr);
81
82     path = expand_iolog_path(NULL, dir_in, file_in, &slash);
83     *slash = '\0';
84     if (strcmp(path, dir_out) != 0) {
85         warningx("%s: expected %s, got %s", dir_in, dir_out, path);
86         error = 1;
87     }
88     if (strcmp(slash + 1, file_out) != 0) {
89         warningx("%s: expected %s, got %s", file_in, file_out, slash + 1);
90         error = 1;
91     }
92
93     return error;
94 }
95
96 #define MAX_STATE       12
97
98 int
99 main(int argc, char *argv[])
100 {
101     struct passwd pw, rpw;
102     size_t len;
103     FILE *fp;
104     char line[2048];
105     char *file_in = NULL, *file_out = NULL;
106     char *dir_in = NULL, *dir_out = NULL;
107     int state = 0;
108     int errors = 0;
109     int tests = 0;
110
111 #if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME)
112     setprogname(argc > 0 ? argv[0] : "check_iolog_path");
113 #endif
114
115     if (argc != 2)
116         usage();
117
118     fp = fopen(argv[1], "r");
119     if (fp == NULL)
120         errorx(1, "unable to open %s", argv[1]);
121
122     memset(&pw, 0, sizeof(pw));
123     memset(&rpw, 0, sizeof(rpw));
124     sudo_user.pw = &pw;
125     sudo_user._runas_pw = &rpw;
126
127     /*
128      * Input consists of 12 lines:
129      * sequence number
130      * user name
131      * user gid
132      * runas user name
133      * runas gid
134      * hostname [short form]
135      * command
136      * dir [with escapes]
137      * file [with escapes]
138      * expanded dir
139      * expanded file
140      * empty line
141      */
142     while (fgets(line, sizeof(line), fp) != NULL) {
143         len = strcspn(line, "\n");
144         line[len] = '\0';
145
146         switch (state) {
147         case 0:
148             strlcpy(sessid, line, sizeof(sessid));
149             break;
150         case 1:
151             if (user_name != NULL)
152                 free(user_name);
153             user_name = strdup(line);
154             break;
155         case 2:
156             user_gid = atoi(line);
157             break;
158         case 3:
159             if (runas_pw->pw_name != NULL)
160                 free(runas_pw->pw_name);
161             runas_pw->pw_name = strdup(line);
162             break;
163         case 4:
164             runas_pw->pw_gid = atoi(line);
165             break;
166         case 5:
167             user_shost = strdup(line);
168             break;
169         case 6:
170             user_base = strdup(line);
171             break;
172         case 7:
173             dir_in = strdup(line);
174             break;
175         case 8:
176             file_in = strdup(line);
177             break;
178         case 9:
179             dir_out = strdup(line);
180             break;
181         case 10:
182             file_out = strdup(line);
183             break;
184         case 11:
185             errors += do_check(dir_in, file_in, dir_out, file_out);
186             tests++;
187             break;
188         default:
189             errorx(1, "internal error, invalid state %d", state);
190         }
191         state = (state + 1) % MAX_STATE;
192     }
193
194     if (tests != 0) {
195         printf("iolog_path: %d test%s run, %d errors, %d%% success rate\n",
196             tests, tests == 1 ? "" : "s", errors,
197             (tests - errors) * 100 / tests);
198     }
199
200     exit(errors);
201 }
202
203 void io_nextid(char *iolog_dir, char *fallback, char id[7])
204 {
205     memcpy(id, sessid, sizeof(sessid));
206 }
207
208 void
209 cleanup(int gotsig)
210 {
211     return;
212 }