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

Collapse All | Expand All

(-)a/Makefile.in (+1 lines)
Lines 106-111 SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ Link Here
106
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
106
	auth2-none.o auth2-passwd.o auth2-pubkey.o \
107
	monitor_mm.o monitor.o monitor_wrap.o auth-krb5.o \
107
	monitor_mm.o monitor.o monitor_wrap.o auth-krb5.o \
108
	auth2-gss.o gss-serv.o gss-serv-krb5.o \
108
	auth2-gss.o gss-serv.o gss-serv-krb5.o \
109
	auth-u2f.o \
109
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
110
	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
110
	sftp-server.o sftp-common.o \
111
	sftp-server.o sftp-common.o \
111
	roaming_common.o roaming_serv.o \
112
	roaming_common.o roaming_serv.o \
(-)a/audit-linux.c (+1 lines)
Lines 113-118 audit_event(ssh_audit_event_t event) Link Here
113
	case SSH_AUTH_FAIL_PUBKEY:
113
	case SSH_AUTH_FAIL_PUBKEY:
114
	case SSH_AUTH_FAIL_HOSTBASED:
114
	case SSH_AUTH_FAIL_HOSTBASED:
115
	case SSH_AUTH_FAIL_GSSAPI:
115
	case SSH_AUTH_FAIL_GSSAPI:
116
	case SSH_AUTH_FAIL_U2F:
116
	case SSH_INVALID_USER:
117
	case SSH_INVALID_USER:
117
		linux_audit_record_event(-1, audit_username(), NULL,
118
		linux_audit_record_event(-1, audit_username(), NULL,
118
			get_remote_ipaddr(), "sshd", 0);
119
			get_remote_ipaddr(), "sshd", 0);
(-)a/audit.c (+3 lines)
Lines 63-68 audit_classify_auth(const char *method) Link Here
63
		return SSH_AUTH_FAIL_HOSTBASED;
63
		return SSH_AUTH_FAIL_HOSTBASED;
64
	else if (strcmp(method, "gssapi-with-mic") == 0)
64
	else if (strcmp(method, "gssapi-with-mic") == 0)
65
		return SSH_AUTH_FAIL_GSSAPI;
65
		return SSH_AUTH_FAIL_GSSAPI;
66
	else if (strcmp(method, "u2f") == 0)
67
		return SSH_AUTH_FAIL_U2F;
66
	else
68
	else
67
		return SSH_AUDIT_UNKNOWN;
69
		return SSH_AUDIT_UNKNOWN;
68
}
70
}
Lines 98-103 audit_event_lookup(ssh_audit_event_t ev) Link Here
98
		{SSH_AUTH_FAIL_PUBKEY,		"AUTH_FAIL_PUBKEY"},
100
		{SSH_AUTH_FAIL_PUBKEY,		"AUTH_FAIL_PUBKEY"},
99
		{SSH_AUTH_FAIL_HOSTBASED,	"AUTH_FAIL_HOSTBASED"},
101
		{SSH_AUTH_FAIL_HOSTBASED,	"AUTH_FAIL_HOSTBASED"},
100
		{SSH_AUTH_FAIL_GSSAPI,		"AUTH_FAIL_GSSAPI"},
102
		{SSH_AUTH_FAIL_GSSAPI,		"AUTH_FAIL_GSSAPI"},
103
		{SSH_AUTH_FAIL_U2F,		"AUTH_FAIL_U2F"},
101
		{SSH_INVALID_USER,		"INVALID_USER"},
104
		{SSH_INVALID_USER,		"INVALID_USER"},
102
		{SSH_NOLOGIN,			"NOLOGIN"},
105
		{SSH_NOLOGIN,			"NOLOGIN"},
103
		{SSH_CONNECTION_CLOSE,		"CONNECTION_CLOSE"},
106
		{SSH_CONNECTION_CLOSE,		"CONNECTION_CLOSE"},
