diff options
Diffstat (limited to 'logintest.c')
-rw-r--r-- | logintest.c | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/logintest.c b/logintest.c new file mode 100644 index 000000000..d26f9ef9e --- /dev/null +++ b/logintest.c | |||
@@ -0,0 +1,307 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000 Andre Lucas. All rights reserved. | ||
3 | * | ||
4 | * Redistribution and use in source and binary forms, with or without | ||
5 | * modification, are permitted provided that the following conditions | ||
6 | * are met: | ||
7 | * 1. Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * 2. Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * 3. All advertising materials mentioning features or use of this software | ||
13 | * must display the following acknowledgement: | ||
14 | * This product includes software developed by Markus Friedl. | ||
15 | * 4. The name of the author may not be used to endorse or promote products | ||
16 | * derived from this software without specific prior written permission. | ||
17 | * | ||
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
20 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
21 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
22 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
23 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | /** | ||
31 | ** logintest.c: simple test driver for platform-independent login recording | ||
32 | ** and lastlog retrieval | ||
33 | **/ | ||
34 | |||
35 | #include "config.h" | ||
36 | |||
37 | #include <sys/types.h> | ||
38 | #include <sys/wait.h> | ||
39 | #include <unistd.h> | ||
40 | #include <stdlib.h> | ||
41 | #include <stdio.h> | ||
42 | #include <string.h> | ||
43 | #include <pwd.h> | ||
44 | #include <netdb.h> | ||
45 | #ifdef HAVE_TIME_H | ||
46 | #include <time.h> | ||
47 | #endif | ||
48 | |||
49 | #include "loginrec.h" | ||
50 | |||
51 | RCSID("$Id: logintest.c,v 1.1 2000/06/03 14:57:40 andre Exp $"); | ||
52 | |||
53 | |||
54 | int nologtest = 0; | ||
55 | int compile_opts_only = 0; | ||
56 | int be_verbose = 0; | ||
57 | |||
58 | |||
59 | #define DOTQUAD_MAXSIZE 17 | ||
60 | void dump_dotquad(char *s, struct in_addr *sin4) { | ||
61 | unsigned int addr; | ||
62 | |||
63 | addr = ntohl(sin4->s_addr); | ||
64 | snprintf(s, DOTQUAD_MAXSIZE, "%d.%d.%d.%d", | ||
65 | (addr >> 24)& 0xff, (addr >>16) & 0xff, | ||
66 | (addr >>8) & 0xff, addr & 0xff ); | ||
67 | } /* dump_dotquad */ | ||
68 | |||
69 | |||
70 | /* Dump a logininfo to stdout. Assumes a tab size of 8 chars. */ | ||
71 | void dump_logininfo(struct logininfo *li, char *descname) { | ||
72 | char a4[DOTQUAD_MAXSIZE]; | ||
73 | |||
74 | dump_dotquad(a4, &(li->hostaddr.sa_in4.sin_addr)); | ||
75 | |||
76 | /* yes I know how nasty this is */ | ||
77 | printf("struct logininfo %s = {\n\t" | ||
78 | "progname\t'%s'\n\ttype\t\t%d\n\t" | ||
79 | "pid\t\t%d\n\tuid\t\t%d\n\t" | ||
80 | "line\t\t'%s'\n\tusername\t'%s'\n\t" | ||
81 | "hostname\t'%s'\n\texit\t\t%d\n\ttermination\t%d\n\t" | ||
82 | "tv_sec\t%d\n\ttv_usec\t%d\n\t" | ||
83 | "struct login_netinfo hostaddr {\n\t\t" | ||
84 | "struct sockaddr_in sa_in4 {\n" | ||
85 | "\t\t\tsin_port\t%d\n\t\t\t*sin_addr\t%d(%s)\n\t\t}\n" | ||
86 | "\t\t** !!! IP6 stuff not supported yet **\n" | ||
87 | "\t}\n" | ||
88 | "}\n", | ||
89 | descname, li->progname, li->type, | ||
90 | li->pid, li->uid, li->line, | ||
91 | li->username, li->hostname, li->exit, | ||
92 | li->termination, li->tv_sec, li->tv_usec, | ||
93 | ntohs(li->hostaddr.sa_in4.sin_port), | ||
94 | ntohl(li->hostaddr.sa_in4.sin_addr.s_addr), a4); | ||
95 | /* FIXME: (ATL) print sockaddr_in6 stuff */ | ||
96 | } | ||
97 | |||
98 | |||
99 | int testAPI() { | ||
100 | struct logininfo *li1; | ||
101 | struct passwd *pw; | ||
102 | struct hostent *he; | ||
103 | struct sockaddr_in sa_in4; | ||
104 | char cmdstring[256], stripline[8]; | ||
105 | char username[32]; | ||
106 | #ifdef HAVE_TIME_H | ||
107 | time_t t0, t1, t2; | ||
108 | char s_t0[64],s_t1[64],s_t2[64]; /* ctime() strings */ | ||
109 | #endif | ||
110 | |||
111 | printf("**\n** Testing the API...\n**\n"); | ||
112 | |||
113 | pw = getpwuid(getuid()); | ||
114 | strlcpy(username, pw->pw_name, sizeof(username)); | ||
115 | |||
116 | /* gethostname(hostname, sizeof(hostname)); */ | ||
117 | |||
118 | printf("login_alloc_entry test (no host info):\n"); | ||
119 | /* !!! fake tty more effectively */ | ||
120 | li1 = login_alloc_entry((int)getpid(), username, NULL, ttyname(0)); | ||
121 | login_set_progname(li1, "testlogin"); | ||
122 | |||
123 | if (be_verbose) | ||
124 | dump_logininfo(li1, "li1"); | ||
125 | |||
126 | printf("Setting IPv4 host info for 'localhost' (may call out):\n"); | ||
127 | if (! (he = gethostbyname("localhost"))) { | ||
128 | printf("Couldn't set hostname(lookup failed)\n"); | ||
129 | } else { | ||
130 | /* NOTE: this is messy, but typically a program wouldn't have to set | ||
131 | * any of this, a sockaddr_in* would be already prepared */ | ||
132 | memcpy((void *)&(sa_in4.sin_addr), (void *)&(he->h_addr_list[0][0]), | ||
133 | sizeof(struct in_addr)); | ||
134 | login_set_ip4(li1, &sa_in4); | ||
135 | login_set_hostname(li1, "localhost"); | ||
136 | } | ||
137 | if (be_verbose) | ||
138 | dump_logininfo(li1, "li1"); | ||
139 | |||
140 | if ((int)geteuid() != 0) { | ||
141 | printf("NOT RUNNING LOGIN TESTS - you are not root!\n"); | ||
142 | return 1; /* this isn't necessarily an error */ | ||
143 | } | ||
144 | |||
145 | if (nologtest) | ||
146 | return 1; | ||
147 | |||
148 | line_stripname(stripline, li1->line, sizeof(stripline)); | ||
149 | |||
150 | printf("Performing an invalid login attempt (no type field)\n--\n"); | ||
151 | login_write(li1); | ||
152 | printf("--\n(Should have written an error to stderr)\n"); | ||
153 | |||
154 | #ifdef HAVE_TIME_H | ||
155 | (void)time(&t0); | ||
156 | strlcpy(s_t0, ctime(&t0), sizeof(s_t0)); | ||
157 | t1 = login_getlasttime_uid(getuid()); | ||
158 | strlcpy(s_t1, ctime(&t1), sizeof(s_t1)); | ||
159 | printf("Before logging in:\n\tcurrent time is %d - %s\t" | ||
160 | "lastlog time is %d - %s\n", | ||
161 | (int)t0, s_t0, (int)t1, s_t1); | ||
162 | #endif | ||
163 | |||
164 | printf("Performing a login on line %s...\n--\n", stripline); | ||
165 | login_login(li1); | ||
166 | |||
167 | snprintf(cmdstring, sizeof(cmdstring), "who | grep '%s '", | ||
168 | stripline); | ||
169 | system(cmdstring); | ||
170 | |||
171 | printf("--\nWaiting for a few seconds...\n"); | ||
172 | sleep(2); | ||
173 | |||
174 | printf("Performing a logout (the root login " | ||
175 | "shown above should be gone)\n" | ||
176 | "If the root login hasn't gone, but another user on the same\n" | ||
177 | "pty has, this is OK - we're hacking it here, and there\n" | ||
178 | "shouldn't be two users on one pty in reality...\n" | ||
179 | "-- ('who' output follows)\n"); | ||
180 | login_logout(li1); | ||
181 | |||
182 | system(cmdstring); | ||
183 | printf("-- ('who' output ends)\n"); | ||
184 | |||
185 | #ifdef HAVE_TIME_H | ||
186 | t2 = login_getlasttime_uid(getuid()); | ||
187 | strlcpy(s_t2, ctime(&t2), sizeof(s_t2)); | ||
188 | printf("After logging in, lastlog time is %d - %s\n", (int)t2, s_t2); | ||
189 | if (t1 == t2) | ||
190 | printf("The lastlog times before and after logging in are the " | ||
191 | "same.\nThis indicates that lastlog is ** NOT WORKING " | ||
192 | "CORRECTLY **\n"); | ||
193 | else if (t0 != t2) | ||
194 | printf("** The login time and the lastlog time differ.\n" | ||
195 | "** This indicates that lastlog is either recording the " | ||
196 | "wrong time,\n** or retrieving the wrong entry.\n"); | ||
197 | else | ||
198 | printf("lastlog agrees with the login time. This is a good thing.\n"); | ||
199 | |||
200 | #endif | ||
201 | |||
202 | printf("--\nThe output of 'last' shown next should have " | ||
203 | "an entry for root \n on %s for the time shown above:\n--\n", | ||
204 | stripline); | ||
205 | snprintf(cmdstring, sizeof(cmdstring), "last | grep '%s ' | head -3", | ||
206 | stripline); | ||
207 | system(cmdstring); | ||
208 | |||
209 | printf("--\nEnd of login test.\n"); | ||
210 | |||
211 | login_free_entry(li1); | ||
212 | |||
213 | return 1; | ||
214 | } /* testAPI() */ | ||
215 | |||
216 | |||
217 | void testLineName(char *line) { | ||
218 | /* have to null-terminate - these functions are designed for | ||
219 | * structures with fixed-length char arrays, and don't null-term.*/ | ||
220 | char full[17], strip[9], abbrev[5]; | ||
221 | |||
222 | memset(full, '\0', sizeof(full)); | ||
223 | memset(strip, '\0', sizeof(strip)); | ||
224 | memset(abbrev, '\0', sizeof(abbrev)); | ||
225 | |||
226 | line_fullname(full, line, sizeof(full)-1); | ||
227 | line_stripname(strip, full, sizeof(strip)-1); | ||
228 | line_abbrevname(abbrev, full, sizeof(abbrev)-1); | ||
229 | printf("%s: %s, %s, %s\n", line, full, strip, abbrev); | ||
230 | |||
231 | } /* testLineName() */ | ||
232 | |||
233 | |||
234 | int testOutput() { | ||
235 | printf("**\n** Testing linename functions\n**\n"); | ||
236 | testLineName("/dev/pts/1"); | ||
237 | testLineName("pts/1"); | ||
238 | testLineName("pts/999"); | ||
239 | testLineName("/dev/ttyp00"); | ||
240 | testLineName("ttyp00"); | ||
241 | |||
242 | return 1; | ||
243 | } /* testOutput() */ | ||
244 | |||
245 | |||
246 | /* show which options got compiled in */ | ||
247 | void showOptions(void) { | ||
248 | |||
249 | printf("**\n** Compile-time options\n**\n"); | ||
250 | |||
251 | printf("login recording methods selected:\n"); | ||
252 | #ifdef USE_LOGIN | ||
253 | printf("\tUSE_LOGIN\n"); | ||
254 | #endif | ||
255 | #ifdef USE_UTMP | ||
256 | printf("\tUSE_UTMP (UTMP_FILE=%s)\n", UTMP_FILE); | ||
257 | #endif | ||
258 | #ifdef USE_UTMPX | ||
259 | printf("\tUSE_UTMPX (UTMPX_FILE=%s)\n", UTMPX_FILE); | ||
260 | #endif | ||
261 | #ifdef USE_WTMP | ||
262 | printf("\tUSE_WTMP (WTMP_FILE=%s)\n", WTMP_FILE); | ||
263 | #endif | ||
264 | #ifdef USE_WTMPX | ||
265 | printf("\tUSE_WTMPX (WTMPX_FILE=%s)\n", WTMPX_FILE); | ||
266 | #endif | ||
267 | #ifdef USE_LASTLOG | ||
268 | printf("\tUSE_LASTLOG (LASTLOG_FILE=%s)\n", LASTLOG_FILE); | ||
269 | #endif | ||
270 | printf("\n"); | ||
271 | |||
272 | printf("IP6 support: %s\n", | ||
273 | #ifdef HAVE_IP6 | ||
274 | "enabled" | ||
275 | #else | ||
276 | "disabled" | ||
277 | #endif | ||
278 | ); | ||
279 | |||
280 | |||
281 | } /* showOptions() */ | ||
282 | |||
283 | |||
284 | int main(int argc, char *argv[]) { | ||
285 | |||
286 | printf("Platform-independent login recording test driver"); | ||
287 | |||
288 | if (argc == 2) { | ||
289 | if (strncmp(argv[1], "-i", 3) == 0) | ||
290 | compile_opts_only = 1; | ||
291 | else if (strncmp(argv[1], "-v", 3) == 0) | ||
292 | be_verbose=1; | ||
293 | } | ||
294 | |||
295 | if (!compile_opts_only) { | ||
296 | if (be_verbose && !testOutput()) | ||
297 | return 1; | ||
298 | |||
299 | if (!testAPI()) | ||
300 | return 1; | ||
301 | } | ||
302 | |||
303 | showOptions(); | ||
304 | |||
305 | return 0; | ||
306 | } /* main() */ | ||
307 | |||