- (dtucker) [auth.c canohost.c canohost.h configure.ac defines.h loginrec.c]

Bug #974: Teach sshd to write failed login records to btmp for failed auth
   attempts (currently only for password, kbdint and C/R, only on Linux and
   HP-UX), based on code from login.c from util-linux. With ashok_kovai at
   hotmail.com, ok djm@
This commit is contained in:
Darren Tucker 2005-02-02 23:30:24 +11:00
Родитель 9dc6c7dbec
Коммит 2fba993080
7 изменённых файлов: 130 добавлений и 7 удалений

Просмотреть файл

@ -9,6 +9,11 @@
the process. Since we also unset KRB5CCNAME at startup, if it's set after
authentication it must have been set by the platform's native auth system.
This was already done for AIX; this enables it for the general case.
- (dtucker) [auth.c canohost.c canohost.h configure.ac defines.h loginrec.c]
Bug #974: Teach sshd to write failed login records to btmp for failed auth
attempts (currently only for password, kbdint and C/R, only on Linux and
HP-UX), based on code from login.c from util-linux. With ashok_kovai at
hotmail.com, ok djm@
20050201
- (dtucker) [log.c] Bug #973: force log_init() to open syslog, since on some
@ -2063,4 +2068,4 @@
- (djm) Trim deprecated options from INSTALL. Mention UsePAM
- (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
$Id: ChangeLog,v 1.3631 2005/02/02 07:30:33 dtucker Exp $
$Id: ChangeLog,v 1.3632 2005/02/02 12:30:24 dtucker Exp $

5
auth.c
Просмотреть файл

@ -244,7 +244,10 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
info);
#ifdef CUSTOM_FAILED_LOGIN
if (authenticated == 0 && strcmp(method, "password") == 0)
if (authenticated == 0 && !authctxt->postponed &&
(strcmp(method, "password") == 0 ||
strncmp(method, "keyboard-interactive", 20) == 0) ||
strcmp(method, "challenge-response") == 0)
record_failed_login(authctxt->user,
get_canonical_hostname(options.use_dns), "ssh");
#endif

Просмотреть файл

@ -20,7 +20,6 @@ RCSID("$OpenBSD: canohost.c,v 1.41 2004/07/21 11:51:29 djm Exp $");
#include "canohost.h"
static void check_ip_options(int, char *);
static void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);
/*
* Return the canonical name of the host at the other end of the socket. The
@ -166,7 +165,7 @@ check_ip_options(int sock, char *ipaddr)
#endif /* IP_OPTIONS */
}
static void
void
ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
{
struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)addr;

Просмотреть файл

@ -23,3 +23,5 @@ char *get_local_name(int);
int get_remote_port(void);
int get_local_port(void);
void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);

Просмотреть файл

@ -1,4 +1,4 @@
# $Id: configure.ac,v 1.236 2005/02/01 23:44:00 dtucker Exp $
# $Id: configure.ac,v 1.237 2005/02/02 12:30:25 dtucker Exp $
#
# Copyright (c) 1999-2004 Damien Miller
#
@ -219,6 +219,7 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
AC_DEFINE(DISABLE_UTMP)
AC_DEFINE(LOCKED_PASSWD_STRING, "*")
AC_DEFINE(SPT_TYPE,SPT_PSTAT)
AC_DEFINE(USE_BTMP, 1, [Use btmp to log bad logins])
check_for_hpux_broken_getaddrinfo=1
check_for_conflicting_getspnam=1
LIBS="$LIBS -lsec"
@ -256,6 +257,8 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
AC_DEFINE(LOCKED_PASSWD_PREFIX, "!")
AC_DEFINE(SPT_TYPE,SPT_REUSEARGV)
AC_DEFINE(LINK_OPNOTSUPP_ERRNO, EPERM)
AC_DEFINE(_PATH_BTMP, "/var/log/btmp", [log for bad login attempts])
AC_DEFINE(USE_BTMP, 1, [Use btmp to log bad logins])
inet6_default_4in6=yes
case `uname -r` in
1.*|2.0.*)

Просмотреть файл

