View | Details | Raw Unified | Return to bug 3384 | Differences between
and this patch

Collapse All | Expand All

(-)a/Makefile.in (-2 / +2 lines)
Lines 122-128 SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ Link Here
122
	audit.o audit-bsm.o audit-linux.o platform.o \
122
	audit.o audit-bsm.o audit-linux.o platform.o \
123
	sshpty.o sshlogin.o servconf.o serverloop.o \
123
	sshpty.o sshlogin.o servconf.o serverloop.o \
124
	auth.o auth2.o auth-options.o session.o \
124
	auth.o auth2.o auth-options.o session.o \
125
	auth2-chall.o groupaccess.o \
125
	auth2-chall.o groupaccess.o authreport.o \
126
	auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
126
	auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
127
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
127
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
128
	monitor.o monitor_wrap.o auth-krb5.o \
128
	monitor.o monitor_wrap.o auth-krb5.o \
Lines 307-313 distclean: regressclean Link Here
307
	rm -f *.o *.a $(TARGETS) logintest config.cache config.log
307
	rm -f *.o *.a $(TARGETS) logintest config.cache config.log
308
	rm -f *.out core opensshd.init openssh.xml
308
	rm -f *.out core opensshd.init openssh.xml
309
	rm -f Makefile buildpkg.sh config.h config.status
309
	rm -f Makefile buildpkg.sh config.h config.status
310
	rm -f survey.sh openbsd-compat/regress/Makefile *~ 
310
	rm -f survey.sh openbsd-compat/regress/Makefile *~
311
	rm -rf autom4te.cache
311
	rm -rf autom4te.cache
312
	rm -f regress/check-perm
312
	rm -f regress/check-perm
313
	rm -f regress/mkdtemp
313
	rm -f regress/mkdtemp
(-)a/README.authreport (+38 lines)
Line 0 Link Here
1
The authentication report feature
2
---------------------------------
3
There is an optional feature named 'authentication reporting', enabled
4
by the --enable-authreport configuration switch. This causes sshd to
5
report the outcome of every user authentication requested by a client to
6
an external program for further processing. The intention is to allow
7
for things like blacklisting clients that attempt to break into the system
8
by trying large lists of common user names. Consult your log files if you
9
don't know what I'm talking about.
10
11
Use of this feature requires the external authentication result processor
12
to set up a unix domain socket which sshd will then send report records
13
to. There is a configuration option named AuthReportSocket in sshd_config
14
which has to be set to the file system path of that socket, (or 'none',
15
the default). Unless this option is set to 'none', sshd will attempt to
16
access the socket during startup. If this fails, startup is aborted, so
17
the external processor has to be started before sshd. Communication style
18
is connectionless, so the receiving socket has to be of the SOCK_DGRAM
19
variety.
20
21
When sshd is up and running, every time a client connects and requests
22
user authentication, a record containing the authentication result is
23
sent. This record contains an ASCII string consisting of four parts
24
separated by blanks, formatted like
25
26
	"RES=reject ADDR=::1 PORT=52592 USER=goofy"
27
28
RES is set to the authentication result, encoded as either "accept" or
29
"reject". ADDR is the address of the requesting host, PORT is its source
30
port number. Finally, USER contains the user name for which authentication
31
was requested. The authreport-test folder contains a sample program
32
illustrating the feature.
33
34
Care has been taken to design this feature in a way that it interferes
35
with sshd's normal operation as little as possible. The socket used to
36
communicate to the external processor is set to nonblocking mode, and
37
any communiction failure will be ignored.
38
(-)a/auth.c (-1 / +8 lines)
Lines 76-82 Link Here
76
#include "ssherr.h"
76
#include "ssherr.h"
77
#include "compat.h"
77
#include "compat.h"
78
#include "channels.h"
78
#include "channels.h"
79
79
#ifdef ENABLE_AUTHREPORT
80
#include "authreport.h"
81
#endif
80
/* import */
82
/* import */
81
extern ServerOptions options;
83
extern ServerOptions options;
82
extern struct include_list includes;
84
extern struct include_list includes;
Lines 386-391 auth_maxtries_exceeded(struct ssh *ssh) Link Here
386
	    authctxt->user,
388
	    authctxt->user,
387
	    ssh_remote_ipaddr(ssh),
389
	    ssh_remote_ipaddr(ssh),
388
	    ssh_remote_port(ssh));
390
	    ssh_remote_port(ssh));
391
#ifdef ENABLE_AUTHREPORT
392
	debug_f("Reporting authentication result: %s",
393
	      authctxt->success ? "success" : "failed");
394
	report_auth_result(ssh);
395
#endif
389
	ssh_packet_disconnect(ssh, "Too many authentication failures");
396
	ssh_packet_disconnect(ssh, "Too many authentication failures");
390
	/* NOTREACHED */
