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