2 * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 static char copyright
[] =
59 "@(#) Copyright (c) Apple Computer, Inc. 1997\n\n";
64 * login -h hostname (for telnetd, etc.)
65 * login -f name (for pre-authenticated login: datakit, xterm, etc.)
68 #include <sys/param.h>
71 #include <sys/resource.h>
90 #include <sys/types.h>
91 #include <sys/socket.h>
92 #include <netinet/in.h>
93 #include <arpa/inet.h>
96 #include <bsm/libbsm.h>
97 #include <bsm/audit_uevents.h>
100 #include <pam/pam_appl.h>
101 #include <pam/pam_misc.h>
104 #include "pathnames.h"
106 void badlogin
__P((char *));
107 void checknologin
__P((void));
108 void dolastlog
__P((int));
109 void getloginname
__P((void));
110 void motd
__P((void));
111 int rootterm
__P((char *));
112 void sigint
__P((int));
113 void sleepexit
__P((int));
114 char *stypeof
__P((char *));
115 void timedout
__P((int));
117 int klogin
__P((struct passwd
*, char *, char *, char *));
120 void au_fail(char *, int);
123 extern void login
__P((struct utmp
*));
124 static void bail(int, int);
125 static void refused(const char *, const char *, int);
127 #define TTYGRPNAME "tty" /* name of group to own ttys */
128 #define NO_SLEEP_EXIT 0
132 * This bounds the time given to login. Not a define so it can
133 * be patched on machines where it's too small.
146 char term
[64], *hostname
, *username
= NULL
, *tty
;
148 static pam_handle_t
*pamh
= NULL
;
149 static struct pam_conv conv
= { misc_conv
, NULL
};
151 static int pam_silent
= PAM_SILENT
;
152 static int pam_cred_established
;
153 static int pam_session_established
;
157 #define NA_EVENT_STR_SIZE 25
165 extern char **environ
;
169 int ask
, ch
, cnt
, oflag
= 0, fflag
, pflag
, quietlog
, rootlogin
= 0;
173 char *domain
, *p
, *ttyn
;
174 char tbuf
[MAXPATHLEN
+ 2], tname
[sizeof(_PATH_TTY
) + 10];
175 char localhost
[MAXHOSTNAMELEN
];
184 char auditsuccess
= 1;
186 (void)signal(SIGALRM
, timedout
);
187 (void)alarm(timeout
);
188 (void)signal(SIGQUIT
, SIG_IGN
);
189 (void)signal(SIGINT
, SIG_IGN
);
190 (void)setpriority(PRIO_PROCESS
, 0, 0);
192 openlog("login", LOG_ODELAY
, LOG_AUTH
);
195 * -p is used by getty to tell login not to destroy the environment
196 * -f is used to skip a second login authentication
197 * -h is used by other servers to pass the name of the remote
198 * host to login so that it may be placed in utmp and wtmp
201 if (gethostname(localhost
, sizeof(localhost
)) < 0)
202 syslog(LOG_ERR
, "couldn't get local hostname: %m");
204 domain
= strchr(localhost
, '.');
209 fflag
= hflag
= pflag
= 0;
211 while ((ch
= getopt(argc
, argv
, "1fh:p")) != EOF
)
221 errx(1, "-h option: %s", strerror(EPERM
));
223 if (domain
&& (p
= strchr(optarg
, '.')) &&
224 strcasecmp(p
, domain
) == 0)
234 syslog(LOG_ERR
, "invalid flag %c", ch
);
235 (void)fprintf(stderr
,
236 "usage: login [-fp] [-h hostname] [username]\n");
248 for (cnt
= getdtablesize(); cnt
> 2; cnt
--)
251 ttyn
= ttyname(STDIN_FILENO
);
252 if (ttyn
== NULL
|| *ttyn
== '\0') {
253 (void)snprintf(tname
, sizeof(tname
), "%s??", _PATH_TTY
);
256 if (tty
= strrchr(ttyn
, '/'))
261 /* Set the terminal id */
262 audit_set_terminal_id(&tid
);
263 if (fstat(STDIN_FILENO
, &st
) < 0) {
264 fprintf(stderr
, "login: Unable to stat terminal\n");
265 au_fail("Unable to stat terminal", 1);
268 if (S_ISCHR(st
.st_mode
)) {
269 tid
.port
= st
.st_rdev
;
275 pam_err
= pam_start("login", username
, &conv
, &pamh
);
276 if( pam_err
!= PAM_SUCCESS
) {
277 fprintf(stderr
, "login: PAM Error: %s\n", pam_strerror(pamh
, pam_err
));
278 au_fail("PAM Error", 1);
281 pam_err
= pam_set_item(pamh
, PAM_TTY
, tty
);
282 if( pam_err
!= PAM_SUCCESS
) {
283 fprintf(stderr
, "login: PAM Error: %s\n", pam_strerror(pamh
, pam_err
));
284 au_fail("PAM Error", 1);
288 pam_err
= pam_set_item(pamh
, PAM_RHOST
, hostname
);
289 if( pam_err
!= PAM_SUCCESS
) {
290 fprintf(stderr
, "login: PAM Error: %s\n", pam_strerror(pamh
, pam_err
));
291 au_fail("PAM Error", 1);
295 pam_err
= pam_set_item(pamh
, PAM_USER_PROMPT
, "login: ");
296 if( pam_err
!= PAM_SUCCESS
) {
297 fprintf(stderr
, "login: PAM Error: %s\n", pam_strerror(pamh
, pam_err
));
298 au_fail("PAM Error", 1);
304 pam_set_item(pamh
, PAM_USER
, username
);
305 pwd
= getpwnam(username
);
306 if( (pwd
!= NULL
) && (pwd
->pw_uid
== 0) )
309 if( (pwd
!= NULL
) && fflag
&& ((uid
== 0) || (uid
== pwd
->pw_uid
)) ){
311 auditsuccess
= 0; /* we've simply opened a terminal window */
314 pam_err
= pam_authenticate(pamh
, 0);
315 while( (!oflag
) && (cnt
++ < 10) && ((pam_err
== PAM_AUTH_ERR
) ||
316 (pam_err
== PAM_USER_UNKNOWN
) ||
317 (pam_err
== PAM_CRED_INSUFFICIENT
) ||
318 (pam_err
== PAM_AUTHINFO_UNAVAIL
))) {
320 * we are not exiting here, but this corresponds to
321 * a failed login event, so set exitstatus to 1
323 au_fail("Login incorrect", 1);
325 printf("Login incorrect\n");
328 pwd
= getpwnam(username
);
329 if( (pwd
!= NULL
) && (pwd
->pw_uid
== 0) )
331 pam_set_item(pamh
, PAM_USER
, username
);
332 pam_err
= pam_authenticate(pamh
, 0);
335 if( pam_err
!= PAM_SUCCESS
) {
336 pam_get_item(pamh
, PAM_USER
, (void *)&username
);
338 printf("Login incorrect\n");
339 au_fail("Login incorrect", 1);
343 pam_err
= pam_acct_mgmt(pamh
, 0);
344 if( pam_err
== PAM_NEW_AUTHTOK_REQD
) {
345 pam_err
= pam_chauthtok(pamh
, PAM_CHANGE_EXPIRED_AUTHTOK
);
347 if( pam_err
!= PAM_SUCCESS
) {
348 fprintf(stderr
, "login: PAM Error: %s\n", pam_strerror(pamh
, pam_err
));
349 au_fail("PAM error", 1);
354 pam_err
= pam_get_item(pamh
, PAM_USER
, (void *)&username
);
355 if( (pam_err
== PAM_SUCCESS
) && username
&& *username
)
356 pwd
= getpwnam(username
);
358 pam_err
= pam_open_session(pamh
, 0);
359 if( pam_err
!= PAM_SUCCESS
) {
360 fprintf(stderr
, "login: PAM Error: %s\n", pam_strerror(pamh
, pam_err
));
361 au_fail("PAM error", 1);
365 pam_err
= pam_setcred(pamh
, PAM_ESTABLISH_CRED
);
366 if( pam_err
!= PAM_SUCCESS
) {
367 fprintf(stderr
, "login: PAM Error: %s\n", pam_strerror(pamh
, pam_err
));
368 au_fail("PAM error", 1);
373 for (cnt
= 0;; ask
= 1) {
380 if ((instance
= strchr(username
, '.')) != NULL
) {
381 if (strncmp(instance
, ".root", 5) == 0)
387 if (strlen(username
) > UT_NAMESIZE
)
388 username
[UT_NAMESIZE
] = '\0';
391 * Note if trying multiple user names; log failures for
392 * previous user name, but don't bother logging one failure
393 * for nonexistent name (mistyped username).
395 if (failures
&& strcmp(tbuf
, username
)) {
396 if (failures
> (pwd
? 0 : 1)) {
401 (void)strcpy(tbuf
, username
);
403 if (pwd
= getpwnam(username
))
404 salt
= pwd
->pw_passwd
;
409 * if we have a valid account name, and it doesn't have a
410 * password, or the -f option was specified and the caller
411 * is root or the caller isn't changing their uid, don't
414 if (pwd
&& (*pwd
->pw_passwd
== '\0' ||
415 fflag
&& (uid
== 0 || uid
== pwd
->pw_uid
)))
418 if (pwd
&& pwd
->pw_uid
== 0)
421 (void)setpriority(PRIO_PROCESS
, 0, -4);
423 p
= getpass("Password:");
427 rval
= klogin(pwd
, instance
, localhost
, p
);
428 if (rval
!= 0 && rootlogin
&& pwd
->pw_uid
!= 0)
433 rval
= strcmp(crypt(p
, salt
), pwd
->pw_passwd
);
435 rval
= strcmp(crypt(p
, salt
), pwd
->pw_passwd
);
438 memset(p
, 0, strlen(p
));
440 (void)setpriority(PRIO_PROCESS
, 0, 0);
443 * If trying to log in as root without Kerberos,
444 * but with insecure terminal, refuse the login attempt.
449 if (pwd
&& rootlogin
&& !rootterm(tty
)) {
450 (void)fprintf(stderr
,
451 "%s login refused on this terminal.\n",
455 "LOGIN %s REFUSED FROM %s ON TTY %s",
456 pwd
->pw_name
, hostname
, tty
);
459 "LOGIN %s REFUSED ON TTY %s",
461 au_fail("Login refused on terminal", 0);
468 (void)printf("Login incorrect\n");
470 /* we allow 10 tries, but after 3 we start backing off */
474 au_fail("Login incorrect", 1);
477 au_fail("Login incorrect", 1);
478 sleep((u_int
)((cnt
- 3) * 5));
483 /* committed to login -- turn off timeout */
484 (void)alarm((u_int
)0);
488 /* if user not super-user, check for disabled logins */
492 /* Audit successful login */
496 setegid(pwd
->pw_gid
);
497 seteuid(rootlogin
? 0 : pwd
->pw_uid
);
499 /* First do a stat in case the homedir is automounted */
500 stat(pwd
->pw_dir
,&st
);
502 if (!*pwd
->pw_dir
|| chdir(pwd
->pw_dir
) < 0) {
503 printf("No home directory %s!\n", pwd
->pw_dir
);
505 refused("Cannot find root directory", "HOMEDIR", 1);
507 pwd
->pw_dir
= strdup("/");
508 if (pwd
->pw_dir
== NULL
) {
509 syslog(LOG_NOTICE
, "strdup(): %m");
512 printf("Logging in with home = \"/\".\n");
517 quietlog
= access(_PATH_HUSHLOGIN
, F_OK
) == 0;
519 /* Nothing else left to fail -- really log in. */
520 memset((void *)&utmp
, 0, sizeof(utmp
));
521 (void)time(&utmp
.ut_time
);
522 (void)strncpy(utmp
.ut_name
, username
, sizeof(utmp
.ut_name
));
524 (void)strncpy(utmp
.ut_host
, hostname
, sizeof(utmp
.ut_host
));
525 (void)strncpy(utmp
.ut_line
, tty
, sizeof(utmp
.ut_line
));
530 (void)chown(ttyn
, pwd
->pw_uid
,
531 (gr
= getgrnam(TTYGRPNAME
)) ? gr
->gr_gid
: pwd
->pw_gid
);
532 (void)chmod(ttyn
, 0620);
533 (void)setgid(pwd
->pw_gid
);
535 if (initgroups(username
, pwd
->pw_gid
) == -1)
536 syslog(LOG_ERR
, "login: initgroups() failed");
538 if (*pwd
->pw_shell
== '\0')
539 pwd
->pw_shell
= strdup(_PATH_BSHELL
);
540 if (pwd
->pw_shell
== NULL
) {
541 syslog(LOG_NOTICE
, "strdup(): %m");
545 /* Destroy environment unless user has requested its preservation. */
547 environ
= malloc(sizeof(char *));
550 (void)setenv("HOME", pwd
->pw_dir
, 1);
551 (void)setenv("SHELL", pwd
->pw_shell
, 1);
553 (void)strncpy(term
, stypeof(tty
), sizeof(term
));
554 (void)setenv("TERM", term
, 0);
555 (void)setenv("LOGNAME", pwd
->pw_name
, 1);
556 (void)setenv("USER", pwd
->pw_name
, 1);
557 (void)setenv("PATH", _PATH_DEFPATH
, 0);
560 (void)setenv("KRBTKFILE", krbtkfile_env
, 1);
564 pmenv
= pam_getenvlist(pamh
);
565 for( cnt
= 0; pmenv
&& pmenv
[cnt
]; cnt
++ )
571 } else if( pid
!= 0 ) {
572 waitpid(pid
, NULL
, 0);
573 pam_setcred(pamh
, PAM_DELETE_CRED
);
574 pam_err
= pam_close_session(pamh
, 0);
575 pam_end(pamh
,pam_err
);
583 if (tty
[sizeof("tty")-1] == 'd')
584 syslog(LOG_INFO
, "DIALUP %s, %s", tty
, pwd
->pw_name
);
586 /* If fflag is on, assume caller/authenticator has logged root login. */
587 if (rootlogin
&& fflag
== 0)
589 syslog(LOG_NOTICE
, "ROOT LOGIN (%s) ON %s FROM %s",
590 username
, tty
, hostname
);
592 syslog(LOG_NOTICE
, "ROOT LOGIN (%s) ON %s", username
, tty
);
595 if (!quietlog
&& notickets
== 1)
596 (void)printf("Warning: no Kerberos tickets issued.\n");
602 sizeof(tbuf
), "%s/%s", _PATH_MAILDIR
, pwd
->pw_name
);
603 if (stat(tbuf
, &st
) == 0 && st
.st_size
!= 0)
604 (void)printf("You have %smail.\n",
605 (st
.st_mtime
> st
.st_atime
) ? "new " : "");
608 (void)signal(SIGALRM
, SIG_DFL
);
609 (void)signal(SIGQUIT
, SIG_DFL
);
610 (void)signal(SIGINT
, SIG_DFL
);
611 (void)signal(SIGTSTP
, SIG_IGN
);
614 (void)strcpy(tbuf
+ 1, (p
= strrchr(pwd
->pw_shell
, '/')) ?
615 p
+ 1 : pwd
->pw_shell
);
617 if (setlogin(pwd
->pw_name
) < 0)
618 syslog(LOG_ERR
, "setlogin() failure: %m");
620 /* Discard permissions last so can't get killed and drop core. */
624 (void) setuid(pwd
->pw_uid
);
626 execlp(pwd
->pw_shell
, tbuf
, 0);
627 err(1, "%s", pwd
->pw_shell
);
631 #define NBUFSIZ (MAXLOGNAME + 1 + 5) /* .root suffix */
633 #define NBUFSIZ (MAXLOGNAME + 1)
637 * The following tokens are included in the audit record for successful login attempts
648 uid_t uid
= pwd
->pw_uid
;
649 gid_t gid
= pwd
->pw_gid
;
650 pid_t pid
= getpid();
653 /* If we are not auditing, don't cut an audit record; just return */
654 if (auditon(A_GETCOND
, &au_cond
, sizeof(long)) < 0) {
655 fprintf(stderr
, "login: Could not determine audit condition\n");
658 if (au_cond
== AUC_NOAUDIT
)
661 /* Compute and Set the user's preselection mask */
662 if(au_user_mask(pwd
->pw_name
, &aumask
) == -1) {
663 fprintf(stderr
, "login: Could not set audit mask\n");
667 /* Set the audit info for the user */
668 auinfo
.ai_auid
= uid
;
669 auinfo
.ai_asid
= pid
;
670 bcopy(&tid
, &auinfo
.ai_termid
, sizeof(auinfo
.ai_termid
));
671 bcopy(&aumask
, &auinfo
.ai_mask
, sizeof(auinfo
.ai_mask
));
672 if(setaudit(&auinfo
) != 0) {
673 fprintf(stderr
, "login: setaudit failed: %s\n", strerror(errno
));
677 if((aufd
= au_open()) == -1) {
678 fprintf(stderr
, "login: Audit Error: au_open() failed\n");
682 /* The subject that is created (euid, egid of the current process) */
683 if((tok
= au_to_subject32(uid
, geteuid(), getegid(),
684 uid
, gid
, pid
, pid
, &tid
)) == NULL
) {
685 fprintf(stderr
, "login: Audit Error: au_to_subject32() failed\n");
690 if((tok
= au_to_return32(0, 0)) == NULL
) {
691 fprintf(stderr
, "login: Audit Error: au_to_return32() failed\n");
696 if(au_close(aufd
, 1, AUE_login
) == -1) {
697 fprintf(stderr
, "login: Audit Record was not committed.\n");
703 * The following tokens are included in the audit record for successful login attempts
709 void au_fail(char *errmsg
, int na
)
716 pid_t pid
= getpid();
718 /* If we are not auditing, don't cut an audit record; just return */
719 if (auditon(A_GETCOND
, &au_cond
, sizeof(long)) < 0) {
720 fprintf(stderr
, "login: Could not determine audit condition\n");
723 if (au_cond
== AUC_NOAUDIT
)
726 if((aufd
= au_open()) == -1) {
727 fprintf(stderr
, "login: Audit Error: au_open() failed\n");
732 /* Non attributable event */
733 /* Assuming that login is not called within a users' session => auid,asid == -1 */
734 if((tok
= au_to_subject32(-1, geteuid(), getegid(), -1, -1,
735 pid
, -1, &tid
)) == NULL
) {
737 fprintf(stderr
, "login: Audit Error: au_to_subject32() failed\n");
742 /* we know the subject -- so use its value instead */
745 if((tok
= au_to_subject32(uid
, geteuid(), getegid(),
746 uid
, gid
, pid
, pid
, &tid
)) == NULL
) {
747 fprintf(stderr
, "login: Audit Error: au_to_subject32() failed\n");
753 /* Include the error message */
754 if((tok
= au_to_text(errmsg
)) == NULL
) {
755 fprintf(stderr
, "login: Audit Error: au_to_text() failed\n");
760 if((tok
= au_to_return32(1, errno
)) == NULL
) {
761 fprintf(stderr
, "login: Audit Error: au_to_return32() failed\n");
766 if(au_close(aufd
, 1, AUE_login
) == -1) {
767 fprintf(stderr
, "login: Audit Error: au_close() was not committed\n");
777 static char nbuf
[NBUFSIZ
];
780 (void)printf("login: ");
781 for (p
= nbuf
; (ch
= getchar()) != '\n'; ) {
786 if (p
< nbuf
+ (NBUFSIZ
- 1))
791 (void)fprintf(stderr
,
792 "login names may not start with '-'.\n");
808 return ((t
= getttynam(ttyn
)) && t
->ty_status
& TTY_SECURE
);
811 jmp_buf motdinterrupt
;
820 if ((fd
= open(_PATH_MOTDFILE
, O_RDONLY
, 0)) < 0)
822 oldint
= signal(SIGINT
, sigint
);
823 if (setjmp(motdinterrupt
) == 0)
824 while ((nchars
= read(fd
, tbuf
, sizeof(tbuf
))) > 0)
825 (void)write(fileno(stdout
), tbuf
, nchars
);
826 (void)signal(SIGINT
, oldint
);
836 longjmp(motdinterrupt
, 1);
845 (void)fprintf(stderr
, "Login timed out after %d seconds\n", timeout
);
855 if ((fd
= open(_PATH_NOLOGIN
, O_RDONLY
, 0)) >= 0) {
856 while ((nchars
= read(fd
, tbuf
, sizeof(tbuf
))) > 0)
857 (void)write(fileno(stdout
), tbuf
, nchars
);
858 au_fail("No login", 0);
870 /* HACK HACK HACK: This is because HFS doesn't support sparse files
871 * and seeking into the file too far is too slow. The "solution"
872 * is to just bail if the seek time for a large uid would be too
875 if(pwd
->pw_uid
> 100000) {
876 syslog(LOG_NOTICE
, "User login %s (%d) not logged in lastlog. UID too large.", pwd
->pw_name
, pwd
->pw_uid
);
880 if ((fd
= open(_PATH_LASTLOG
, O_RDWR
, 0)) >= 0) {
881 (void)lseek(fd
, (off_t
)pwd
->pw_uid
* sizeof(ll
), L_SET
);
883 if (read(fd
, (char *)&ll
, sizeof(ll
)) == sizeof(ll
) &&
885 (void)printf("Last login: %.*s ",
886 24-5, (char *)ctime(&ll
.ll_time
));
887 if (*ll
.ll_host
!= '\0')
888 (void)printf("from %.*s\n",
889 (int)sizeof(ll
.ll_host
),
892 (void)printf("on %.*s\n",
893 (int)sizeof(ll
.ll_line
),
896 (void)lseek(fd
, (off_t
)pwd
->pw_uid
* sizeof(ll
), L_SET
);
898 memset((void *)&ll
, 0, sizeof(ll
));
899 (void)time(&ll
.ll_time
);
900 (void)strncpy(ll
.ll_line
, tty
, sizeof(ll
.ll_line
));
902 (void)strncpy(ll
.ll_host
, hostname
, sizeof(ll
.ll_host
));
903 (void)write(fd
, (char *)&ll
, sizeof(ll
));
916 syslog(LOG_NOTICE
, "%d LOGIN FAILURE%s FROM %s",
917 failures
, failures
> 1 ? "S" : "", hostname
);
918 syslog(LOG_AUTHPRIV
|LOG_NOTICE
,
919 "%d LOGIN FAILURE%s FROM %s, %s",
920 failures
, failures
> 1 ? "S" : "", hostname
, name
);
922 syslog(LOG_NOTICE
, "%d LOGIN FAILURE%s ON %s",
923 failures
, failures
> 1 ? "S" : "", tty
);
924 syslog(LOG_AUTHPRIV
|LOG_NOTICE
,
925 "%d LOGIN FAILURE%s ON %s, %s",
926 failures
, failures
> 1 ? "S" : "", tty
, name
);
939 return (ttyid
&& (t
= getttynam(ttyid
)) ? t
->ty_type
: UNKNOWN
);
952 refused(const char *msg
, const char *rtype
, int lout
)
956 printf("%s.\n", msg
);
958 syslog(LOG_NOTICE
, "LOGIN %s REFUSED (%s) FROM %s ON TTY %s",
959 pwd
->pw_name
, rtype
, hostname
, tty
);
961 syslog(LOG_NOTICE
, "LOGIN %s REFUSED (%s) ON TTY %s",
962 pwd
->pw_name
, rtype
, tty
);
972 pam_syslog(const char *msg
)
974 syslog(LOG_ERR
, "%s: %s", msg
, pam_strerror(pamh
, pam_err
));
985 if (pam_session_established
) {
986 pam_err
= pam_close_session(pamh
, 0);
987 if (pam_err
!= PAM_SUCCESS
)
988 pam_syslog("pam_close_session()");
990 pam_session_established
= 0;
991 if (pam_cred_established
) {
992 pam_err
= pam_setcred(pamh
, pam_silent
|PAM_DELETE_CRED
);
993 if (pam_err
!= PAM_SUCCESS
)
994 pam_syslog("pam_setcred()");
996 pam_cred_established
= 0;
997 pam_end(pamh
, pam_err
);
1001 #endif /* USE_PAM */
1003 * Exit, optionally after sleeping a few seconds
1006 bail(int sec
, int eval
)