Skip to content

Commit 9576726

Browse files
committed
upstream commit
refactor canohost.c: move functions that cache results closer to the places that use them (authn and session code). After this, no state is cached in canohost.c feedback and ok markus@ Upstream-ID: 5f2e4df88d4803fc8ec59ec53629105e23ce625e
1 parent af0bb38 commit 9576726

21 files changed

+372
-373
lines changed

auth-options.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: auth-options.c,v 1.70 2015/12/10 17:08:40 mmcc Exp $ */
1+
/* $OpenBSD: auth-options.c,v 1.71 2016/03/07 19:02:43 djm Exp $ */
22
/*
33
* Author: Tatu Ylonen <[email protected]>
44
* Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
@@ -29,6 +29,7 @@
2929
#include "ssherr.h"
3030
#include "log.h"
3131
#include "canohost.h"
32+
#include "packet.h"
3233
#include "sshbuf.h"
3334
#include "misc.h"
3435
#include "channels.h"
@@ -120,6 +121,7 @@ match_flag(const char *opt, int allow_negate, char **optsp, const char *msg)
120121
int
121122
auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
122123
{
124+
struct ssh *ssh = active_state; /* XXX */
123125
const char *cp;
124126
int i, r;
125127

@@ -273,9 +275,9 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
273275
}
274276
cp = "from=\"";
275277
if (strncasecmp(opts, cp, strlen(cp)) == 0) {
276-
const char *remote_ip = get_remote_ipaddr();
277-
const char *remote_host = get_canonical_hostname(
278-
options.use_dns);
278+
const char *remote_ip = ssh_remote_ipaddr(ssh);
279+
const char *remote_host = auth_get_canonical_hostname(
280+
ssh, options.use_dns);
279281
char *patterns = xmalloc(strlen(opts) + 1);
280282

281283
opts += strlen(cp);
@@ -457,6 +459,7 @@ parse_option_list(struct sshbuf *oblob, struct passwd *pw,
457459
char **cert_forced_command,
458460
int *cert_source_address_done)
459461
{
462+
struct ssh *ssh = active_state; /* XXX */
460463
char *command, *allowed;
461464
const char *remote_ip;
462465
char *name = NULL;
@@ -530,7 +533,7 @@ parse_option_list(struct sshbuf *oblob, struct passwd *pw,
530533
free(allowed);
531534
goto out;
532535
}
533-
remote_ip = get_remote_ipaddr();
536+
remote_ip = ssh_remote_ipaddr(ssh);
534537
result = addr_match_cidr_list(remote_ip,
535538
allowed);
536539
free(allowed);

auth-rh-rsa.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
1+
/* $OpenBSD: auth-rh-rsa.c,v 1.45 2016/03/07 19:02:43 djm Exp $ */
22
/*
33
* Author: Tatu Ylonen <[email protected]>
44
* Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
@@ -42,8 +42,8 @@
4242
extern ServerOptions options;
4343

4444
int
45-
auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
46-
Key *client_host_key)
45+
auth_rhosts_rsa_key_allowed(struct passwd *pw, const char *cuser,
46+
const char *chost, Key *client_host_key)
4747
{
4848
HostStatus host_status;
4949

@@ -68,7 +68,8 @@ auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
6868
int
6969
auth_rhosts_rsa(Authctxt *authctxt, char *cuser, Key *client_host_key)
7070
{
71-
char *chost;
71+
struct ssh *ssh = active_state; /* XXX */
72+
const char *chost;
7273
struct passwd *pw = authctxt->pw;
7374

7475
debug("Trying rhosts with RSA host authentication for client user %.100s",
@@ -78,7 +79,7 @@ auth_rhosts_rsa(Authctxt *authctxt, char *cuser, Key *client_host_key)
7879
client_host_key->rsa == NULL)
7980
return 0;
8081

81-
chost = (char *)get_canonical_hostname(options.use_dns);
82+
chost = auth_get_canonical_hostname(ssh, options.use_dns);
8283
debug("Rhosts RSA authentication: canonical host %.900s", chost);
8384

8485
if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) {

auth-rhosts.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: auth-rhosts.c,v 1.46 2014/12/23 22:42:48 djm Exp $ */
1+
/* $OpenBSD: auth-rhosts.c,v 1.47 2016/03/07 19:02:43 djm Exp $ */
22
/*
33
* Author: Tatu Ylonen <[email protected]>
44
* Copyright (c) 1995 Tatu Ylonen <[email protected]>, Espoo, Finland
@@ -30,14 +30,15 @@
3030
#include <unistd.h>
3131

3232
#include "packet.h"
33-
#include "buffer.h"
3433
#include "uidswap.h"
3534
#include "pathnames.h"
3635
#include "log.h"
3736
#include "misc.h"
37+
#include "buffer.h" /* XXX */
38+
#include "key.h" /* XXX */
3839
#include "servconf.h"
3940
#include "canohost.h"
40-
#include "key.h"
41+
#include "sshkey.h"
4142
#include "hostfile.h"
4243
#include "auth.h"
4344

@@ -189,10 +190,11 @@ check_rhosts_file(const char *filename, const char *hostname,
189190
int
190191
auth_rhosts(struct passwd *pw, const char *client_user)
191192
{
193+
struct ssh *ssh = active_state; /* XXX */
192194
const char *hostname, *ipaddr;
193195

194-
hostname = get_canonical_hostname(options.use_dns);
195-
ipaddr = get_remote_ipaddr();
196+
hostname = auth_get_canonical_hostname(ssh, options.use_dns);
197+
ipaddr = ssh_remote_ipaddr(ssh);
196198
return auth_rhosts2(pw, client_user, hostname, ipaddr);
197199
}
198200

auth.c

Lines changed: 135 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: auth.c,v 1.113 2015/08/21 03:42:19 djm Exp $ */
1+
/* $OpenBSD: auth.c,v 1.114 2016/03/07 19:02:43 djm Exp $ */
22
/*
33
* Copyright (c) 2000 Markus Friedl. All rights reserved.
44
*
@@ -27,6 +27,7 @@
2727

2828
#include <sys/types.h>
2929
#include <sys/stat.h>
30+
#include <sys/socket.h>
3031

3132
#include <netinet/in.h>
3233

@@ -50,6 +51,7 @@
5051
#include <string.h>
5152
#include <unistd.h>
5253
#include <limits.h>
54+
#include <netdb.h>
5355

5456
#include "xmalloc.h"
5557
#include "match.h"
@@ -97,6 +99,7 @@ int auth_debug_init;
9799
int
98100
allowed_user(struct passwd * pw)
99101
{
102+
struct ssh *ssh = active_state; /* XXX */
100103
struct stat st;
101104
const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
102105
u_int i;
@@ -182,8 +185,8 @@ allowed_user(struct passwd * pw)
182185

183186
if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
184187
options.num_deny_groups > 0 || options.num_allow_groups > 0) {
185-
hostname = get_canonical_hostname(options.use_dns);
186-
ipaddr = get_remote_ipaddr();
188+
hostname = auth_get_canonical_hostname(ssh, options.use_dns);
189+
ipaddr = ssh_remote_ipaddr(ssh);
187190
}
188191

189192
/* Return false if user is listed in DenyUsers */
@@ -274,6 +277,7 @@ void
274277
auth_log(Authctxt *authctxt, int authenticated, int partial,
275278
const char *method, const char *submethod)
276279
{
280+
struct ssh *ssh = active_state; /* XXX */
277281
void (*authlog) (const char *fmt,...) = verbose;
278282
char *authmsg;
279283

@@ -300,8 +304,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
300304
submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
301305
authctxt->valid ? "" : "invalid user ",
302306
authctxt->user,
303-
get_remote_ipaddr(),
304-
get_remote_port(),
307+
ssh_remote_ipaddr(ssh),
308+
ssh_remote_port(ssh),
305309
compat20 ? "ssh2" : "ssh1",
306310
authctxt->info != NULL ? ": " : "",
307311
authctxt->info != NULL ? authctxt->info : "");
@@ -331,12 +335,14 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
331335
void
332336
auth_maxtries_exceeded(Authctxt *authctxt)
333337
{
338+
struct ssh *ssh = active_state; /* XXX */
339+
334340
error("maximum authentication attempts exceeded for "
335341
"%s%.100s from %.200s port %d %s",
336342
authctxt->valid ? "" : "invalid user ",
337343
authctxt->user,
338-
get_remote_ipaddr(),
339-
get_remote_port(),
344+
ssh_remote_ipaddr(ssh),
345+
ssh_remote_port(ssh),
340346
compat20 ? "ssh2" : "ssh1");
341347
packet_disconnect("Too many authentication failures");
342348
/* NOTREACHED */
@@ -348,6 +354,8 @@ auth_maxtries_exceeded(Authctxt *authctxt)
348354
int
349355
auth_root_allowed(const char *method)
350356
{
357+
struct ssh *ssh = active_state; /* XXX */
358+
351359
switch (options.permit_root_login) {
352360
case PERMIT_YES:
353361
return 1;
@@ -364,7 +372,8 @@ auth_root_allowed(const char *method)
364372
}
365373
break;
366374
}
367-
logit("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
375+
logit("ROOT LOGIN REFUSED FROM %.200s port %d",
376+
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
368377
return 0;
369378
}
370379

@@ -604,6 +613,7 @@ auth_openprincipals(const char *file, struct passwd *pw, int strict_modes)
604613
struct passwd *
605614
getpwnamallow(const char *user)
606615
{
616+
struct ssh *ssh = active_state; /* XXX */
607617
#ifdef HAVE_LOGIN_CAP
608618
extern login_cap_t *lc;
609619
#ifdef BSD_AUTH
@@ -639,8 +649,8 @@ getpwnamallow(const char *user)
639649
}
640650
#endif
641651
if (pw == NULL) {
642-
logit("Invalid user %.100s from %.100s",
643-
user, get_remote_ipaddr());
652+
logit("Invalid user %.100s from %.100s port %d",
653+
user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
644654
#ifdef CUSTOM_FAILED_LOGIN
645655
record_failed_login(user,
646656
get_canonical_hostname(options.use_dns), "ssh");
@@ -773,3 +783,118 @@ fakepw(void)
773783

774784
return (&fake);
775785
}
786+
787+
/*
788+
* Returns the remote DNS hostname as a string. The returned string must not
789+
* be freed. NB. this will usually trigger a DNS query the first time it is
790+
* called.
791+
* This function does additional checks on the hostname to mitigate some
792+
* attacks on legacy rhosts-style authentication.
793+
* XXX is RhostsRSAAuthentication vulnerable to these?
794+
* XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
795+
*/
796+
797+
static char *
798+
remote_hostname(struct ssh *ssh)
799+
{
800+
struct sockaddr_storage from;
801+
socklen_t fromlen;
802+
struct addrinfo hints, *ai, *aitop;
803+
char name[NI_MAXHOST], ntop2[NI_MAXHOST];
804+
const char *ntop = ssh_remote_ipaddr(ssh);
805+
806+
/* Get IP address of client. */
807+
fromlen = sizeof(from);
808+
memset(&from, 0, sizeof(from));
809+
if (getpeername(ssh_packet_get_connection_in(ssh),
810+
(struct sockaddr *)&from, &fromlen) < 0) {
811+
debug("getpeername failed: %.100s", strerror(errno));
812+
return strdup(ntop);
813+
}
814+
815+
ipv64_normalise_mapped(&from, &fromlen);
816+
if (from.ss_family == AF_INET6)
817+
fromlen = sizeof(struct sockaddr_in6);
818+
819+
debug3("Trying to reverse map address %.100s.", ntop);
820+
/* Map the IP address to a host name. */
821+
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
822+
NULL, 0, NI_NAMEREQD) != 0) {
823+
/* Host name not found. Use ip address. */
824+
return strdup(ntop);
825+
}
826+
827+
/*
828+
* if reverse lookup result looks like a numeric hostname,
829+
* someone is trying to trick us by PTR record like following:
830+
* 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
831+
*/
832+
memset(&hints, 0, sizeof(hints));
833+
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
834+
hints.ai_flags = AI_NUMERICHOST;
835+
if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
836+
logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
837+
name, ntop);
838+
freeaddrinfo(ai);
839+
return strdup(ntop);
840+
}
841+
842+
/* Names are stored in lowercase. */
843+
lowercase(name);
844+
845+
/*
846+
* Map it back to an IP address and check that the given
847+
* address actually is an address of this host. This is
848+
* necessary because anyone with access to a name server can
849+
* define arbitrary names for an IP address. Mapping from
850+
* name to IP address can be trusted better (but can still be
851+
* fooled if the intruder has access to the name server of
852+
* the domain).
853+
*/
854+
memset(&hints, 0, sizeof(hints));
855+
hints.ai_family = from.ss_family;
856+
hints.ai_socktype = SOCK_STREAM;
857+
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
858+
logit("reverse mapping checking getaddrinfo for %.700s "
859+
"[%s] failed - POSSIBLE BREAK-IN ATTEMPT!", name, ntop);
860+
return strdup(ntop);
861+
}
862+
/* Look for the address from the list of addresses. */
863+
for (ai = aitop; ai; ai = ai->ai_next) {
864+
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
865+
sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
866+
(strcmp(ntop, ntop2) == 0))
867+
break;
868+
}
869+
freeaddrinfo(aitop);
870+
/* If we reached the end of the list, the address was not there. */
871+
if (ai == NULL) {
872+
/* Address not found for the host name. */
873+
logit("Address %.100s maps to %.600s, but this does not "
874+
"map back to the address - POSSIBLE BREAK-IN ATTEMPT!",
875+
ntop, name);
876+
return strdup(ntop);
877+
}
878+
return strdup(name);
879+
}
880+
881+
/*
882+
* Return the canonical name of the host in the other side of the current
883+
* connection. The host name is cached, so it is efficient to call this
884+
* several times.
885+
*/
886+
887+
const char *
888+
auth_get_canonical_hostname(struct ssh *ssh, int use_dns)
889+
{
890+
static char *dnsname;
891+
892+
if (!use_dns)
893+
return ssh_remote_ipaddr(ssh);
894+
else if (dnsname != NULL)
895+
return dnsname;
896+
else {
897+
dnsname = remote_hostname(ssh);
898+
return dnsname;
899+
}
900+
}

