1 /* $NetBSD: common.c,v 1.8 2015/10/28 07:27:24 shm Exp $ */ 2 3 /*- 4 * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: common.c,v 1.8 2015/10/28 07:27:24 shm Exp $"); 33 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/socket.h> 37 #include <stdio.h> 38 #include <string.h> 39 #include <unistd.h> 40 #include <stdlib.h> 41 #include <syslog.h> 42 #include <fcntl.h> 43 #include <ttyent.h> 44 #include <setjmp.h> 45 #include <time.h> 46 #include <pwd.h> 47 #include <err.h> 48 #include <vis.h> 49 #include <util.h> 50 51 #include "pathnames.h" 52 #include "common.h" 53 54 #if defined(KERBEROS5) 55 #define NBUFSIZ (MAXLOGNAME + 1 + 5) /* .root suffix */ 56 #else 57 #define NBUFSIZ (MAXLOGNAME + 1) 58 #endif 59 60 #ifdef SUPPORT_UTMP 61 #include <utmp.h> 62 static void doutmp(void); 63 static void dolastlog(int); 64 #endif 65 #ifdef SUPPORT_UTMPX 66 #include <utmpx.h> 67 static void doutmpx(void); 68 static void dolastlogx(int); 69 #endif 70 71 /* 72 * This bounds the time given to login. Not a define so it can 73 * be patched on machines where it's too small. 74 */ 75 u_int timeout = 300; 76 77 void decode_ss(const char *); 78 struct passwd *pwd; 79 int failures, have_ss; 80 char term[64], *envinit[1], *hostname, *tty, *nested; 81 const char *username; 82 struct timeval now; 83 struct sockaddr_storage ss; 84 85 char * 86 trimloginname(char *u) 87 { 88 if (strlen(u) > MAXLOGNAME) 89 u[MAXLOGNAME] = '\0'; 90 return u; 91 } 92 93 char * 94 getloginname(void) 95 { 96 int ch; 97 char *p; 98 static char nbuf[NBUFSIZ]; 99 100 for (;;) { 101 (void)printf("login: "); 102 for (p = nbuf; (ch = getchar()) != '\n'; ) { 103 if (ch == EOF) { 104 badlogin(username); 105 exit(EXIT_FAILURE); 106 } 107 if (p < nbuf + (NBUFSIZ - 1)) 108 *p++ = ch; 109 } 110 if (p > nbuf) { 111 if (nbuf[0] == '-') 112 (void)fprintf(stderr, 113 "login names may not start with '-'.\n"); 114 else { 115 *p = '\0'; 116 return nbuf; 117 } 118 } 119 } 120 } 121 122 int 123 rootterm(char *ttyn) 124 { 125 struct ttyent *t; 126 127 return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); 128 } 129 130 static jmp_buf motdinterrupt; 131 132 void 133 motd(const char *fname) 134 { 135 int fd, nchars; 136 sig_t oldint; 137 char tbuf[8192]; 138 139 if ((fd = open(fname ? fname : _PATH_MOTDFILE, O_RDONLY, 0)) < 0) 140 return; 141 oldint = signal(SIGINT, sigint); 142 if (setjmp(motdinterrupt) == 0) 143 while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 144 (void)write(fileno(stdout), tbuf, nchars); 145 (void)signal(SIGINT, oldint); 146 (void)close(fd); 147 } 148 149 /* ARGSUSED */ 150 void __dead 151 sigint(int signo) 152 { 153 154 longjmp(motdinterrupt, 1); 155 } 156 157 /* ARGSUSED */ 158 void __dead 159 timedout(int signo) 160 { 161 162 (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); 163 exit(EXIT_FAILURE); 164 } 165 166 void 167 update_db(int quietlog, int rootlogin, int fflag) 168 { 169 struct sockaddr_storage ass; 170 char assbuf[1024]; 171 socklen_t alen; 172 const char *hname; 173 int remote; 174 175 hname = (hostname == NULL) ? "?" : hostname; 176 alen = sizeof(ass); 177 if (getpeername(STDIN_FILENO, (struct sockaddr *)&ass, &alen) != -1) { 178 (void)sockaddr_snprintf(assbuf, 179 sizeof(assbuf), "%A (%a)", (void *)&ass); 180 if (have_ss) { 181 char ssbuf[1024]; 182 (void)sockaddr_snprintf(ssbuf, 183 sizeof(ssbuf), "%A(%a)", (void *)&ss); 184 if (memcmp(&ass, &ss, alen) != 0) 185 syslog(LOG_NOTICE, 186 "login %s on tty %s address mismatch " 187 "passed %s != actual %s", username, tty, 188 ssbuf, assbuf); 189 } else 190 ss = ass; 191 remote = 1; 192 } else if (have_ss) { 193 (void)sockaddr_snprintf(assbuf, 194 sizeof(assbuf), "%A(%a)", (void *)&ss); 195 remote = 1; 196 } else if (hostname) { 197 (void)snprintf(assbuf, sizeof(assbuf), "? ?"); 198 remote = 1; 199 } else 200 remote = 0; 201 202 /* If fflag is on, assume caller/authenticator has logged root login. */ 203 if (rootlogin && fflag == 0) { 204 if (remote) 205 syslog(LOG_NOTICE, "ROOT LOGIN (%s) on tty %s from %s /" 206 " %s", username, tty, hname, assbuf); 207 else 208 syslog(LOG_NOTICE, "ROOT LOGIN (%s) on tty %s", 209 username, tty); 210 } else if (nested != NULL) { 211 if (remote) 212 syslog(LOG_NOTICE, "%s to %s on tty %s from %s / " 213 "%s", nested, pwd->pw_name, tty, hname, assbuf); 214 else 215 syslog(LOG_NOTICE, "%s to %s on tty %s", nested, 216 pwd->pw_name, tty); 217 } else { 218 if (remote) 219 syslog(LOG_NOTICE, "%s on tty %s from %s / %s", 220 pwd->pw_name, tty, hname, assbuf); 221 else 222 syslog(LOG_NOTICE, "%s on tty %s", 223 pwd->pw_name, tty); 224 } 225 (void)gettimeofday(&now, NULL); 226 #ifdef SUPPORT_UTMPX 227 doutmpx(); 228 dolastlogx(quietlog); 229 quietlog = 1; 230 #endif 231 #ifdef SUPPORT_UTMP 232 doutmp(); 233 dolastlog(quietlog); 234 #endif 235 } 236 237 #ifdef SUPPORT_UTMPX 238 static void 239 doutmpx(void) 240 { 241 struct utmpx utmpx; 242 char *t; 243 244 memset((void *)&utmpx, 0, sizeof(utmpx)); 245 utmpx.ut_tv = now; 246 (void)strncpy(utmpx.ut_name, username, sizeof(utmpx.ut_name)); 247 if (hostname) { 248 (void)strncpy(utmpx.ut_host, hostname, sizeof(utmpx.ut_host)); 249 utmpx.ut_ss = ss; 250 } 251 (void)strncpy(utmpx.ut_line, tty, sizeof(utmpx.ut_line)); 252 utmpx.ut_type = USER_PROCESS; 253 utmpx.ut_pid = getpid(); 254 t = tty + strlen(tty); 255 if ((size_t)(t - tty) >= sizeof(utmpx.ut_id)) { 256 (void)strncpy(utmpx.ut_id, t - sizeof(utmpx.ut_id), 257 sizeof(utmpx.ut_id)); 258 } else { 259 (void)strncpy(utmpx.ut_id, tty, sizeof(utmpx.ut_id)); 260 } 261 if (pututxline(&utmpx) == NULL) 262 syslog(LOG_NOTICE, "Cannot update utmpx: %m"); 263 endutxent(); 264 if (updwtmpx(_PATH_WTMPX, &utmpx) != 0) 265 syslog(LOG_NOTICE, "Cannot update wtmpx: %m"); 266 } 267 268 static void 269 dolastlogx(int quiet) 270 { 271 struct lastlogx ll; 272 if (!quiet && getlastlogx(_PATH_LASTLOGX, pwd->pw_uid, &ll) != NULL) { 273 time_t t = (time_t)ll.ll_tv.tv_sec; 274 (void)printf("Last login: %.24s ", ctime(&t)); 275 if (*ll.ll_host != '\0') 276 (void)printf("from %.*s ", 277 (int)sizeof(ll.ll_host), 278 ll.ll_host); 279 (void)printf("on %.*s\n", 280 (int)sizeof(ll.ll_line), 281 ll.ll_line); 282 } 283 ll.ll_tv = now; 284 (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 285 if (hostname) 286 (void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); 287 else 288 (void)memset(ll.ll_host, '\0', sizeof(ll.ll_host)); 289 if (have_ss) 290 ll.ll_ss = ss; 291 else 292 (void)memset(&ll.ll_ss, 0, sizeof(ll.ll_ss)); 293 if (updlastlogx(_PATH_LASTLOGX, pwd->pw_uid, &ll) != 0) 294 syslog(LOG_NOTICE, "Cannot update lastlogx: %m"); 295 } 296 #endif 297 298 #ifdef SUPPORT_UTMP 299 static void 300 doutmp(void) 301 { 302 struct utmp utmp; 303 304 (void)memset((void *)&utmp, 0, sizeof(utmp)); 305 utmp.ut_time = now.tv_sec; 306 (void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); 307 if (hostname) 308 (void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); 309 (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); 310 login(&utmp); 311 } 312 313 static void 314 dolastlog(int quiet) 315 { 316 struct lastlog ll; 317 int fd; 318 319 if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { 320 (void)lseek(fd, (off_t)(pwd->pw_uid * sizeof(ll)), SEEK_SET); 321 if (!quiet) { 322 if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && 323 ll.ll_time != 0) { 324 (void)printf("Last login: %.24s ", 325 ctime(&ll.ll_time)); 326 if (*ll.ll_host != '\0') 327 (void)printf("from %.*s ", 328 (int)sizeof(ll.ll_host), 329 ll.ll_host); 330 (void)printf("on %.*s\n", 331 (int)sizeof(ll.ll_line), ll.ll_line); 332 } 333 (void)lseek(fd, (off_t)(pwd->pw_uid * sizeof(ll)), 334 SEEK_SET); 335 } 336 memset((void *)&ll, 0, sizeof(ll)); 337 ll.ll_time = now.tv_sec; 338 (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 339 if (hostname) 340 (void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); 341 (void)write(fd, (char *)&ll, sizeof(ll)); 342 (void)close(fd); 343 } 344 } 345 #endif 346 347 void 348 badlogin(const char *name) 349 { 350 351 if (failures == 0) 352 return; 353 if (hostname) { 354 syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s", 355 failures, failures > 1 ? "S" : "", hostname); 356 syslog(LOG_AUTHPRIV|LOG_NOTICE, 357 "%d LOGIN FAILURE%s FROM %s, %s", 358 failures, failures > 1 ? "S" : "", hostname, name); 359 } else { 360 syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s", 361 failures, failures > 1 ? "S" : "", tty); 362 syslog(LOG_AUTHPRIV|LOG_NOTICE, 363 "%d LOGIN FAILURE%s ON %s, %s", 364 failures, failures > 1 ? "S" : "", tty, name); 365 } 366 } 367 368 const char * 369 stypeof(const char *ttyid) 370 { 371 struct ttyent *t; 372 373 return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : NULL); 374 } 375 376 void __dead 377 sleepexit(int eval) 378 { 379 380 (void)sleep(5); 381 exit(eval); 382 } 383 384 void 385 decode_ss(const char *arg) 386 { 387 struct sockaddr_storage *ssp; 388 size_t len = strlen(arg); 389 390 if (len > sizeof(*ssp) * 4 + 1 || len < sizeof(*ssp)) 391 errx(EXIT_FAILURE, "Bad argument"); 392 393 if ((ssp = malloc(len + 1)) == NULL) 394 err(EXIT_FAILURE, NULL); 395 396 if (strunvis((char *)ssp, arg) != sizeof(*ssp)) 397 errx(EXIT_FAILURE, "Decoding error"); 398 399 (void)memcpy(&ss, ssp, sizeof(ss)); 400 free(ssp); 401 have_ss = 1; 402 } 403