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 $ */
2
2
/*
3
3
* Copyright (c) 2000 Markus Friedl. All rights reserved.
4
4
*
27
27
28
28
#include <sys/types.h>
29
29
#include <sys/stat.h>
30
+ #include <sys/socket.h>
30
31
31
32
#include <netinet/in.h>
32
33
50
51
#include <string.h>
51
52
#include <unistd.h>
52
53
#include <limits.h>
54
+ #include <netdb.h>
53
55
54
56
#include "xmalloc.h"
55
57
#include "match.h"
@@ -97,6 +99,7 @@ int auth_debug_init;
97
99
int
98
100
allowed_user (struct passwd * pw )
99
101
{
102
+ struct ssh * ssh = active_state ; /* XXX */
100
103
struct stat st ;
101
104
const char * hostname = NULL , * ipaddr = NULL , * passwd = NULL ;
102
105
u_int i ;
@@ -182,8 +185,8 @@ allowed_user(struct passwd * pw)
182
185
183
186
if (options .num_deny_users > 0 || options .num_allow_users > 0 ||
184
187
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 );
187
190
}
188
191
189
192
/* Return false if user is listed in DenyUsers */
274
277
auth_log (Authctxt * authctxt , int authenticated , int partial ,
275
278
const char * method , const char * submethod )
276
279
{
280
+ struct ssh * ssh = active_state ; /* XXX */
277
281
void (* authlog ) (const char * fmt ,...) = verbose ;
278
282
char * authmsg ;
279
283
@@ -300,8 +304,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
300
304
submethod != NULL ? "/" : "" , submethod == NULL ? "" : submethod ,
301
305
authctxt -> valid ? "" : "invalid user " ,
302
306
authctxt -> user ,
303
- get_remote_ipaddr ( ),
304
- get_remote_port ( ),
307
+ ssh_remote_ipaddr ( ssh ),
308
+ ssh_remote_port ( ssh ),
305
309
compat20 ? "ssh2" : "ssh1" ,
306
310
authctxt -> info != NULL ? ": " : "" ,
307
311
authctxt -> info != NULL ? authctxt -> info : "" );
@@ -331,12 +335,14 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
331
335
void
332
336
auth_maxtries_exceeded (Authctxt * authctxt )
333
337
{
338
+ struct ssh * ssh = active_state ; /* XXX */
339
+
334
340
error ("maximum authentication attempts exceeded for "
335
341
"%s%.100s from %.200s port %d %s" ,
336
342
authctxt -> valid ? "" : "invalid user " ,
337
343
authctxt -> user ,
338
- get_remote_ipaddr ( ),
339
- get_remote_port ( ),
344
+ ssh_remote_ipaddr ( ssh ),
345
+ ssh_remote_port ( ssh ),
340
346
compat20 ? "ssh2" : "ssh1" );
341
347
packet_disconnect ("Too many authentication failures" );
342
348
/* NOTREACHED */
@@ -348,6 +354,8 @@ auth_maxtries_exceeded(Authctxt *authctxt)
348
354
int
349
355
auth_root_allowed (const char * method )
350
356
{
357
+ struct ssh * ssh = active_state ; /* XXX */
358
+
351
359
switch (options .permit_root_login ) {
352
360
case PERMIT_YES :
353
361
return 1 ;
@@ -364,7 +372,8 @@ auth_root_allowed(const char *method)
364
372
}
365
373
break ;
366
374
}
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 ));
368
377
return 0 ;
369
378
}
370
379
@@ -604,6 +613,7 @@ auth_openprincipals(const char *file, struct passwd *pw, int strict_modes)
604
613
struct passwd *
605
614
getpwnamallow (const char * user )
606
615
{
616
+ struct ssh * ssh = active_state ; /* XXX */
607
617
#ifdef HAVE_LOGIN_CAP
608
618
extern login_cap_t * lc ;
609
619
#ifdef BSD_AUTH
@@ -639,8 +649,8 @@ getpwnamallow(const char *user)
639
649
}
640
650
#endif
641
651
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 ));
644
654
#ifdef CUSTOM_FAILED_LOGIN
645
655
record_failed_login (user ,
646
656
get_canonical_hostname (options .use_dns ), "ssh" );
@@ -773,3 +783,118 @@ fakepw(void)
773
783
774
784
return (& fake );
775
785
}
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
+ }
0 commit comments