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