1 /* $NetBSD: common.c,v 1.6 2012/05/19 00:02:44 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.6 2012/05/19 00:02:44 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
, *tty
, *nested
;
83 struct sockaddr_storage ss
;
86 trimloginname(char *u
)
88 if (strlen(u
) > MAXLOGNAME
)
98 static char nbuf
[NBUFSIZ
];
101 (void)printf("login: ");
102 for (p
= nbuf
; (ch
= getchar()) != '\n'; ) {
107 if (p
< nbuf
+ (NBUFSIZ
- 1))
112 (void)fprintf(stderr
,
113 "login names may not start with '-'.\n");
127 return ((t
= getttynam(ttyn
)) && t
->ty_status
& TTY_SECURE
);
130 static jmp_buf motdinterrupt
;
133 motd(const char *fname
)
139 if ((fd
= open(fname
? fname
: _PATH_MOTDFILE
, O_RDONLY
, 0)) < 0)
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
);
154 longjmp(motdinterrupt
, 1);
162 (void)fprintf(stderr
, "Login timed out after %d seconds\n", timeout
);
167 update_db(int quietlog
, int rootlogin
, int fflag
)
169 struct sockaddr_storage ass
;
175 hname
= (hostname
== NULL
) ? "?" : hostname
;
176 if (getpeername(STDIN_FILENO
, (struct sockaddr
*)&ass
, &alen
) != -1) {
177 (void)sockaddr_snprintf(assbuf
,
178 sizeof(assbuf
), "%A (%a)", (void *)&ass
);
181 (void)sockaddr_snprintf(ssbuf
,
182 sizeof(ssbuf
), "%A(%a)", (void *)&ss
);
183 if (memcmp(&ass
, &ss
, alen
) != 0)
185 "login %s on tty %s address mismatch "
186 "passed %s != actual %s", username
, tty
,
191 } else if (have_ss
) {
192 (void)sockaddr_snprintf(assbuf
,
193 sizeof(assbuf
), "%A(%a)", (void *)&ss
);
195 } else if (hostname
) {
196 (void)snprintf(assbuf
, sizeof(assbuf
), "? ?");
201 /* If fflag is on, assume caller/authenticator has logged root login. */
202 if (rootlogin
&& fflag
== 0) {
204 syslog(LOG_NOTICE
, "ROOT LOGIN (%s) on tty %s from %s /"
205 " %s", username
, tty
, hname
, assbuf
);
207 syslog(LOG_NOTICE
, "ROOT LOGIN (%s) on tty %s",
209 } else if (nested
!= NULL
) {
211 syslog(LOG_NOTICE
, "%s to %s on tty %s from %s / "
212 "%s", nested
, pwd
->pw_name
, tty
, hname
, assbuf
);
214 syslog(LOG_NOTICE
, "%s to %s on tty %s", nested
,
218 syslog(LOG_NOTICE
, "%s on tty %s from %s / %s",
219 pwd
->pw_name
, tty
, hname
, assbuf
);
221 syslog(LOG_NOTICE
, "%s on tty %s",
224 (void)gettimeofday(&now
, NULL
);
227 dolastlogx(quietlog
);
243 memset((void *)&utmpx
, 0, sizeof(utmpx
));
245 (void)strncpy(utmpx
.ut_name
, username
, sizeof(utmpx
.ut_name
));
247 (void)strncpy(utmpx
.ut_host
, hostname
, sizeof(utmpx
.ut_host
));
250 (void)strncpy(utmpx
.ut_line
, tty
, sizeof(utmpx
.ut_line
));
251 utmpx
.ut_type
= USER_PROCESS
;
252 utmpx
.ut_pid
= getpid();
253 t
= tty
+ strlen(tty
);
254 if ((size_t)(t
- tty
) >= sizeof(utmpx
.ut_id
)) {
255 (void)strncpy(utmpx
.ut_id
, t
- sizeof(utmpx
.ut_id
),
256 sizeof(utmpx
.ut_id
));
258 (void)strncpy(utmpx
.ut_id
, tty
, sizeof(utmpx
.ut_id
));
260 if (pututxline(&utmpx
) == NULL
)
261 syslog(LOG_NOTICE
, "Cannot update utmpx: %m");
263 if (updwtmpx(_PATH_WTMPX
, &utmpx
) != 0)
264 syslog(LOG_NOTICE
, "Cannot update wtmpx: %m");
268 dolastlogx(int quiet
)
271 if (!quiet
&& getlastlogx(_PATH_LASTLOGX
, pwd
->pw_uid
, &ll
) != NULL
) {
272 time_t t
= (time_t)ll
.ll_tv
.tv_sec
;
273 (void)printf("Last login: %.24s ", ctime(&t
));
274 if (*ll
.ll_host
!= '\0')
275 (void)printf("from %.*s ",
276 (int)sizeof(ll
.ll_host
),
278 (void)printf("on %.*s\n",
279 (int)sizeof(ll
.ll_line
),
283 (void)strncpy(ll
.ll_line
, tty
, sizeof(ll
.ll_line
));
285 (void)strncpy(ll
.ll_host
, hostname
, sizeof(ll
.ll_host
));
287 (void)memset(ll
.ll_host
, '\0', sizeof(ll
.ll_host
));
291 (void)memset(&ll
.ll_ss
, 0, sizeof(ll
.ll_ss
));
292 if (updlastlogx(_PATH_LASTLOGX
, pwd
->pw_uid
, &ll
) != 0)
293 syslog(LOG_NOTICE
, "Cannot update lastlogx: %m");
303 (void)memset((void *)&utmp
, 0, sizeof(utmp
));
304 utmp
.ut_time
= now
.tv_sec
;
305 (void)strncpy(utmp
.ut_name
, username
, sizeof(utmp
.ut_name
));
307 (void)strncpy(utmp
.ut_host
, hostname
, sizeof(utmp
.ut_host
));
308 (void)strncpy(utmp
.ut_line
, tty
, sizeof(utmp
.ut_line
));
318 if ((fd
= open(_PATH_LASTLOG
, O_RDWR
, 0)) >= 0) {
319 (void)lseek(fd
, (off_t
)(pwd
->pw_uid
* sizeof(ll
)), SEEK_SET
);
321 if (read(fd
, (char *)&ll
, sizeof(ll
)) == sizeof(ll
) &&
323 (void)printf("Last login: %.24s ",
325 if (*ll
.ll_host
!= '\0')
326 (void)printf("from %.*s ",
327 (int)sizeof(ll
.ll_host
),
329 (void)printf("on %.*s\n",
330 (int)sizeof(ll
.ll_line
), ll
.ll_line
);
332 (void)lseek(fd
, (off_t
)(pwd
->pw_uid
* sizeof(ll
)),
335 memset((void *)&ll
, 0, sizeof(ll
));
336 ll
.ll_time
= now
.tv_sec
;
337 (void)strncpy(ll
.ll_line
, tty
, sizeof(ll
.ll_line
));
339 (void)strncpy(ll
.ll_host
, hostname
, sizeof(ll
.ll_host
));
340 (void)write(fd
, (char *)&ll
, sizeof(ll
));
347 badlogin(const char *name
)
353 syslog(LOG_NOTICE
, "%d LOGIN FAILURE%s FROM %s",
354 failures
, failures
> 1 ? "S" : "", hostname
);
355 syslog(LOG_AUTHPRIV
|LOG_NOTICE
,
356 "%d LOGIN FAILURE%s FROM %s, %s",
357 failures
, failures
> 1 ? "S" : "", hostname
, name
);
359 syslog(LOG_NOTICE
, "%d LOGIN FAILURE%s ON %s",
360 failures
, failures
> 1 ? "S" : "", tty
);
361 syslog(LOG_AUTHPRIV
|LOG_NOTICE
,
362 "%d LOGIN FAILURE%s ON %s, %s",
363 failures
, failures
> 1 ? "S" : "", tty
, name
);
368 stypeof(const char *ttyid
)
372 return (ttyid
&& (t
= getttynam(ttyid
)) ? t
->ty_type
: NULL
);
384 decode_ss(const char *arg
)
386 struct sockaddr_storage
*ssp
;
387 size_t len
= strlen(arg
);
389 if (len
> sizeof(*ssp
) * 4 + 1 || len
< sizeof(*ssp
))
390 errx(EXIT_FAILURE
, "Bad argument");
392 if ((ssp
= malloc(len
)) == NULL
)
393 err(EXIT_FAILURE
, NULL
);
395 if (strunvis((char *)ssp
, arg
) != sizeof(*ssp
))
396 errx(EXIT_FAILURE
, "Decoding error");
398 (void)memcpy(&ss
, ssp
, sizeof(ss
));