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