auth.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: auth.h,v 1.86 2015/12/04 16:41:28 markus Exp $ */
1+
/* $OpenBSD: auth.h,v 1.87 2016/03/07 19:02:43 djm Exp $ */
22

33
/*
44
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -197,6 +197,8 @@ FILE *auth_openkeyfile(const char *, struct passwd *, int);
197197
FILE *auth_openprincipals(const char *, struct passwd *, int);
198198
int auth_key_is_revoked(Key *);
199199

200+
const char *auth_get_canonical_hostname(struct ssh *, int);
201+
200202
HostStatus
201203
check_key_in_hostfiles(struct passwd *, Key *, const char *,
202204
const char *, const char *);

auth2-hostbased.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: auth2-hostbased.c,v 1.25 2015/05/04 06:10:48 djm Exp $ */
1+
/* $OpenBSD: auth2-hostbased.c,v 1.26 2016/03/07 19:02:43 djm Exp $ */
22
/*
33
* Copyright (c) 2000 Markus Friedl. All rights reserved.
44
*
@@ -160,6 +160,7 @@ int
160160
hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
161161
Key *key)
162162
{
163+
struct ssh *ssh = active_state; /* XXX */
163164
const char *resolvedname, *ipaddr, *lookup, *reason;
164165
HostStatus host_status;
165166
int len;
@@ -168,8 +169,8 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
168169
if (auth_key_is_revoked(key))
169170
return 0;
170171

171-
resolvedname = get_canonical_hostname(options.use_dns);
172-
ipaddr = get_remote_ipaddr();
172+
resolvedname = auth_get_canonical_hostname(ssh, options.use_dns);
173+
ipaddr = ssh_remote_ipaddr(ssh);
173174

174175
debug2("%s: chost %s resolvedname %s ipaddr %s", __func__,
175176
chost, resolvedname, ipaddr);

0 commit comments

Comments
 (0)