GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/login/failedlogin.c Lines: 0 40 0.0 %
Date: 2017-11-07 Branches: 0 24 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: failedlogin.c,v 1.17 2015/01/16 06:40:09 deraadt Exp $	*/
2
3
/*
4
 * Copyright (c) 1996 Todd C. Miller <Todd.Miller@courtesan.com>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
/*
20
 * failedlogin.c
21
 *	Log to failedlogin file and read from it, reporting the number of
22
 *	failed logins since the last good login and when/from where
23
 *	the last failed login was.
24
 */
25
26
#include <sys/stat.h>
27
#include <sys/time.h>
28
29
#include <fcntl.h>
30
#include <stdio.h>
31
#include <string.h>
32
#include <unistd.h>
33
#include <utmp.h>
34
35
#include "pathnames.h"
36
37
struct badlogin {
38
	char	bl_line[UT_LINESIZE];	/* tty used */
39
	char	bl_name[UT_NAMESIZE];	/* remote username */
40
	char	bl_host[UT_HOSTSIZE];	/* remote host */
41
	time_t	bl_time;		/* time of the login attempt */
42
	size_t	count;			/* number of bad logins */
43
};
44
45
void	 log_failedlogin(uid_t, char *, char *, char *);
46
int	 check_failedlogin(uid_t);
47
48
/*
49
 * Log a bad login to the failedlogin file.
50
 */
51
void
52
log_failedlogin(uid_t uid, char *host, char *name, char *tty)
53
{
54
	struct badlogin failedlogin;
55
	int fd;
56
57
	/* Add O_CREAT if you want to create failedlogin if it doesn't exist */
58
	if ((fd = open(_PATH_FAILEDLOGIN, O_RDWR, S_IRUSR|S_IWUSR)) >= 0) {
59
		(void)lseek(fd, (off_t)uid * sizeof(failedlogin), SEEK_SET);
60
61
		/* Read in last bad login so can get the count */
62
		if (read(fd, (char *)&failedlogin, sizeof(failedlogin)) !=
63
			sizeof(failedlogin) || failedlogin.bl_time == 0)
64
			memset((void *)&failedlogin, 0, sizeof(failedlogin));
65
66
		(void)lseek(fd, (off_t)uid * sizeof(failedlogin), SEEK_SET);
67
		/* Increment count of bad logins */
68
		++failedlogin.count;
69
		(void)time(&failedlogin.bl_time);
70
		strncpy(failedlogin.bl_line, tty, sizeof(failedlogin.bl_line));
71
		if (host)
72
			strncpy(failedlogin.bl_host, host, sizeof(failedlogin.bl_host));
73
		else
74
			*failedlogin.bl_host = '\0';	/* NULL host field */
75
		if (name)
76
			strncpy(failedlogin.bl_name, name, sizeof(failedlogin.bl_name));
77
		else
78
			*failedlogin.bl_name = '\0';	/* NULL name field */
79
		(void)write(fd, (char *)&failedlogin, sizeof(failedlogin));
80
		(void)close(fd);
81
	}
82
}
83
84
/*
85
 * Check the failedlogin file and report about the number of unsuccessful
86
 * logins and info about the last one in lastlogin style.
87
 * NOTE: zeros the count field since this is assumed to be called after the
88
 * user has been validated.
89
 */
90
int
91
check_failedlogin(uid_t uid)
92
{
93
	struct badlogin failedlogin;
94
	int fd, was_bad = 0;
95
96
	(void)memset((void *)&failedlogin, 0, sizeof(failedlogin));
97
98
	if ((fd = open(_PATH_FAILEDLOGIN, O_RDWR, 0)) >= 0) {
99
		(void)lseek(fd, (off_t)uid * sizeof(failedlogin), SEEK_SET);
100
		if (read(fd, (char *)&failedlogin, sizeof(failedlogin)) ==
101
		    sizeof(failedlogin) && failedlogin.count > 0 ) {
102
			/* There was a bad login */
103
			was_bad = 1;
104
			if (failedlogin.count > 1)
105
				(void)printf("There have been %lu unsuccessful "
106
				    "login attempts to your account.\n",
107
				    (u_long)failedlogin.count);
108
			(void)printf("Last unsuccessful login: %.*s", 24-5,
109
				(char *)ctime(&failedlogin.bl_time));
110
			(void)printf(" on %.*s",
111
			    (int)sizeof(failedlogin.bl_line),
112
			    failedlogin.bl_line);
113
			if (*failedlogin.bl_host != '\0') {
114
				if (*failedlogin.bl_name != '\0')
115
					(void)printf(" from %.*s@%.*s",
116
					    (int)sizeof(failedlogin.bl_name),
117
					    failedlogin.bl_name,
118
					    (int)sizeof(failedlogin.bl_host),
119
					    failedlogin.bl_host);
120
				else
121
					(void)printf(" from %.*s",
122
					    (int)sizeof(failedlogin.bl_host),
123
					    failedlogin.bl_host);
124
			}
125
			(void)putchar('\n');
126
127
			/* Reset since this is a good login and write record */
128
			failedlogin.count = 0;
129
			(void)lseek(fd, (off_t)uid * sizeof(failedlogin),
130
			    SEEK_SET);
131
			(void)write(fd, (char *)&failedlogin,
132
			    sizeof(failedlogin));
133
		}
134
		(void)close(fd);
135
	}
136
	return(was_bad);
137
}