1 /* $NetBSD: common.c,v 1.3 2009/12/29 20:15:15 christos Exp $ */
4 * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: common.c,v 1.3 2009/12/29 20:15:15 christos Exp $");
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
51 #include "pathnames.h"
54 #if defined(KERBEROS5)
55 #define NBUFSIZ (MAXLOGNAME + 1 + 5) /* .root suffix */
57 #define NBUFSIZ (MAXLOGNAME + 1)
62 static void doutmp(void);
63 static void dolastlog(int);
67 static void doutmpx(void);
68 static void dolastlogx(int);
72 * This bounds the time given to login. Not a define so it can
73 * be patched on machines where it's too small.
77 void decode_ss(const char *);
79 int failures
, have_ss
;
80 char term
[64], *envinit
[1], *hostname
, *username
, *tty
, *nested
;
82 struct sockaddr_storage ss
;
89 static char nbuf
[NBUFSIZ
];
92 (void)printf("login: ");
93 for (p
= nbuf
; (ch
= getchar()) != '\n'; ) {
98 if (p
< nbuf
+ (NBUFSIZ
- 1))
103 (void)fprintf(stderr
,
104 "login names may not start with '-'.\n");
119 return ((t
= getttynam(ttyn
)) && t
->ty_status
& TTY_SECURE
);
122 static jmp_buf motdinterrupt
;
131 if ((fd
= open(fname
? fname
: _PATH_MOTDFILE
, O_RDONLY
, 0)) < 0)
133 oldint
= signal(SIGINT
, sigint
);
134 if (setjmp(motdinterrupt
) == 0)
135 while ((nchars
= read(fd
, tbuf
, sizeof(tbuf
))) > 0)
136 (void)write(fileno(stdout
), tbuf
, nchars
);
137 (void)signal(SIGINT
, oldint
);
146 longjmp(motdinterrupt
, 1);
154 (void)fprintf(stderr
, "Login timed out after %d seconds\n", timeout
);
159 update_db(int quietlog
, int rootlogin
, int fflag
)
161 struct sockaddr_storage ass
;
167 hname
= (hostname
== NULL
) ? "?" : hostname
;
168 if (getpeername(STDIN_FILENO
, (struct sockaddr
*)&ass
, &alen
) != -1) {
169 (void)sockaddr_snprintf(assbuf
,
170 sizeof(assbuf
), "%A (%a)", (void *)&ass
);
173 (void)sockaddr_snprintf(ssbuf
,
174 sizeof(ssbuf
), "%A(%a)", (void *)&ss
);
175 if (memcmp(&ass
, &ss
, alen
) != 0)
177 "login %s on tty %s address mismatch "
178 "passed %s != actual %s", username
, tty
,
183 } else if (have_ss
) {
184 (void)sockaddr_snprintf(assbuf
,
185 sizeof(assbuf
), "%A(%a)", (void *)&ss
);
187 } else if (hostname
) {
188 (void)snprintf(assbuf
, sizeof(assbuf
), "? ?");
193 /* If fflag is on, assume caller/authenticator has logged root login. */
194 if (rootlogin
&& fflag
== 0) {
196 syslog(LOG_NOTICE
, "ROOT LOGIN (%s) on tty %s from %s /"
197 " %s", username
, tty
, hname
, assbuf
);
199 syslog(LOG_NOTICE
, "ROOT LOGIN (%s) on tty %s",
201 } else if (nested
!= NULL
) {
203 syslog(LOG_NOTICE
, "%s to %s on tty %s from %s / "
204 "%s", nested
, pwd
->pw_name
, tty
, hname
, assbuf
);
206 syslog(LOG_NOTICE
, "%s to %s on tty %s", nested
,
210 syslog(LOG_NOTICE
, "%s on tty %s from %s / %s",
211 pwd
->pw_name
, tty
, hname
, assbuf
);
213 syslog(LOG_NOTICE
, "%s on tty %s",
216 (void)gettimeofday(&now
, NULL
);
219 dolastlogx(quietlog
);
235 memset((void *)&utmpx
, 0, sizeof(utmpx
));
237 (void)strncpy(utmpx
.ut_name
, username
, sizeof(utmpx
.ut_name
));
239 (void)strncpy(utmpx
.ut_host
, hostname
, sizeof(utmpx
.ut_host
));
242 (void)strncpy(utmpx
.ut_line
, tty
, sizeof(utmpx
.ut_line
));
243 utmpx
.ut_type
= USER_PROCESS
;
244 utmpx
.ut_pid
= getpid();
245 t
= tty
+ strlen(tty
);
246 if (t
- tty
>= sizeof(utmpx
.ut_id
)) {
247 (void)strncpy(utmpx
.ut_id
, t
- sizeof(utmpx
.ut_id
),
248 sizeof(utmpx
.ut_id
));
250 (void)strncpy(utmpx
.ut_id
, tty
, sizeof(utmpx
.ut_id
));
252 if (pututxline(&utmpx
) == NULL
)
253 syslog(LOG_NOTICE
, "Cannot update utmpx: %m");
255 if (updwtmpx(_PATH_WTMPX
, &utmpx
) != 0)
256 syslog(LOG_NOTICE
, "Cannot update wtmpx: %m");
260 dolastlogx(int quiet
)
263 if (!quiet
&& getlastlogx(_PATH_LASTLOGX
, pwd
->pw_uid
, &ll
) != NULL
) {
264 time_t t
= (time_t)ll
.ll_tv
.tv_sec
;
265 (void)printf("Last login: %.24s ", ctime(&t
));
266 if (*ll
.ll_host
!= '\0')
267 (void)printf("from %.*s ",
268 (int)sizeof(ll
.ll_host
),
270 (void)printf("on %.*s\n",
271 (int)sizeof(ll
.ll_line
),
275 (void)strncpy(ll
.ll_line
, tty
, sizeof(ll
.ll_line
));
277 (void)strncpy(ll
.ll_host
, hostname
, sizeof(ll
.ll_host
));
279 (void)memset(ll
.ll_host
, '\0', sizeof(ll
.ll_host
));
283 (void)memset(&ll
.ll_ss
, 0, sizeof(ll
.ll_ss
));
284 if (updlastlogx(_PATH_LASTLOGX
, pwd
->pw_uid
, &ll
) != 0)
285 syslog(LOG_NOTICE
, "Cannot update lastlogx: %m");
295 (void)memset((void *)&utmp
, 0, sizeof(utmp
));
296 utmp
.ut_time
= now
.tv_sec
;
297 (void)strncpy(utmp
.ut_name
, username
, sizeof(utmp
.ut_name
));
299 (void)strncpy(utmp
.ut_host
, hostname
, sizeof(utmp
.ut_host
));
300 (void)strncpy(utmp
.ut_line
, tty
, sizeof(utmp
.ut_line
));
310 if ((fd
= open(_PATH_LASTLOG
, O_RDWR
, 0)) >= 0) {
311 (void)lseek(fd
, (off_t
)(pwd
->pw_uid
* sizeof(ll
)), SEEK_SET
);
313 if (read(fd
, (char *)&ll
, sizeof(ll
)) == sizeof(ll
) &&
315 (void)printf("Last login: %.24s ",
317 if (*ll
.ll_host
!= '\0')
318 (void)printf("from %.*s ",
319 (int)sizeof(ll
.ll_host
),
321 (void)printf("on %.*s\n",
322 (int)sizeof(ll
.ll_line
), ll
.ll_line
);
324 (void)lseek(fd
, (off_t
)(pwd
->pw_uid
* sizeof(ll
)),
327 memset((void *)&ll
, 0, sizeof(ll
));
328 ll
.ll_time
= now
.tv_sec
;
329 (void)strncpy(ll
.ll_line
, tty
, sizeof(ll
.ll_line
));
331 (void)strncpy(ll
.ll_host
, hostname
, sizeof(ll
.ll_host
));
332 (void)write(fd
, (char *)&ll
, sizeof(ll
));
339 badlogin(const char *name
)
345 syslog(LOG_NOTICE
, "%d LOGIN FAILURE%s FROM %s",
346 failures
, failures
> 1 ? "S" : "", hostname
);
347 syslog(LOG_AUTHPRIV
|LOG_NOTICE
,
348 "%d LOGIN FAILURE%s FROM %s, %s",
349 failures
, failures
> 1 ? "S" : "", hostname
, name
);
351 syslog(LOG_NOTICE
, "%d LOGIN FAILURE%s ON %s",
352 failures
, failures
> 1 ? "S" : "", tty
);
353 syslog(LOG_AUTHPRIV
|LOG_NOTICE
,
354 "%d LOGIN FAILURE%s ON %s, %s",
355 failures
, failures
> 1 ? "S" : "", tty
, name
);
360 stypeof(const char *ttyid
)
364 return (ttyid
&& (t
= getttynam(ttyid
)) ? t
->ty_type
: NULL
);
376 decode_ss(const char *arg
)
378 struct sockaddr_storage
*ssp
;
379 size_t len
= strlen(arg
);
381 if (len
> sizeof(*ssp
) * 4 + 1 || len
< sizeof(*ssp
))
382 errx(EXIT_FAILURE
, "Bad argument");
384 if ((ssp
= malloc(len
)) == NULL
)
385 err(EXIT_FAILURE
, NULL
);
387 if (strunvis((char *)ssp
, arg
) != sizeof(*ssp
))
388 errx(EXIT_FAILURE
, "Decoding error");
390 (void)memcpy(&ss
, ssp
, sizeof(ss
));