@ -25,7 +25,7 @@
#ifndef _DEFINES_H
#define _DEFINES_H
/* $Id: defines.h,v 1.117 2004/06/22 03:27:16 dtucker Exp $ */
/* $Id: defines.h,v 1.118 2005/02/02 12:30:25 dtucker Exp $ */
/* Constants */
@ -644,6 +644,15 @@ struct winsize {
# define CUSTOM_SYS_AUTH_PASSWD 1
#endif
/* HP-UX 11.11 */
#ifdef BTMP_FILE
# define _PATH_BTMP BTMP_FILE
#endif
#if defined(USE_BTMP) && defined(_PATH_BTMP)
# define CUSTOM_FAILED_LOGIN
#endif
/** end of login recorder definitions */
#endif /* _DEFINES_H */

Просмотреть файл

@ -25,6 +25,27 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The btmp logging code is derived from login.c from util-linux and is under
* the the following license:
*
* Copyright (c) 1980, 1987, 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
** loginrec.c: platform-independent login recording and lastlog retrieval
**/
@ -131,6 +152,8 @@
#include "loginrec.h"
#include "log.h"
#include "atomicio.h"
#include "packet.h"
#include "canohost.h"
#ifdef HAVE_UTIL_H
# include <util.h>
@ -140,7 +163,7 @@
# include <libutil.h>
#endif
RCSID("$Id: loginrec.c,v 1.62 2004/09/12 05:26:01 djm Exp $");
RCSID("$Id: loginrec.c,v 1.63 2005/02/02 12:30:25 dtucker Exp $");
/**
** prototypes for helper functions in this file
@ -1563,3 +1586,82 @@ lastlog_get_entry(struct logininfo *li)
return (0);
}
#endif /* USE_LASTLOG */
#ifdef USE_BTMP
/*
* Logs failed login attempts in _PATH_BTMP if that exists.
* The most common login failure is to give password instead of username.
* So the _PATH_BTMP file checked for the correct permission, so that
* only root can read it.
*/
void
record_failed_login(const char *username, const char *hostname,
const char *ttyn)
{
int fd;
struct utmp ut;
struct sockaddr_storage from;
size_t fromlen = sizeof(from);
struct sockaddr_in *a4;
struct sockaddr_in6 *a6;
time_t t;
struct stat fst;
if (geteuid() != 0)
return;
if ((fd = open(_PATH_BTMP, O_WRONLY | O_APPEND)) < 0) {
debug("Unable to open the btmp file %s: %s", _PATH_BTMP,
strerror(errno));
return;
}
if (fstat(fd, &fst) < 0) {
logit("%s: fstat of %s failed: %s", __func__, _PATH_BTMP,
strerror(errno));
goto out;
}
if((fst.st_mode & (S_IRWXG | S_IRWXO)) || (fst.st_uid != 0)){
logit("Excess permission or bad ownership on file %s",
_PATH_BTMP);
goto out;
}
memset(&ut, 0, sizeof(ut));
/* strncpy because we don't necessarily want nul termination */
strncpy(ut.ut_user, username, sizeof(ut.ut_user));
strlcpy(ut.ut_line, "ssh:notty", sizeof(ut.ut_line));
time(&t);
ut.ut_time = t; /* ut_time is not always a time_t */
ut.ut_type = LOGIN_PROCESS;
ut.ut_pid = getpid();
/* strncpy because we don't necessarily want nul termination */
strncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
if (packet_connection_is_on_socket() &&
getpeername(packet_get_connection_in(),
(struct sockaddr *)&from, &fromlen) == 0) {
ipv64_normalise_mapped(&from, &fromlen);
if (from.ss_family == AF_INET) {
a4 = (struct sockaddr_in *)&from;
memcpy(&ut.ut_addr, &(a4->sin_addr),
MIN_SIZEOF(ut.ut_addr, a4->sin_addr));
}
#ifdef HAVE_ADDR_V6_IN_UTMP
if (from.ss_family == AF_INET6) {
a6 = (struct sockaddr_in6 *)&from;
memcpy(&ut.ut_addr_v6, &(a6->sin6_addr),
MIN_SIZEOF(ut.ut_addr_v6, a6->sin6_addr));
}
#endif
}
if (atomicio(vwrite, fd, &ut, sizeof(ut)) != sizeof(ut))
error("Failed to write to %s: %s", _PATH_BTMP,
strerror(errno));
out:
close(fd);
}
#endif /* USE_BTMP */