397
	/* NOTREACHED */
391
}
398
}
(-)a/auth2.c (+8 lines)
Lines 58-63 Link Here
58
#endif
58
#endif
59
#include "monitor_wrap.h"
59
#include "monitor_wrap.h"
60
#include "digest.h"
60
#include "digest.h"
61
#ifdef ENABLE_AUTHREPORT
62
#include "authreport.h"
63
#endif
61
64
62
/* import */
65
/* import */
63
extern ServerOptions options;
66
extern ServerOptions options;
Lines 175-180 do_authentication2(struct ssh *ssh) Link Here
175
	ssh_dispatch_init(ssh, &dispatch_protocol_error);
178
	ssh_dispatch_init(ssh, &dispatch_protocol_error);
176
	ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request);
179
	ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request);
177
	ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success);
180
	ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success);
181
#ifdef ENABLE_AUTHREPORT
182
	debug_f("Reporting authentication result: %s",
183
	      authctxt->success ? "success" : "failed");
184
	report_auth_result(ssh);
185
#endif
178
	ssh->authctxt = NULL;
186
	ssh->authctxt = NULL;
179
}
187
}
180
188
(-)a/authreport.c (+121 lines)
Line 0 Link Here
1
/*
2
 * Copyright (c) 2022 Thomas Koeller.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
25
#include <errno.h>
26
#include <string.h>
27
#include <stdio.h>
28
#include <fcntl.h>
29
#include <unistd.h>
30
#include <stddef.h>
31
#include <sys/socket.h>
32
#include <sys/un.h>
33
34
#include "config.h"
35
#include "packet.h"
36
#include "log.h"
37
#include "misc.h"
38
#include "auth.h"
39
#include "authreport.h"
40
41
static int sock_l = -1;
42
43
void
44
init_auth_report(const char *skt_path)
45
{
46
	static const size_t sbsize = 1024;
47
48
	struct sockaddr_un remaddr = {
49
		.sun_family = AF_UNIX,
50
		.sun_path = { 0 }
51
	};
52
53
	if (skt_path == NULL || *skt_path == 0 ||
54
	    strcasecmp(skt_path, "none") == 0) {
55
		verbose("Authresult processing disabled");
56
		return;
57
	}
58
59
	strncpy(remaddr.sun_path, skt_path, sizeof remaddr.sun_path);
60
	if (*(remaddr.sun_path + sizeof remaddr.sun_path - 1) != 0) {
61
		/* Error: socket path truncated */
62
		fatal_f("Path '%s' too long", skt_path);
63
	}
64
65
	sock_l = socket(PF_LOCAL, SOCK_DGRAM, 0);
66
67
	if (sock_l == -1) {
68
		/* Error: failed to create local socket */
69
		fatal_f("Failed to create local socket %s: %s",
70
			skt_path, strerror(errno));
71
	}
72
73
	if (setsockopt(sock_l, SOL_SOCKET, SO_SNDBUF, &sbsize,  sizeof sbsize) < 0) {
74
		fatal_f("Failed to set socket buffer size:%s",
75
			strerror(errno));
76
	}
77
78
	if (set_nonblock(sock_l) < 0) {
79
		fatal_f("Failed to set socket nonblocking mode");
80
	}
81
82
	if (connect(sock_l, (__CONST_SOCKADDR_ARG) &remaddr, SUN_LEN(&remaddr)) < 0) {
83
		fatal_f("Failed to connect to socket %s: %s",
84
		skt_path, strerror(errno));
85
	}
