diff options
Diffstat (limited to 'loginrec.c')
-rw-r--r-- | loginrec.c | 104 |
1 files changed, 103 insertions, 1 deletions
diff --git a/loginrec.c b/loginrec.c index 25aa29f2f..e77318ba3 100644 --- a/loginrec.c +++ b/loginrec.c | |||
@@ -25,6 +25,27 @@ | |||
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | /* | ||
29 | * The btmp logging code is derived from login.c from util-linux and is under | ||
30 | * the the following license: | ||
31 | * | ||
32 | * Copyright (c) 1980, 1987, 1988 The Regents of the University of California. | ||
33 | * All rights reserved. | ||
34 | * | ||
35 | * Redistribution and use in source and binary forms are permitted | ||
36 | * provided that the above copyright notice and this paragraph are | ||
37 | * duplicated in all such forms and that any documentation, | ||
38 | * advertising materials, and other materials related to such | ||
39 | * distribution and use acknowledge that the software was developed | ||
40 | * by the University of California, Berkeley. The name of the | ||
41 | * University may not be used to endorse or promote products derived | ||
42 | * from this software without specific prior written permission. | ||
43 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | ||
44 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | ||
45 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
46 | */ | ||
47 | |||
48 | |||
28 | /** | 49 | /** |
29 | ** loginrec.c: platform-independent login recording and lastlog retrieval | 50 | ** loginrec.c: platform-independent login recording and lastlog retrieval |
30 | **/ | 51 | **/ |
@@ -131,6 +152,8 @@ | |||
131 | #include "loginrec.h" | 152 | #include "loginrec.h" |
132 | #include "log.h" | 153 | #include "log.h" |
133 | #include "atomicio.h" | 154 | #include "atomicio.h" |
155 | #include "packet.h" | ||
156 | #include "canohost.h" | ||
134 | 157 | ||
135 | #ifdef HAVE_UTIL_H | 158 | #ifdef HAVE_UTIL_H |
136 | # include <util.h> | 159 | # include <util.h> |
@@ -140,7 +163,7 @@ | |||
140 | # include <libutil.h> | 163 | # include <libutil.h> |
141 | #endif | 164 | #endif |
142 | 165 | ||
143 | RCSID("$Id: loginrec.c,v 1.62 2004/09/12 05:26:01 djm Exp $"); | 166 | RCSID("$Id: loginrec.c,v 1.63 2005/02/02 12:30:25 dtucker Exp $"); |
144 | 167 | ||
145 | /** | 168 | /** |
146 | ** prototypes for helper functions in this file | 169 | ** prototypes for helper functions in this file |
@@ -1563,3 +1586,82 @@ lastlog_get_entry(struct logininfo *li) | |||
1563 | return (0); | 1586 | return (0); |
1564 | } | 1587 | } |
1565 | #endif /* USE_LASTLOG */ | 1588 | #endif /* USE_LASTLOG */ |
1589 | |||
1590 | #ifdef USE_BTMP | ||
1591 | /* | ||
1592 | * Logs failed login attempts in _PATH_BTMP if that exists. | ||
1593 | * The most common login failure is to give password instead of username. | ||
1594 | * So the _PATH_BTMP file checked for the correct permission, so that | ||
1595 | * only root can read it. | ||
1596 | */ | ||
1597 | |||
1598 | void | ||
1599 | record_failed_login(const char *username, const char *hostname, | ||
1600 | const char *ttyn) | ||
1601 | { | ||
1602 | int fd; | ||
1603 | struct utmp ut; | ||
1604 | struct sockaddr_storage from; | ||
1605 | size_t fromlen = sizeof(from); | ||
1606 | struct sockaddr_in *a4; | ||
1607 | struct sockaddr_in6 *a6; | ||
1608 | time_t t; | ||
1609 | struct stat fst; | ||
1610 | |||
1611 | if (geteuid() != 0) | ||
1612 | return; | ||
1613 | if ((fd = open(_PATH_BTMP, O_WRONLY | O_APPEND)) < 0) { | ||
1614 | debug("Unable to open the btmp file %s: %s", _PATH_BTMP, | ||
1615 | strerror(errno)); | ||
1616 | return; | ||
1617 | } | ||
1618 | if (fstat(fd, &fst) < 0) { | ||
1619 | logit("%s: fstat of %s failed: %s", __func__, _PATH_BTMP, | ||
1620 | strerror(errno)); | ||
1621 | goto out; | ||
1622 | } | ||
1623 | if((fst.st_mode & (S_IRWXG | S_IRWXO)) || (fst.st_uid != 0)){ | ||
1624 | logit("Excess permission or bad ownership on file %s", | ||
1625 | _PATH_BTMP); | ||
1626 | goto out; | ||
1627 | } | ||
1628 | |||
1629 | memset(&ut, 0, sizeof(ut)); | ||
1630 | /* strncpy because we don't necessarily want nul termination */ | ||
1631 | strncpy(ut.ut_user, username, sizeof(ut.ut_user)); | ||
1632 | strlcpy(ut.ut_line, "ssh:notty", sizeof(ut.ut_line)); | ||
1633 | |||
1634 | time(&t); | ||
1635 | ut.ut_time = t; /* ut_time is not always a time_t */ | ||
1636 | ut.ut_type = LOGIN_PROCESS; | ||
1637 | ut.ut_pid = getpid(); | ||
1638 | |||
1639 | /* strncpy because we don't necessarily want nul termination */ | ||
1640 | strncpy(ut.ut_host, hostname, sizeof(ut.ut_host)); | ||
1641 | |||
1642 | if (packet_connection_is_on_socket() && | ||
1643 | getpeername(packet_get_connection_in(), | ||
1644 | (struct sockaddr *)&from, &fromlen) == 0) { | ||
1645 | ipv64_normalise_mapped(&from, &fromlen); | ||
1646 | if (from.ss_family == AF_INET) { | ||
1647 | a4 = (struct sockaddr_in *)&from; | ||
1648 | memcpy(&ut.ut_addr, &(a4->sin_addr), | ||
1649 | MIN_SIZEOF(ut.ut_addr, a4->sin_addr)); | ||
1650 | } | ||
1651 | #ifdef HAVE_ADDR_V6_IN_UTMP | ||
1652 | if (from.ss_family == AF_INET6) { | ||
1653 | a6 = (struct sockaddr_in6 *)&from; | ||
1654 | memcpy(&ut.ut_addr_v6, &(a6->sin6_addr), | ||
1655 | MIN_SIZEOF(ut.ut_addr_v6, a6->sin6_addr)); | ||
1656 | } | ||
1657 | #endif | ||
1658 | } | ||
1659 | |||
1660 | if (atomicio(vwrite, fd, &ut, sizeof(ut)) != sizeof(ut)) | ||
1661 | error("Failed to write to %s: %s", _PATH_BTMP, | ||
1662 | strerror(errno)); | ||
1663 | |||
1664 | out: | ||
1665 | close(fd); | ||
1666 | } | ||
1667 | #endif /* USE_BTMP */ | ||