(-)a/audit.h (+1 lines)
Lines 39-44 enum ssh_audit_event_type { Link Here
39
	SSH_AUTH_FAIL_PUBKEY,	/* ssh2 pubkey or ssh1 rsa */
39
	SSH_AUTH_FAIL_PUBKEY,	/* ssh2 pubkey or ssh1 rsa */
40
	SSH_AUTH_FAIL_HOSTBASED,	/* ssh2 hostbased or ssh1 rhostsrsa */
40
	SSH_AUTH_FAIL_HOSTBASED,	/* ssh2 hostbased or ssh1 rhostsrsa */
41
	SSH_AUTH_FAIL_GSSAPI,
41
	SSH_AUTH_FAIL_GSSAPI,
42
	SSH_AUTH_FAIL_U2F,
42
	SSH_INVALID_USER,
43
	SSH_INVALID_USER,
43
	SSH_NOLOGIN,		/* denied by /etc/nologin, not implemented */
44
	SSH_NOLOGIN,		/* denied by /etc/nologin, not implemented */
44
	SSH_CONNECTION_CLOSE,	/* closed after attempting auth or session */
45
	SSH_CONNECTION_CLOSE,	/* closed after attempting auth or session */
(-)a/auth.h (+10 lines)
Lines 76-81 struct Authctxt { Link Here
76
	char		*krb5_ticket_file;
76
	char		*krb5_ticket_file;
77
	char		*krb5_ccname;
77
	char		*krb5_ccname;
78
#endif
78
#endif
79
#ifdef U2F
80
	Key         *u2f_key;
81
	char        *u2f_challenge;
82
	int          u2f_attempt;
83
#endif
79
	Buffer		*loginmsg;
84
	Buffer		*loginmsg;
80
	void		*methoddata;
85
	void		*methoddata;
81
86
Lines 132-137 void pubkey_auth_info(Authctxt *, const Key *, const char *, ...) Link Here
132
void	 auth2_record_userkey(Authctxt *, struct sshkey *);
137
void	 auth2_record_userkey(Authctxt *, struct sshkey *);
133
int	 auth2_userkey_already_used(Authctxt *, struct sshkey *);
138
int	 auth2_userkey_already_used(Authctxt *, struct sshkey *);
134
139
140
#ifdef U2F
141
Key	 *read_user_u2f_key(struct passwd *, u_int);
142
int	 verify_u2f_user(Key *, u_char *, size_t, u_char *, size_t);
143
#endif
144
135
struct stat;
145
struct stat;
136
int	 auth_secure_path(const char *, struct stat *, const char *, uid_t,
146
int	 auth_secure_path(const char *, struct stat *, const char *, uid_t,
137
    char *, size_t);
147
    char *, size_t);
(-)a/auth2.c (+6 lines)
Lines 72-77 extern Authmethod method_hostbased; Link Here
72
#ifdef GSSAPI
72
#ifdef GSSAPI
73
extern Authmethod method_gssapi;
73
extern Authmethod method_gssapi;
74
#endif
74
#endif
75
#ifdef U2F
76
extern Authmethod method_u2f;
77
#endif
75
78
76
Authmethod *authmethods[] = {
79
Authmethod *authmethods[] = {
77
	&method_none,
80
	&method_none,
Lines 79-84 Authmethod *authmethods[] = { Link Here
79
#ifdef GSSAPI
82
#ifdef GSSAPI
80
	&method_gssapi,
83
	&method_gssapi,
81
#endif
84
#endif
85
#ifdef U2F
86
	&method_u2f,
87
#endif
82
	&method_passwd,
88
	&method_passwd,
83
	&method_kbdint,
89
	&method_kbdint,
84
	&method_hostbased,
90
	&method_hostbased,
(-)a/configure.ac (-3 / +57 lines)
Lines 1423-1428 AC_ARG_WITH([skey], Link Here
1423
	]
1423
	]
1424
)
1424
)
1425
1425
1426
# Check whether user wants u2f support (using libu2f-host)
1427
U2F_MSG="no"
1428
AC_ARG_WITH([u2f],
1429
	[  --with-u2f[[=PATH]]   Enable U2F support (using libu2f-host)],
1430
	[ if test "x$withval" != "xno" ; then
1431
		if test "x$withval" = "xyes" ; then
1432
			AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no])
1433
			if test "x$PKGCONFIG" != "xno"; then
1434
				AC_MSG_CHECKING([if $PKGCONFIG knows about u2f-host])
1435
			 	if "$PKGCONFIG" u2f-host; then
1436
					AC_MSG_RESULT([yes])
1437
					use_pkgconfig_for_libu2fhost=yes
1438
				else
1439
					AC_MSG_RESULT([no])
1440
				fi
1441
			fi
1442
		else
1443
			CPPFLAGS="$CPPFLAGS -I${withval}/include"
1444
			if test -n "${need_dash_r}"; then
1445
				LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
1446
			else
1447
				LDFLAGS="-L${withval}/lib ${LDFLAGS}"
1448
			fi
1449
		fi
1450
		if test "x$use_pkgconfig_for_libu2fhost" = "xyes"; then
1451
			LIBU2FHOST=`$PKGCONFIG --libs u2f-host`
1452
			CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags u2f-host`"
1453
		else
1454
			LIBU2FHOST="-lu2f-host"
1455
		fi
1456
		LIBS="$LIBS $LIBU2FHOST"
1457
		AC_CHECK_LIB([u2f-host], [u2fh_global_init],
1458
			[ AC_DEFINE([U2F], [1], [Enable U2F support (using libu2f-host)])
1459
			  U2F_MSG="yes"
1460
			  AC_SUBST([LIBU2FHOST])
1461
			],
1462
			[ AC_MSG_ERROR([libu2f-host not found]) ],
1463
			[ $LIBS ]
1464
		)
1465
		AC_MSG_CHECKING([if libu2f-host version is compatible])
1466
		AC_COMPILE_IFELSE(
1467
		    [AC_LANG_PROGRAM([[ #include <u2f-host.h> ]],
1468
		    [[
1469
	u2fh_global_init(0);
1470
	exit(0);
1471
		    ]])],
1472
		    [ AC_MSG_RESULT([yes]) ],
1473
		    [ AC_MSG_RESULT([no])
1474
		      AC_MSG_ERROR([u2f-host version is not compatible]) ]
1475
		)
1476
	fi ]
1477
)
1478
1426
# Check whether user wants to use ldns
1479
# Check whether user wants to use ldns
1427
LDNS_MSG="no"
1480
LDNS_MSG="no"
1428
AC_ARG_WITH(ldns,
1481
AC_ARG_WITH(ldns,
Lines 2318-2324 AC_ARG_WITH([ssl-engine], Link Here
2318
)
2371
)
2319
2372
2320
if test "x$openssl" = "xyes" ; then
2373
if test "x$openssl" = "xyes" ; then
2321
	LIBS="-lcrypto $LIBS"
2374
	LIBS="-lcrypto -lssl $LIBS"
2322
	AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL], [1],
2375
	AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL], [1],
2323
		[Define if your ssl headers are included
2376
		[Define if your ssl headers are included
2324
		with #include <openssl/header.h>])],
2377
		with #include <openssl/header.h>])],
Lines 2401-2408 if test "x$openssl" = "xyes" ; then Link Here
2401
			ssl_library_ver=`cat conftest.ssllibver`
2454
			ssl_library_ver=`cat conftest.ssllibver`
2402
			# Check version is supported.
2455
			# Check version is supported.
2403
			case "$ssl_library_ver" in
2456
			case "$ssl_library_ver" in
2404
				0090[[0-7]]*|009080[[0-5]]*)
2457
				0090*)
2405
					AC_MSG_ERROR([OpenSSL >= 0.9.8f required (have "$ssl_library_ver")])
2458
					AC_MSG_ERROR([OpenSSL >= 1.0.0 required (have "$ssl_library_ver")])
2406
			                ;;
2459
			                ;;
2407
			        *) ;;
2460
			        *) ;;
2408
			esac
2461
			esac
Lines 4931-4936 echo " KerberosV support: $KRB5_MSG" Link Here
4931
echo "                   SELinux support: $SELINUX_MSG"
4984
echo "                   SELinux support: $SELINUX_MSG"
4932
echo "                 Smartcard support: $SCARD_MSG"
4985
echo "                 Smartcard support: $SCARD_MSG"
4933
echo "                     S/KEY support: $SKEY_MSG"
4986
echo "                     S/KEY support: $SKEY_MSG"
4987
echo "                       U2F support: $U2F_MSG"
4934
echo "              MD5 password support: $MD5_MSG"
4988
echo "              MD5 password support: $MD5_MSG"
4935
echo "                   libedit support: $LIBEDIT_MSG"
4989
echo "                   libedit support: $LIBEDIT_MSG"
4936
echo "  Solaris process contract support: $SPC_MSG"
4990
echo "  Solaris process contract support: $SPC_MSG"
(-)a/monitor.c (+69 lines)
Lines 2-7 Link Here
2
/*
2
/*
3
 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3
 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4
 * Copyright 2002 Markus Friedl <markus@openbsd.org>
4
 * Copyright 2002 Markus Friedl <markus@openbsd.org>
5
 * Copyright 2014 Google Inc.
5
 * All rights reserved.
6
 * All rights reserved.
6
 *
7
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * Redistribution and use in source and binary forms, with or without
Lines 164-169 int mm_answer_audit_event(int, Buffer *); Link Here
164
int mm_answer_audit_command(int, Buffer *);
165
int mm_answer_audit_command(int, Buffer *);
165
#endif
166
#endif
166
167
168
#ifdef U2F
169
int mm_answer_read_user_u2f_key(int, Buffer *);
170
int mm_answer_verify_u2f_user(int, Buffer *);
171
#endif
172
167
static int monitor_read_log(struct monitor *);
173
static int monitor_read_log(struct monitor *);
168
174
169
static Authctxt *authctxt;
175
static Authctxt *authctxt;
Lines 235-240 struct mon_table mon_dispatch_proto20[] = { Link Here
235
    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
241
    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
236
    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
242
    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
237
#endif
243
#endif
244
#ifdef U2F
245
    {MONITOR_REQ_READUSERU2FKEY, MON_AUTH, mm_answer_read_user_u2f_key},
246
    {MONITOR_REQ_VERIFYU2FUSER, MON_AUTH, mm_answer_verify_u2f_user},
247
#endif
238
    {0, 0, NULL}
248
    {0, 0, NULL}
239
};
249
};
240
250
Lines 1806-1811 mm_answer_audit_event(int socket, Buffer *m) Link Here
1806
	case SSH_AUTH_FAIL_PUBKEY:
1816
	case SSH_AUTH_FAIL_PUBKEY:
1807
	case SSH_AUTH_FAIL_HOSTBASED:
1817
	case SSH_AUTH_FAIL_HOSTBASED:
1808
	case SSH_AUTH_FAIL_GSSAPI:
1818
	case SSH_AUTH_FAIL_GSSAPI:
1819
	case SSH_AUTH_FAIL_U2F:
1809
	case SSH_LOGIN_EXCEED_MAXTRIES:
1820
	case SSH_LOGIN_EXCEED_MAXTRIES:
1810
	case SSH_LOGIN_ROOT_DENIED:
1821
	case SSH_LOGIN_ROOT_DENIED:
1811
	case SSH_CONNECTION_CLOSE:
1822
	case SSH_CONNECTION_CLOSE:
Lines 2054-2056 mm_answer_gss_userok(int sock, Buffer *m) Link Here
2054
}
2065
}
2055
#endif /* GSSAPI */
2066
#endif /* GSSAPI */
2056
2067
2068
#ifdef U2F
2069
int
2070
mm_answer_read_user_u2f_key(int sock, Buffer *m)
2071
{
2072
	int authenticated = 0;
2073
	Key *key;
2074
	u_int key_idx;
2075
	u_char *blob = NULL;
2076
	u_int blen = 0;
2077
2078
	key_idx = buffer_get_int(m);
2079
	buffer_clear(m);
2080
2081
	key = read_user_u2f_key(authctxt->pw, key_idx);
2082
	buffer_put_int(m, key == NULL ? 1 : 0);
2083
	if (key != NULL)
2084
	{
2085
		if (key_to_blob(key, &blob, &blen) == 0)
2086
			fatal("%s: key_to_blob failed", __func__);
2087
		buffer_put_string(m, blob, blen);
2088
		debug3("%s: sending key", __func__);
2089
	} else {
2090
		debug3("%s: no key to send", __func__);
2091
		if (key_idx == 0) {
2092
			auth_method = "u2f";
2093
			authenticated = 1;
2094
		}
2095
	}
2096
2097
	mm_request_send(sock, MONITOR_ANS_READUSERU2FKEY, m);
2098
	return authenticated;
2099
}
2100
2101
int
2102
mm_answer_verify_u2f_user(int sock, Buffer *m)
2103
{
2104
	int authenticated = 0;
2105
	Key *key;
2106
	u_char *blob, *dgst, *sig;
2107
	u_int bloblen, dgstlen, siglen;
2108
2109
	blob = buffer_get_string(m, &bloblen);
2110
	key = key_from_blob(blob, bloblen);
2111
	dgst = buffer_get_string(m, &dgstlen);
2112
	sig = buffer_get_string(m, &siglen);
2113
2114
	buffer_clear(m);
2115
2116
	authenticated = verify_u2f_user(key, dgst, dgstlen, sig, siglen);
2117
	buffer_put_int(m, authenticated);
2118
2119
	auth_method = "u2f";
2120
	mm_request_send(sock, MONITOR_ANS_VERIFYU2FUSER, m);
2121
2122
	key_free(key);
2123
	return authenticated;
2124
}
2125
#endif /* U2F */
(-)a/monitor.h (+2 lines)
Lines 56-61 enum monitor_reqtype { Link Here
56
	MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
56
	MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
57
	MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
57
	MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
58
	MONITOR_REQ_TERM = 50,
58
	MONITOR_REQ_TERM = 50,
59
	MONITOR_REQ_READUSERU2FKEY = 52, MONITOR_ANS_READUSERU2FKEY = 53,
60
	MONITOR_REQ_VERIFYU2FUSER = 54, MONITOR_ANS_VERIFYU2FUSER = 55,
59
61
60
	MONITOR_REQ_PAM_START = 100,
62
	MONITOR_REQ_PAM_START = 100,
61
	MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,
63
	MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,
(-)a/monitor_wrap.c (+60 lines)
Lines 2-7 Link Here
2
/*
2
/*
3
 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3
 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4
 * Copyright 2002 Markus Friedl <markus@openbsd.org>
4
 * Copyright 2002 Markus Friedl <markus@openbsd.org>
5
 * Copyright 2014 Google Inc.
5
 * All rights reserved.
6
 * All rights reserved.
6
 *
7
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * Redistribution and use in source and binary forms, with or without
Lines 1087-1089 mm_ssh_gssapi_userok(char *user) Link Here
1087
}
1088
}
1088
#endif /* GSSAPI */
1089
#endif /* GSSAPI */
1089
1090
1091
#ifdef U2F
1092
Key *
1093
mm_read_user_u2f_key(struct passwd *pw, u_int key_idx)
1094
{
1095
	Buffer m;
1096
	Key *key = NULL;
1097
	u_char *blob;
1098
	u_int blen;
1099
	u_int is_null;
1100
1101
	debug3("%s entering", __func__);
1102
1103
	buffer_init(&m);
1104
	buffer_put_int(&m, key_idx);
1105
1106
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_READUSERU2FKEY, &m);
1107
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_READUSERU2FKEY, &m);
1108
1109
	is_null = buffer_get_int(&m);
1110
	if (is_null == 0) {
1111
		blob = buffer_get_string(&m, &blen);
1112
		if ((key = key_from_blob(blob, blen)) == NULL)
1113
			fatal("%s: key_from_blob failed", __func__);
1114
1115
		free(blob);
1116
	}
1117
1118
	buffer_free(&m);
1119
	return key;
1120
}
1121
1122
int
1123
mm_verify_u2f_user(Key *key, u_char * dgst, size_t dgstlen, u_char * sig, size_t siglen)
1124
{
1125
	int authenticated = 0;
1126
	Buffer m;
1127
	u_char *blob;
1128
	u_int blen;
1129
1130
	debug3("%s entering", __func__);
1131
1132
	if (key_to_blob(key, &blob, &blen) == 0)
1133
		fatal("%s: key_to_blob failed", __func__);
1134
	buffer_init(&m);
1135
	buffer_put_string(&m, blob, blen);
1136
	free(blob);
1137
1138
	buffer_put_string(&m, dgst, dgstlen);
1139
	buffer_put_string(&m, sig, siglen);
1140
1141
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_VERIFYU2FUSER, &m);
1142
	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_VERIFYU2FUSER, &m);
1143
1144
	authenticated = buffer_get_int(&m);
1145
	buffer_free(&m);
1146
1147
	return authenticated;
1148
}
1149
#endif /* U2F */
(-)a/monitor_wrap.h (+4 lines)
Lines 53-58 int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int); Link Here
53
int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
53
int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
54
int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
54
int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
55
BIGNUM *mm_auth_rsa_generate_challenge(Key *);
55
BIGNUM *mm_auth_rsa_generate_challenge(Key *);
56
#ifdef U2F
57
Key *mm_read_user_u2f_key(struct passwd *, u_int);
58
int mm_verify_u2f_user(Key *, u_char *, size_t, u_char *, size_t);
59
#endif
56
60
57
#ifdef GSSAPI
61
#ifdef GSSAPI
58
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
62
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
(-)a/readconf.c (+26 lines)
Lines 149-154 typedef enum { Link Here
149
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
149
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
150
	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
150
	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
151
	oSendEnv, oControlPath, oControlMaster, oControlPersist,
151
	oSendEnv, oControlPath, oControlMaster, oControlPersist,
152
	oU2FAuthentication, oU2FMode,
152
	oHashKnownHosts,
153
	oHashKnownHosts,
153
	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
154
	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
154
	oVisualHostKey, oUseRoaming,
155
	oVisualHostKey, oUseRoaming,
Lines 197-202 static struct { Link Here
197
	{ "gssapiauthentication", oUnsupported },
198
	{ "gssapiauthentication", oUnsupported },
198
	{ "gssapidelegatecredentials", oUnsupported },
199
	{ "gssapidelegatecredentials", oUnsupported },
199
#endif
200
#endif
201
#ifdef U2F
202
	{ "u2fauthentication", oU2FAuthentication },
203
	{ "u2fmode", oU2FMode },
204
#else
205
	{ "u2fmode", oUnsupported },
206
	{ "u2fauthentication", oUnsupported },
207
#endif
200
	{ "fallbacktorsh", oDeprecated },
208
	{ "fallbacktorsh", oDeprecated },
201
	{ "usersh", oDeprecated },
209
	{ "usersh", oDeprecated },
202
	{ "identityfile", oIdentityFile },
210
	{ "identityfile", oIdentityFile },
Lines 890-895 parse_time: Link Here
890
		intptr = &options->challenge_response_authentication;
898
		intptr = &options->challenge_response_authentication;
891
		goto parse_flag;
899
		goto parse_flag;
892
900
901
	case oU2FAuthentication:
902
		intptr = &options->u2f_authentication;
903
		goto parse_flag;
904
905
	case oU2FMode:
906
		charptr = &options->u2f_mode;
907
		goto parse_string;
908
893
	case oGssAuthentication:
909
	case oGssAuthentication:
894
		intptr = &options->gss_authentication;
910
		intptr = &options->gss_authentication;
895
		goto parse_flag;
911
		goto parse_flag;
Lines 1605-1610 initialize_options(Options * options) Link Here
1605
	options->password_authentication = -1;
1621
	options->password_authentication = -1;
1606
	options->kbd_interactive_authentication = -1;
1622
	options->kbd_interactive_authentication = -1;
1607
	options->kbd_interactive_devices = NULL;
1623
	options->kbd_interactive_devices = NULL;
1624
	options->u2f_authentication = -1;
1625
	options->u2f_mode = NULL;
1608
	options->rhosts_rsa_authentication = -1;
1626
	options->rhosts_rsa_authentication = -1;
1609
	options->hostbased_authentication = -1;
1627
	options->hostbased_authentication = -1;
1610
	options->batch_mode = -1;
1628
	options->batch_mode = -1;
Lines 1833-1838 fill_default_options(Options * options) Link Here
1833
		options->tun_remote = SSH_TUNID_ANY;
1851
		options->tun_remote = SSH_TUNID_ANY;
1834
	if (options->permit_local_command == -1)
1852
	if (options->permit_local_command == -1)
1835
		options->permit_local_command = 0;
1853
		options->permit_local_command = 0;
1854
	if (options->u2f_authentication == -1)
1855
		options->u2f_authentication = 1;
1856
	if (options->u2f_mode == NULL)
1857
		options->u2f_mode = strdup("authentication");
1836
	if (options->use_roaming == -1)
1858
	if (options->use_roaming == -1)
1837
		options->use_roaming = 1;
1859
		options->use_roaming = 1;
1838
	if (options->visual_host_key == -1)
1860
	if (options->visual_host_key == -1)
Lines 2272-2277 dump_client_config(Options *o, const char *host) Link Here
2272
	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
2294
	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
2273
	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
2295
	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
2274
#endif /* GSSAPI */
2296
#endif /* GSSAPI */
2297
#ifdef U2F
2298
	dump_cfg_fmtint(oU2FAuthentication, o->u2f_authentication);
2299
	dump_cfg_string(oU2FMode, o->u2f_mode);
2300
#endif /* GSSAPI */
2275
	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
2301
	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
2276
	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2302
	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2277
	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
2303
	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
(-)a/readconf.h (+2 lines)
Lines 46-55 typedef struct { Link Here
46
					/* Try S/Key or TIS, authentication. */
46
					/* Try S/Key or TIS, authentication. */
47
	int     gss_authentication;	/* Try GSS authentication */
47
	int     gss_authentication;	/* Try GSS authentication */
48
	int     gss_deleg_creds;	/* Delegate GSS credentials */
48
	int     gss_deleg_creds;	/* Delegate GSS credentials */
49
	int     u2f_authentication;
49
	int     password_authentication;	/* Try password
50
	int     password_authentication;	/* Try password
50
						 * authentication. */
51
						 * authentication. */
51
	int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
52
	int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
52
	char	*kbd_interactive_devices; /* Keyboard-interactive auth devices. */
53
	char	*kbd_interactive_devices; /* Keyboard-interactive auth devices. */
54
	char    *u2f_mode; /* mode (registration or authentication) for U2F auth. */
53
	int     batch_mode;	/* Batch mode: do not ask for passwords. */
55
	int     batch_mode;	/* Batch mode: do not ask for passwords. */
54
	int     check_host_ip;	/* Also keep track of keys for IP address */
56
	int     check_host_ip;	/* Also keep track of keys for IP address */
55
	int     strict_host_key_checking;	/* Strict host key checking. */
57
	int     strict_host_key_checking;	/* Strict host key checking. */
(-)a/servconf.c (+20 lines)
Lines 117-122 initialize_server_options(ServerOptions *options) Link Here
117
	options->kerberos_ticket_cleanup = -1;
117
	options->kerberos_ticket_cleanup = -1;
118
	options->kerberos_get_afs_token = -1;
118
	options->kerberos_get_afs_token = -1;
119
	options->gss_authentication=-1;
119
	options->gss_authentication=-1;
120
	options->u2f_authentication = -1;
120
	options->gss_cleanup_creds = -1;
121
	options->gss_cleanup_creds = -1;
121
	options->gss_strict_acceptor = -1;
122
	options->gss_strict_acceptor = -1;
122
	options->password_authentication = -1;
123
	options->password_authentication = -1;
Lines 273-278 fill_default_server_options(ServerOptions *options) Link Here
273
		options->kerberos_get_afs_token = 0;
274
		options->kerberos_get_afs_token = 0;
274
	if (options->gss_authentication == -1)
275
	if (options->gss_authentication == -1)
275
		options->gss_authentication = 0;
276
		options->gss_authentication = 0;
277
	// U2F authentication is disabled by default. On its own, it does not
278
	// provide adequate security, and it should be used as a second factor in
279
	// combination with publickey, for example.
280
	if (options->u2f_authentication == -1)
281
		options->u2f_authentication = 0;
276
	if (options->gss_cleanup_creds == -1)
282
	if (options->gss_cleanup_creds == -1)
277
		options->gss_cleanup_creds = 1;
283
		options->gss_cleanup_creds = 1;
278
	if (options->gss_strict_acceptor == -1)
284
	if (options->gss_strict_acceptor == -1)
Lines 412-417 typedef enum { Link Here
412
	sHostKeyAlgorithms,
418
	sHostKeyAlgorithms,
413
	sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
419
	sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
414
	sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
420
	sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
421
	sU2FAuthentication,
415
	sAcceptEnv, sPermitTunnel,
422
	sAcceptEnv, sPermitTunnel,
416
	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
423
	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
417
	sUsePrivilegeSeparation, sAllowAgentForwarding,
424
	sUsePrivilegeSeparation, sAllowAgentForwarding,
Lines 491-496 static struct { Link Here
491
	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
498
	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
492
	{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
499
	{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
493
#endif
500
#endif
501
#ifdef U2F
502
	{ "u2fauthentication", sU2FAuthentication, SSHCFG_ALL },
503
#else
504
	{ "u2fauthentication", sUnsupported, SSHCFG_ALL },
505
#endif
494
	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
506
	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
495
	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
507
	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
496
	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
508
	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
Lines 1239-1244 process_server_config_line(ServerOptions *options, char *line, Link Here
1239
		intptr = &options->gss_strict_acceptor;
1251
		intptr = &options->gss_strict_acceptor;
1240
		goto parse_flag;
1252
		goto parse_flag;
1241
1253
1254
	case sU2FAuthentication:
1255
		intptr = &options->u2f_authentication;
1256
		goto parse_flag;
1257
1242
	case sPasswordAuthentication:
1258
	case sPasswordAuthentication:
1243
		intptr = &options->password_authentication;
1259
		intptr = &options->password_authentication;
1244
		goto parse_flag;
1260
		goto parse_flag;
Lines 1972-1977 copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) Link Here
1972
1988
1973
	M_CP_INTOPT(password_authentication);
1989
	M_CP_INTOPT(password_authentication);
1974
	M_CP_INTOPT(gss_authentication);
1990
	M_CP_INTOPT(gss_authentication);
1991
	M_CP_INTOPT(u2f_authentication);
1975
	M_CP_INTOPT(rsa_authentication);
1992
	M_CP_INTOPT(rsa_authentication);
1976
	M_CP_INTOPT(pubkey_authentication);
1993
	M_CP_INTOPT(pubkey_authentication);
1977
	M_CP_INTOPT(kerberos_authentication);
1994
	M_CP_INTOPT(kerberos_authentication);
Lines 2248-2253 dump_config(ServerOptions *o) Link Here
2248
	dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
2265
	dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
2249
	dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
2266
	dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
2250
#endif
2267
#endif
2268
#ifdef U2F
2269
	dump_cfg_fmtint(sU2FAuthentication, o->u2f_authentication);
2270
#endif
2251
	dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
2271
	dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
2252
	dump_cfg_fmtint(sKbdInteractiveAuthentication,
2272
	dump_cfg_fmtint(sKbdInteractiveAuthentication,
2253
	    o->kbd_interactive_authentication);
2273
	    o->kbd_interactive_authentication);
(-)a/servconf.h (+1 lines)
Lines 124-129 typedef struct { Link Here
124
						 * authentication. */
124
						 * authentication. */
125
	int     kbd_interactive_authentication;	/* If true, permit */
125
	int     kbd_interactive_authentication;	/* If true, permit */
126
	int     challenge_response_authentication;
126
	int     challenge_response_authentication;
127
	int     u2f_authentication;
127
	int     permit_empty_passwd;	/* If false, do not permit empty
128
	int     permit_empty_passwd;	/* If false, do not permit empty
128
					 * passwords. */
129
					 * passwords. */
129
	int     permit_user_env;	/* If true, read ~/.ssh/environment */
130
	int     permit_user_env;	/* If true, read ~/.ssh/environment */
(-)a/ssh.1 (+2 lines)
Lines 536-541 For full details of the options listed below, and their possible values, see Link Here
536
.It TCPKeepAlive
536
.It TCPKeepAlive
537
.It Tunnel
537
.It Tunnel
538
.It TunnelDevice
538
.It TunnelDevice
539
.It U2FAuthentication
540
.It U2FMode
539
.It UpdateHostKeys
541
.It UpdateHostKeys
540
.It UsePrivilegedPort
542
.It UsePrivilegedPort
541
.It User
543
.It User
(-)a/ssh.c (+11 lines)
Lines 74-83 Link Here
74
#ifdef WITH_OPENSSL
74
#ifdef WITH_OPENSSL
75
#include <openssl/evp.h>
75
#include <openssl/evp.h>
76
#include <openssl/err.h>
76
#include <openssl/err.h>
77
#include <openssl/ssl.h>
77
#endif
78
#endif
78
#include "openbsd-compat/openssl-compat.h"
79
#include "openbsd-compat/openssl-compat.h"
79
#include "openbsd-compat/sys-queue.h"
80
#include "openbsd-compat/sys-queue.h"
80
81
82
#ifdef U2F
83
#include <u2f-host.h>
84
#endif
85
81
#include "xmalloc.h"
86
#include "xmalloc.h"
82
#include "ssh.h"
87
#include "ssh.h"
83
#include "ssh1.h"
88
#include "ssh1.h"
Lines 942-947 main(int ac, char **av) Link Here
942
#ifdef WITH_OPENSSL
947
#ifdef WITH_OPENSSL
943
	OpenSSL_add_all_algorithms();
948
	OpenSSL_add_all_algorithms();
944
	ERR_load_crypto_strings();
949
	ERR_load_crypto_strings();
950
	SSL_load_error_strings();
951
#endif
952
953
#ifdef U2F
954
	if (u2fh_global_init(0) != U2FH_OK)
955
		fatal("u2fh_global_init() failed");
945
#endif
956
#endif
946
957
947
	/* Initialize the command to execute on remote host. */
958
	/* Initialize the command to execute on remote host. */
(-)a/ssh_config.5 (+10 lines)
Lines 1600-1605 Presently, only Link Here
1600
from OpenSSH 6.8 and greater support the
1600
from OpenSSH 6.8 and greater support the
1601
.Dq hostkeys@openssh.com
1601
.Dq hostkeys@openssh.com
1602
protocol extension used to inform the client of all the server's hostkeys.
1602
protocol extension used to inform the client of all the server's hostkeys.
1603
.It Cm U2FAuthentication
1604
Specifies whether user authentication based on U2F (Universal Second Factor) is allowed. The default is
1605
.Dq yes .
1606
.It Cm U2FMode
1607
Specifies which mode the U2F authentication method should use. Can be either
1608
.Dq authentication
1609
or
1610
.Dq registration .
1611
The default is
1612
.Dq authentication .
1603
.It Cm UsePrivilegedPort
1613
.It Cm UsePrivilegedPort
1604
Specifies whether to use a privileged port for outgoing connections.
1614
Specifies whether to use a privileged port for outgoing connections.
1605
The argument must be
1615
The argument must be
(-)a/sshconnect.c (-1 / +1 lines)
Lines 1353-1359 ssh_login(Sensitive *sensitive, const char *orighost, Link Here
1353
	debug("Authenticating to %s:%d as '%s'", host, port, server_user);
1353
	debug("Authenticating to %s:%d as '%s'", host, port, server_user);
1354
	if (compat20) {
1354
	if (compat20) {
1355
		ssh_kex2(host, hostaddr, port);
1355
		ssh_kex2(host, hostaddr, port);
1356
		ssh_userauth2(local_user, server_user, host, sensitive);
1356
		ssh_userauth2(local_user, server_user, host, port, sensitive);
1357
	} else {
1357
	} else {
1358
#ifdef WITH_SSH1
1358
#ifdef WITH_SSH1
1359
		ssh_kex(host, hostaddr);
1359
		ssh_kex(host, hostaddr);
(-)a/sshconnect.h (-1 / +1 lines)
Lines 50-56 void ssh_kex(char *, struct sockaddr *); Link Here
50
void	 ssh_kex2(char *, struct sockaddr *, u_short);
50
void	 ssh_kex2(char *, struct sockaddr *, u_short);
51
51
52
void	 ssh_userauth1(const char *, const char *, char *, Sensitive *);
52
void	 ssh_userauth1(const char *, const char *, char *, Sensitive *);
53
void	 ssh_userauth2(const char *, const char *, char *, Sensitive *);
53
void	 ssh_userauth2(const char *, const char *, char *, u_short, Sensitive *);
54
54
55
void	 ssh_put_password(char *);
55
void	 ssh_put_password(char *);
56
int	 ssh_local_cmd(const char *);
56
int	 ssh_local_cmd(const char *);
(-)a/sshconnect2.c (-1 / +177 lines)
Lines 2-7 Link Here
2
/*
2
/*
3
 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
3
 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
4
 * Copyright (c) 2008 Damien Miller.  All rights reserved.
4
 * Copyright (c) 2008 Damien Miller.  All rights reserved.
5
 * Copyright (c) 2014 Google Inc.  All rights reserved.
5
 *
6
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * modification, are permitted provided that the following conditions
Lines 30-35 Link Here
30
#include <sys/socket.h>
31
#include <sys/socket.h>
31
#include <sys/wait.h>
32
#include <sys/wait.h>
32
#include <sys/stat.h>
33
#include <sys/stat.h>
34
#include <time.h>
33
35
34
#include <errno.h>
36
#include <errno.h>
35
#include <fcntl.h>
37
#include <fcntl.h>
Lines 44-49 Link Here
44
#include <vis.h>
46
#include <vis.h>
45
#endif
47
#endif
46
48
49
#ifdef U2F
50
#include <u2f-host.h>
51
#endif
52
47
#include "openbsd-compat/sys-queue.h"
53
#include "openbsd-compat/sys-queue.h"
48
54
49
#include "xmalloc.h"
55
#include "xmalloc.h"
Lines 71-76 Link Here
71
#include "uidswap.h"
77
#include "uidswap.h"
72
#include "hostfile.h"
78
#include "hostfile.h"
73
#include "ssherr.h"
79
#include "ssherr.h"
80
#include "u2f.h"
74
81
75
#ifdef GSSAPI
82
#ifdef GSSAPI
76
#include "ssh-gss.h"
83
#include "ssh-gss.h"
Lines 258-263 struct cauthctxt { Link Here
258
	const char *server_user;
265
	const char *server_user;
259
	const char *local_user;
266
	const char *local_user;
260
	const char *host;
267
	const char *host;
268
	char *host_port;
261
	const char *service;
269
	const char *service;
262
	struct cauthmethod *method;
270
	struct cauthmethod *method;
263
	sig_atomic_t success;
271
	sig_atomic_t success;
Lines 308-313 int input_gssapi_error(int, u_int32_t, void *); Link Here
308
int	input_gssapi_errtok(int, u_int32_t, void *);
316
int	input_gssapi_errtok(int, u_int32_t, void *);
309
#endif
317
#endif
310
318
319
#ifdef U2F
320
int userauth_u2f(Authctxt *authctxt);
321
int input_userauth_u2f_authenticate(int type, u_int32_t seq, void *ctxt);
322
int input_userauth_u2f_register(int type, u_int32_t seq, void *ctxt);
323
int input_userauth_u2f_register_response(int type, u_int32_t seq, void *ctxt);
324
#endif
325
311
void	userauth(Authctxt *, char *);
326
void	userauth(Authctxt *, char *);
312
327
313
static int sign_and_send_pubkey(Authctxt *, Identity *);
328
static int sign_and_send_pubkey(Authctxt *, Identity *);
Lines 320-325 static Authmethod *authmethod_lookup(const char *name); Link Here
320
static char *authmethods_get(void);
335
static char *authmethods_get(void);
321
336
322
Authmethod authmethods[] = {
337
Authmethod authmethods[] = {
338
	// U2F needs to be the first authentication method, so that we use it once
339
	// the server allows it. This enables server configurations containing e.g.:
340
	// AuthenticationMethods password,u2f pubkey,u2f
341
#ifdef U2F
342
    {"u2f",
343
        userauth_u2f,
344
        NULL,
345
        &options.u2f_authentication,
346
        NULL},
347
#endif
323
#ifdef GSSAPI
348
#ifdef GSSAPI
324
	{"gssapi-with-mic",
349
	{"gssapi-with-mic",
325
		userauth_gssapi,
350
		userauth_gssapi,
Lines 357-363 Authmethod authmethods[] = { Link Here
357
382
358
void
383
void
359
ssh_userauth2(const char *local_user, const char *server_user, char *host,
384
ssh_userauth2(const char *local_user, const char *server_user, char *host,
360
    Sensitive *sensitive)
385
    u_short port, Sensitive *sensitive)
361
{
386
{
362
	Authctxt authctxt;
387
	Authctxt authctxt;
363
	int type;
388
	int type;
Lines 392-397 ssh_userauth2(const char *local_user, const char *server_user, char *host, Link Here
392
	authctxt.server_user = server_user;
417
	authctxt.server_user = server_user;
393
	authctxt.local_user = local_user;
418
	authctxt.local_user = local_user;
394
	authctxt.host = host;
419
	authctxt.host = host;
420
	get_hostfile_hostname_ipaddr(host, NULL, port, &authctxt.host_port, NULL);
395
	authctxt.service = "ssh-connection";		/* service name */
421
	authctxt.service = "ssh-connection";		/* service name */
396
	authctxt.success = 0;
422
	authctxt.success = 0;
397
	authctxt.method = authmethod_lookup("none");
423
	authctxt.method = authmethod_lookup("none");
Lines 852-857 input_gssapi_error(int type, u_int32_t plen, void *ctxt) Link Here
852
}
878
}
853
#endif /* GSSAPI */
879
#endif /* GSSAPI */
854
880
881
#ifdef U2F
882
int
883
userauth_u2f(Authctxt *authctxt)
884
{
885
	// first step: we dont send anything, but install a custom dispatcher.
886
	debug("sshconnect2:userauth_u2f");
887
888
	// For U2F_MODE_REGISTRATION, this code path will return 0, meaning the
889
	// authentication method will not be retried. If we did not do that, we
890
	// would loop endlessly.
891
	if (authctxt->info_req_seen) {
892
		dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
893
		return 0;
894
	}
895
896
	packet_start(SSH2_MSG_USERAUTH_REQUEST);
897
	packet_put_cstring(authctxt->server_user);
898
	packet_put_cstring(authctxt->service);
899
	packet_put_cstring(authctxt->method->name);
900
	if (options.u2f_mode == NULL || strcasecmp(options.u2f_mode, "authentication") == 0) {
901
		packet_put_int(U2F_MODE_AUTHENTICATION);
902
		dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_u2f_authenticate);
903
	} else if (options.u2f_mode != NULL && strcasecmp(options.u2f_mode, "registration") == 0) {
904
		packet_put_int(U2F_MODE_REGISTRATION);
905
		dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_u2f_register);
906
	} else {
907
		fatal("Invalid U2F mode (\"%s\"), expected \"authentication\" or \"registration\".",
908
				options.u2f_mode);
909
	}
910
	packet_send();
911
912
	return 1;
913
}
914
915
static void
916
wait_for_u2f_devices(u2fh_devs *devs)
917
{
918
	time_t looking;
919
	int attempts = 0;
920
	u2fh_rc rc;
921
922
	// The U2F implementation considerations recommend 3 seconds as the time a
923
	// client implementation should grant for security keys to respond. We wait
924
	// 3 times that for the user to insert a security key (and it being
925
	// detected).
926
	looking = monotime();
927
	do {
928
		if ((rc = u2fh_devs_discover(devs, NULL)) != U2FH_OK && attempts++ == 0)
929
			error("Please insert and touch your U2F security key.");
930
		if (rc != U2FH_OK)
931
			usleep(50);
932
	} while (rc != U2FH_OK && (monotime() - looking) <= 9);
933
	if (rc != U2FH_OK)
934
		fatal("No U2F devices found (%s). Did you plug in your U2F security key?",
935
				u2fh_strerror(rc));
936
937
	if (attempts == 0)
938
		error("Please touch your U2F security key now.");
939
}
940
941
int
942
input_userauth_u2f_register(int type, u_int32_t seq, void *ctxt)
943
{
944
	Authctxt *authctxt = ctxt;
945
	char *challenge, *response;
946
	u2fh_devs *devs = NULL;
947
	u2fh_rc rc;
948
	const char *origin = authctxt->host_port;
949
950
	if (authctxt == NULL)
951
		fatal("input_userauth_u2f_register: no authentication context");
952
953
	authctxt->info_req_seen = 1;
954
955
	challenge = packet_get_string(NULL);
956
	packet_check_eom();
957
958
	if ((rc = u2fh_devs_init(&devs)) != U2FH_OK)
959
		fatal("u2fh_devs_init() failed: %s", u2fh_strerror(rc));
960
961
	wait_for_u2f_devices(devs);
962
963
	if ((rc = u2fh_register(devs, challenge, origin, &response, U2FH_REQUEST_USER_PRESENCE)) != U2FH_OK)
964
		fatal("u2fh_register() failed: %s", u2fh_strerror(rc));
965
966
	u2fh_devs_done(devs);
967
968
	packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
969
	packet_put_cstring(response);
970
	packet_send();
971
972
	free(response);
973
	dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
974
	dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_u2f_register_response);
975
	return 0;
976
}
977
978
int
979
input_userauth_u2f_register_response(int type, u_int32_t seq, void *ctxt)
980
{
981
	char *response = packet_get_string(NULL);
982
	printf("%s\n", response);
983
	fflush(stdout);
984
	return 0;
985
}
986
987
int
988
input_userauth_u2f_authenticate(int type, u_int32_t seq, void *ctxt)
989
{
990
	Authctxt *authctxt = ctxt;
991
	char *challenge, *response;
992
	u2fh_devs *devs = NULL;
993
	u2fh_rc rc;
994
	const char *origin = authctxt->host_port;
995
996
	if (authctxt == NULL)
997
		fatal("input_userauth_u2f_authenticate: no authentication context");
998
999
	authctxt->info_req_seen = 1;
1000
1001
	challenge = packet_get_string(NULL);
1002
	packet_check_eom();
1003
1004
	debug("Starting U2F authentication for origin \"%s\".", origin);
1005
1006
	if ((rc = u2fh_devs_init(&devs)) != U2FH_OK)
1007
		fatal("u2fh_devs_init() failed: %s", u2fh_strerror(rc));
1008
1009
	wait_for_u2f_devices(devs);
1010
1011
	// TODO: refactor with input_userauth_u2f_register(), the following line is the only one that is different :)
1012
	if ((rc = u2fh_authenticate(devs, challenge, origin, &response, U2FH_REQUEST_USER_PRESENCE)) != U2FH_OK)
1013
		fatal("u2fh_authenticate() failed: %s", u2fh_strerror(rc));
1014
1015
	u2fh_devs_done(devs);
1016
1017
	packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
1018
	packet_put_cstring(response);
1019
	packet_send();
1020
1021
	free(response);
1022
	return 0;
1023
1024
	// We intentionally do not set SSH2_MSG_USERAUTH_INFO_REQUEST to NULL,
1025
	// because the server might send us more challenges (in case more than one
1026
	// U2F security key is in the authorized_keys).
1027
}
1028
1029
#endif /* U2F */
1030
855
int
1031
int
856
userauth_none(Authctxt *authctxt)
1032
userauth_none(Authctxt *authctxt)
857
{
1033
{
(-)a/sshd.c (+2 lines)
Lines 77-82 Link Here
77
#include <openssl/dh.h>
77
#include <openssl/dh.h>
78
#include <openssl/bn.h>
78
#include <openssl/bn.h>
79
#include <openssl/rand.h>
79
#include <openssl/rand.h>
80
#include <openssl/ssl.h>
80
#include "openbsd-compat/openssl-compat.h"
81
#include "openbsd-compat/openssl-compat.h"
81
#endif
82
#endif
82
83
Lines 1629-1634 main(int ac, char **av) Link Here
1629
1630
1630
#ifdef WITH_OPENSSL
1631
#ifdef WITH_OPENSSL
1631
	OpenSSL_add_all_algorithms();
1632
	OpenSSL_add_all_algorithms();
1633
	SSL_load_error_strings();
1632
#endif
1634
#endif
1633
1635
1634
	/* If requested, redirect the logs to the specified logfile. */
1636
	/* If requested, redirect the logs to the specified logfile. */
(-)a/sshd_config.5 (+19 lines)
Lines 1518-1523 for authentication using Link Here
1518
.Cm TrustedUserCAKeys .
1518
.Cm TrustedUserCAKeys .
1519
For more details on certificates, see the CERTIFICATES section in
1519
For more details on certificates, see the CERTIFICATES section in
1520
.Xr ssh-keygen 1 .
1520
.Xr ssh-keygen 1 .
1521
.It Cm U2FAuthentication
1522
Specifies whether user authentication based on U2F (Universal Second Factor) is allowed. The default is
1523
.Dq no .
1524
Note that U2F authentication should never be used alone, so specify for example:
1525
.Bd -literal -offset indent
1526
U2FAuthentication yes
1527
AuthenticationMethods pubkey,u2f
1528
.Ed
1529
.Pp
1530
That way, pubkey authentication will be performed and U2F will be required
1531
after pubkey authentication was successful. In case the user in question does
1532
not have any ssh-u2f lines in their authorized_keys file, the u2f
1533
authentication method will just return success.
1534
.Pp
1535
In order to register a U2F security key, enable this option as outlined above.
1536
Then, run
1537
.Dq ssh -o U2FMode=registration server.example.net
1538
in order to obtain a ssh-u2f line which you can then append to your
1539
authorized_keys.
1521
.It Cm UseDNS
1540
.It Cm UseDNS
1522
Specifies whether
1541
Specifies whether
1523
.Xr sshd 8
1542
.Xr sshd 8
(-)a/sshkey.c (+83 lines)
Lines 3-8 Link Here
3
 * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
3
 * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
4
 * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
4
 * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
5
 * Copyright (c) 2010,2011 Damien Miller.  All rights reserved.
5
 * Copyright (c) 2010,2011 Damien Miller.  All rights reserved.
6
 * Copyright (c) 2014 Google Inc.  All rights reserved.
6
 *
7
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * modification, are permitted provided that the following conditions
Lines 58-63 Link Here
58
#define SSHKEY_INTERNAL
59
#define SSHKEY_INTERNAL
59
#include "sshkey.h"
60
#include "sshkey.h"
60
#include "match.h"
61
#include "match.h"
62
#include "key.h"
63
#include "hostfile.h"
64
#include "auth.h"
65
#include "u2f.h"
61
66
62
/* openssh private key file format */
67
/* openssh private key file format */
63
#define MARK_BEGIN		"-----BEGIN OPENSSH PRIVATE KEY-----\n"
68
#define MARK_BEGIN		"-----BEGIN OPENSSH PRIVATE KEY-----\n"
Lines 112-117 static const struct keytype keytypes[] = { Link Here
112
#  endif /* OPENSSL_HAS_NISTP521 */
117
#  endif /* OPENSSL_HAS_NISTP521 */
113
# endif /* OPENSSL_HAS_ECC */
118
# endif /* OPENSSL_HAS_ECC */
114
#endif /* WITH_OPENSSL */
119
#endif /* WITH_OPENSSL */
120
	{ "ssh-u2f", "U2F", KEY_U2F, 0, 0 },
115
	{ NULL, NULL, -1, -1, 0 }
121
	{ NULL, NULL, -1, -1, 0 }
116
};
122
};
117
123
Lines 513-518 sshkey_new(int type) Link Here
513
		break;
519
		break;
514
	case KEY_UNSPEC:
520
	case KEY_UNSPEC:
515
		break;
521
		break;
522
	case KEY_U2F:
523
		break;
516
	default:
524
	default:
517
		free(k);
525
		free(k);
518
		return NULL;
526
		return NULL;
Lines 793-798 to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain) Link Here
793
		    key->ed25519_pk, ED25519_PK_SZ)) != 0)
801
		    key->ed25519_pk, ED25519_PK_SZ)) != 0)
794
			return ret;
802
			return ret;
795
		break;
803
		break;
804
#ifdef U2F
805
	case KEY_U2F:
806
		if (key->u2f_pubkey == NULL)
807
			return SSH_ERR_INVALID_ARGUMENT;
808
		if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
809
		    (ret = sshbuf_put_string(b, key->u2f_pubkey, U2F_PUBKEY_LEN)) != 0 ||
810
		    (ret = sshbuf_put_string(b,
811
				key->u2f_key_handle, key->u2f_key_handle_len)) != 0)
812
			return ret;
813
		break;
814
#endif
796
	default:
815
	default:
797
		return SSH_ERR_KEY_TYPE_UNKNOWN;
816
		return SSH_ERR_KEY_TYPE_UNKNOWN;
798
	}
817
	}
Lines 1262-1267 sshkey_read(struct sshkey *ret, char **cpp) Link Here
1262
		retval = 0;
1281
		retval = 0;
1263
#endif /* WITH_SSH1 */
1282
#endif /* WITH_SSH1 */
1264
		break;
1283
		break;
1284
	case KEY_U2F:
1285
#ifdef U2F
1286
		space = strchr(cp, ' ');
1287
		if (space == NULL)
1288
			return SSH_ERR_INVALID_FORMAT;
1289
		*space = '\0';
1290
		type = sshkey_type_from_name(cp);
1291
		if (type == KEY_UNSPEC)
1292
			return SSH_ERR_INVALID_FORMAT;
1293
		cp = space+1;
1294
		if (*cp == '\0')
1295
			return SSH_ERR_INVALID_FORMAT;
1296
		if (ret->type == KEY_UNSPEC) {
1297
			ret->type = type;
1298
		} else if (ret->type != type)
1299
			return SSH_ERR_KEY_TYPE_MISMATCH;
1300
		cp = space+1;
1301
		/* trim comment */
1302
		space = strchr(cp, ' ');
1303
		if (space)
1304
			*space = '\0';
1305
		blob = sshbuf_new();
1306
		if ((r = sshbuf_b64tod(blob, cp)) != 0) {
1307
			sshbuf_free(blob);
1308
			return r;
1309
		}
1310
		// TODO: why do we _need_ to use malloc here? xmalloc gives memory that crashes!
1311
		ret->u2f_pubkey = malloc(U2F_PUBKEY_LEN);
1312
		memcpy(ret->u2f_pubkey, sshbuf_ptr(blob), U2F_PUBKEY_LEN);
1313
		ret->u2f_key_handle_len = sshbuf_len(blob) - U2F_PUBKEY_LEN;
1314
		ret->u2f_key_handle = malloc(ret->u2f_key_handle_len);
1315
		memcpy(ret->u2f_key_handle, sshbuf_ptr(blob) + U2F_PUBKEY_LEN, ret->u2f_key_handle_len);
1316
		sshbuf_free(blob);
1317
		retval = (r >= 0) ? 0 : 1;
1318
#endif /* U2F */
1319
		break;
1265
	case KEY_UNSPEC:
1320
	case KEY_UNSPEC:
1266
	case KEY_RSA:
1321
	case KEY_RSA:
1267
	case KEY_DSA:
1322
	case KEY_DSA:
Lines 1965-1970 sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, Link Here
1965
#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
2020
#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
1966
	EC_POINT *q = NULL;
2021
	EC_POINT *q = NULL;
1967
#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
2022
#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
2023
#ifdef U2F
2024
	u_char *khandle = NULL;
2025
#endif
1968
2026
1969
#ifdef DEBUG_PK /* XXX */
2027
#ifdef DEBUG_PK /* XXX */
1970
	sshbuf_dump(b, stderr);
2028
	sshbuf_dump(b, stderr);
Lines 2104-2109 sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, Link Here
2104
		key->ed25519_pk = pk;
2162
		key->ed25519_pk = pk;
2105
		pk = NULL;
2163
		pk = NULL;
2106
		break;
2164
		break;
2165
#ifdef U2F
2166
	case KEY_U2F:
2167
		if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2168
			goto out;
2169
		if (len != U2F_PUBKEY_LEN) {
2170
			ret = SSH_ERR_INVALID_FORMAT;
2171
			goto out;
2172
		}
2173
		if ((ret = sshbuf_get_string(b, &khandle, &len)) != 0)
2174
			goto out;
2175
		if ((key = sshkey_new(type)) == NULL) {
2176
			ret = SSH_ERR_ALLOC_FAIL;
2177
			goto out;
2178
		}
2179
		key->u2f_pubkey = pk;
2180
		key->u2f_key_handle_len = len;
2181
		key->u2f_key_handle = khandle;
2182
		pk = NULL;
2183
		khandle = NULL;
2184
		ret = SSH_ERR_ALLOC_FAIL;
2185
		break;
2186
#endif
2107
	case KEY_UNSPEC:
2187
	case KEY_UNSPEC:
2108
		if ((key = sshkey_new(type)) == NULL) {
2188
		if ((key = sshkey_new(type)) == NULL) {
2109
			ret = SSH_ERR_ALLOC_FAIL;
2189
			ret = SSH_ERR_ALLOC_FAIL;
Lines 2136-2141 sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, Link Here
2136
	if (q != NULL)
2216
	if (q != NULL)
2137
		EC_POINT_free(q);
2217
		EC_POINT_free(q);
2138
#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
2218
#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
2219
#ifdef U2F
2220
	free(khandle);
2221
#endif
2139
	return ret;
2222
	return ret;
2140
}
2223
}
2141
2224
(-)a/sshkey.h (-1 / +6 lines)
Lines 62-67 enum sshkey_types { Link Here
62
	KEY_DSA_CERT,
62
	KEY_DSA_CERT,
63
	KEY_ECDSA_CERT,
63
	KEY_ECDSA_CERT,
64
	KEY_ED25519_CERT,
64
	KEY_ED25519_CERT,
65
	KEY_U2F,
65
	KEY_UNSPEC
66
	KEY_UNSPEC
66
};
67
};
67
68
Lines 106-111 struct sshkey { Link Here
106
	u_char	*ed25519_sk;
107
	u_char	*ed25519_sk;
107
	u_char	*ed25519_pk;
108
	u_char	*ed25519_pk;
108
	struct sshkey_cert *cert;
109
	struct sshkey_cert *cert;
110
#ifdef U2F
111
	u_char *u2f_pubkey;
112
	u_int   u2f_key_handle_len;
113
	u_char *u2f_key_handle;
114
#endif
109
};
115
};
110
116
111
#define	ED25519_SK_SZ	crypto_sign_ed25519_SECRETKEYBYTES
117
#define	ED25519_SK_SZ	crypto_sign_ed25519_SECRETKEYBYTES
112
- 

Return to bug 2319