86
}
87
88
void
89
report_auth_result(struct ssh *ssh)
90
{
91
	char rec[100];
92
	int n;
93
	const Authctxt *authctxt = ssh->authctxt;
94
	ssize_t nout;
95
96
	if (sock_l == -1) return;
97
98
	n = snprintf(rec, sizeof rec, AUTHRPT_REC_FMT,
99
		     authctxt->valid ? AUTHRPT_RES_ACCEPT : AUTHRPT_RES_REJECT,
100
		     ssh_remote_ipaddr(ssh),
101
		     ssh_remote_port(ssh),
102
		     authctxt->user
103
	);
104
105
	if (n >= sizeof rec) {
106
		error_f("Record length %d exceeds buffer size %z",
107
			n, sizeof rec);
108
		return;
109
	}
110
111
	nout = write(sock_l, rec, (size_t) n);
112
	if (nout != n) {
113
		if (nout < 0)
114
			error_f("Communication failure:%s", strerror(errno));
115
		else
116
			error_f("Message tuncated");
117
		/* Is there a better way to handle this condition? */
118
		close(sock_l);
119
		sock_l = -1;
120
	}
121
}
(-)a/authreport.h (+37 lines)
Line 0 Link Here
1
/*
2
 * Copyright (c) 2022 Thomas Koeller.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
25
#ifndef _SSH_AUTHREPORT_H
26
#define _SSH_AUTHREPORT_H
27
28
#define AUTHRPT_RES_ACCEPT "accept"
29
#define AUTHRPT_RES_REJECT "reject"
30
#define AUTHRPT_REC_FMT	"RES=%s ADDR=%s PORT=%u USER=%s"
31
32
struct ssh;
33
34
void init_auth_report(const char *);
35
void report_auth_result(struct ssh *);
36
37
#endif /* _SSH_AUTHREPORT_H */
(-)a/configure.ac (+13 lines)
Lines 3477-3482 else Link Here
3477
fi
3477
fi
3478
AC_SUBST([SSH_PRIVSEP_USER])
3478
AC_SUBST([SSH_PRIVSEP_USER])
3479
3479
3480
AUTHREPORT_MSG="no"
3481
AC_ARG_ENABLE([authreport],
3482
	[  --enable-authreport     Enable authentication result reporting ],
3483
	[
3484
		if test "x$enableval" = "xyes" ; then
3485
			AC_DEFINE([ENABLE_AUTHREPORT], [1],
3486
				  [Enable authentication failure reporting])
3487
			AUTHREPORT_MSG="yes"
3488
		fi
3489
	]
3490
)
3491
3480
if test "x$have_linux_no_new_privs" = "x1" ; then
3492
if test "x$have_linux_no_new_privs" = "x1" ; then
3481
AC_CHECK_DECL([SECCOMP_MODE_FILTER], [have_seccomp_filter=1], , [
3493
AC_CHECK_DECL([SECCOMP_MODE_FILTER], [have_seccomp_filter=1], , [
3482
	#include <sys/types.h>
3494
	#include <sys/types.h>
Lines 5587-5592 echo " Random number source: $RAND_MSG" Link Here
5587
echo "             Privsep sandbox style: $SANDBOX_STYLE"
5599
echo "             Privsep sandbox style: $SANDBOX_STYLE"
5588
echo "                   PKCS#11 support: $enable_pkcs11"
5600
echo "                   PKCS#11 support: $enable_pkcs11"
5589
echo "                  U2F/FIDO support: $enable_sk"
5601
echo "                  U2F/FIDO support: $enable_sk"
5602
echo "   Authentication result reporting: $AUTHREPORT_MSG"
5590
5603
5591
echo ""
5604
echo ""
5592
5605
(-)a/servconf.c (+17 lines)
Lines 195-200 initialize_server_options(ServerOptions *options) Link Here
195
	options->fingerprint_hash = -1;
195
	options->fingerprint_hash = -1;
196
	options->disable_forwarding = -1;
196
	options->disable_forwarding = -1;
197
	options->expose_userauth_info = -1;
197
	options->expose_userauth_info = -1;
198
#ifdef ENABLE_AUTHREPORT
199
	options->auth_report_socket = NULL;
200
#endif
198
}
201
}
199
202
200
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
203
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
Lines 470-475 fill_default_server_options(ServerOptions *options) Link Here
470
		CLEAR_ON_NONE(options->host_key_files[i]);
473
		CLEAR_ON_NONE(options->host_key_files[i]);
471
	for (i = 0; i < options->num_host_cert_files; i++)
474
	for (i = 0; i < options->num_host_cert_files; i++)
472
		CLEAR_ON_NONE(options->host_cert_files[i]);
475
		CLEAR_ON_NONE(options->host_cert_files[i]);
476
#ifdef ENABLE_AUTHREPORT
477
	CLEAR_ON_NONE(options->auth_report_socket);
478
#endif
473
#undef CLEAR_ON_NONE
479
#undef CLEAR_ON_NONE
474
480
475
	/* Similar handling for AuthenticationMethods=any */
481
	/* Similar handling for AuthenticationMethods=any */
Lines 517-522 typedef enum { Link Here
517
	sStreamLocalBindMask, sStreamLocalBindUnlink,
523
	sStreamLocalBindMask, sStreamLocalBindUnlink,
518
	sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
524
	sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
519
	sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
525
	sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
526
	sAuthReportSocket,
520
	sDeprecated, sIgnore, sUnsupported
527
	sDeprecated, sIgnore, sUnsupported
521
} ServerOpCodes;
528
} ServerOpCodes;
522
529
Lines 676-681 static struct { Link Here
676
	{ "rdomain", sRDomain, SSHCFG_ALL },
683
	{ "rdomain", sRDomain, SSHCFG_ALL },
677
	{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
684
	{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
678
	{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
685
	{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
686
	{ "authreportsocket", sAuthReportSocket, SSHCFG_ALL },
679
	{ NULL, sBadOption, 0 }
687
	{ NULL, sBadOption, 0 }
680
};
688
};
681
689
Lines 2435-2440 process_server_config_line_depth(ServerOptions *options, char *line, Link Here
2435
			*charptr = xstrdup(arg);
2443
			*charptr = xstrdup(arg);
2436
		break;
2444
		break;
2437
2445
2446
#ifdef ENABLE_AUTHREPORT
2447
	case sAuthReportSocket:
2448
		charptr = &options->auth_report_socket;
2449
		goto parse_filename;
2450
#endif
2451
2438
	case sDeprecated:
2452
	case sDeprecated:
2439
	case sIgnore:
2453
	case sIgnore:
2440
	case sUnsupported:
2454
	case sUnsupported:
Lines 2946-2951 dump_config(ServerOptions *o) Link Here
2946
#if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN)
2960
#if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN)
2947
	dump_cfg_string(sRDomain, o->routing_domain);
2961
	dump_cfg_string(sRDomain, o->routing_domain);
2948
#endif
2962
#endif
2963
#ifdef ENABLE_AUTHREPORT
2964
	dump_cfg_string(sAuthReportSocket, o->auth_report_socket);
2965
#endif
2949
2966
2950
	/* string arguments requiring a lookup */
2967
	/* string arguments requiring a lookup */
2951
	dump_cfg_string(sLogLevel, log_level_name(o->log_level));
2968
	dump_cfg_string(sLogLevel, log_level_name(o->log_level));
(-)a/servconf.h (+3 lines)
Lines 229-234 typedef struct { Link Here
229
	int	expose_userauth_info;
229
	int	expose_userauth_info;
230
	u_int64_t timing_secret;
230
	u_int64_t timing_secret;
231
	char   *sk_provider;
231
	char   *sk_provider;
232
#ifdef ENABLE_AUTHREPORT
233
	char   *auth_report_socket;
234
#endif
232
}       ServerOptions;
235
}       ServerOptions;
233
236
234
/* Information about the incoming connection as used by Match */
237
/* Information about the incoming connection as used by Match */
(-)a/sshd.c (+8 lines)
Lines 128-133 Link Here
128
#include "sk-api.h"
128
#include "sk-api.h"
129
#include "srclimit.h"
129
#include "srclimit.h"
130
#include "dh.h"
130
#include "dh.h"
131
#ifdef ENABLE_AUTHREPORT
132
#include "authreport.h"
133
#endif
131
134
132
/* Re-exec fds */
135
/* Re-exec fds */
133
#define REEXEC_DEVCRYPTO_RESERVED_FD	(STDERR_FILENO + 1)
136
#define REEXEC_DEVCRYPTO_RESERVED_FD	(STDERR_FILENO + 1)
Lines 2020-2025 main(int ac, char **av) Link Here
2020
	for (i = 0; i < options.num_log_verbose; i++)
2023
	for (i = 0; i < options.num_log_verbose; i++)
2021
		log_verbose_add(options.log_verbose[i]);
2024
		log_verbose_add(options.log_verbose[i]);
2022
2025
2026
#ifdef ENABLE_AUTHREPORT
2027
	/* Initiallize user authorization result reporting */
2028
	init_auth_report(options.auth_report_socket);
2029
#endif
2030
2023
	/*
2031
	/*
2024
	 * If not in debugging mode, not started from inetd and not already
2032
	 * If not in debugging mode, not started from inetd and not already
2025
	 * daemonized (eg re-exec via SIGHUP), disconnect from the controlling
2033
	 * daemonized (eg re-exec via SIGHUP), disconnect from the controlling
(-)a/sshd_config (+1 lines)
Lines 33-38 Link Here
33
#StrictModes yes
33
#StrictModes yes
34
#MaxAuthTries 6
34
#MaxAuthTries 6
35
#MaxSessions 10
35
#MaxSessions 10
36
#AuthReportSocket none
36
37
37
#PubkeyAuthentication yes
38
#PubkeyAuthentication yes
38
39
(-)a/sshd_config.5 (-1 / +8 lines)
Lines 231-236 is enabled), Link Here
231
.Qq password
231
.Qq password
232
and
232
and
233
.Qq publickey .
233
.Qq publickey .
234
.It Cm AuthReportSocket
235
Specifies the file system path of a unix domain socket. For every user
236
authentication request, sshd will report thr result by sending a record
237
containing the client's address to this socket.
238
This is meant to provide a means of blacklisting hosts that attempt to
239
break into the system by trying long lists of common passwords. A
240
literal 'none' given for this parameter disables reporting of authorization
241
failures.
234
.It Cm AuthorizedKeysCommand
242
.It Cm AuthorizedKeysCommand
235
Specifies a program to be used to look up the user's public keys.
243
Specifies a program to be used to look up the user's public keys.
236
The program must be owned by root, not writable by group or others and
244
The program must be owned by root, not writable by group or others and
237
- 

Return to bug 3384