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

Collapse All | Expand All

(-)misc.c (+50 lines)
Lines 29-34 RCSID("$OpenBSD: misc.c,v 1.34 2005/07/0 Link Here
29
#include "misc.h"
29
#include "misc.h"
30
#include "log.h"
30
#include "log.h"
31
#include "xmalloc.h"
31
#include "xmalloc.h"
32
#include "ssh.h"
32
33
33
/* remove newline at end of string */
34
/* remove newline at end of string */
34
char *
35
char *
Lines 268-273 convtime(const char *s) Link Here
268
	}
269
	}
269
270
270
	return total;
271
	return total;
272
}
273
274
/*
275
 * Returns hostname and optional port.
276
 * Side effect: modifies arg.
277
 */
278
int
279
get_host_port(char *arg, char **host, u_short *port)
280
{
281
	char *p;
282
283
	if (arg == NULL || *arg == '\0')
284
		return -1;	/* missing address */
285
286
	/* check for bare IPv6 address: no "[]" and 2 or more ":" */
287
	if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
288
		&& strchr(p+1, ':') != NULL) {
289
		*host = arg;
290
		*port = 0;
291
		return 0;
292
	}
293
	p = hpdelim(&arg);
294
	if (p == NULL)
295
		return -2;	/* missing port after ":" */
296
	*host = cleanhostname(p);
297
	if (arg == NULL)
298
		*port = 0;
299
	else if ((*port = a2port(arg)) == 0)
300
		return -3;	/* bad port argument */
301
	return 0;
302
}
303
304
char *
305
put_host_port(const char *host, u_short port)
306
{
307
	int ret;
308
	char *p;
309
310
	if (port == 0 || port == SSH_DEFAULT_PORT)
311
		return(xstrdup(host));
312
	if ((p = strchr(host, ':')) != NULL && strchr(p+1, ':') != NULL)
313
		ret = asprintf(&p, "[%s]:%hd", host, port); /* IPv6 */
314
	else
315
		ret = asprintf(&p, "%s:%hd", host, port);
316
317
	if (ret == -1)
318
		fatal("put_host_port: %s", strerror(errno));
319
	debug3("put_host_port: %s", p);
320
	return p;
271
}
321
}
272
322
273
/*
323
/*
(-)misc.h (+2 lines)
Lines 20-25 int set_nonblock(int); Link Here
20
int	 unset_nonblock(int);
20
int	 unset_nonblock(int);
21
void	 set_nodelay(int);
21
void	 set_nodelay(int);
22
int	 a2port(const char *);
22
int	 a2port(const char *);
23
int	 get_host_port(char *, char **, u_short *);
24
char	*put_host_port(const char *, u_short);
23
char	*hpdelim(char **);
25
char	*hpdelim(char **);
24
char	*cleanhostname(char *);
26
char	*cleanhostname(char *);
25
char	*colon(char *);
27
char	*colon(char *);
(-)servconf.c (-16 / +13 lines)
Lines 473-499 parse_time: Link Here
473
473
474
	case sListenAddress:
474
	case sListenAddress:
475
		arg = strdelim(&cp);
475
		arg = strdelim(&cp);
476
		if (arg == NULL || *arg == '\0')
476
		switch (get_host_port(arg, &p, &port)) {
477
		case -1:
477
			fatal("%s line %d: missing address",
478
			fatal("%s line %d: missing address",
478
			    filename, linenum);
479
			    filename, linenum);
479
		/* check for bare IPv6 address: no "[]" and 2 or more ":" */
480
			break;;
480
		if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
481
		case -2:
481
		    && strchr(p+1, ':') != NULL) {
482
			add_listen_addr(options, arg, 0);
483
			break;
484
		}
485
		p = hpdelim(&arg);
486
		if (p == NULL)
487
			fatal("%s line %d: bad address:port usage",
482
			fatal("%s line %d: bad address:port usage",
488
			    filename, linenum);
483
			    filename, linenum);
489
		p = cleanhostname(p);
484
			break;;
490
		if (arg == NULL)
485
		case -3:
491
			port = 0;
492
		else if ((port = a2port(arg)) == 0)
493
			fatal("%s line %d: bad port number", filename, linenum);
486
			fatal("%s line %d: bad port number", filename, linenum);
494
487
			break;
495
		add_listen_addr(options, p, port);
488
		case 0:
496
489
			add_listen_addr(options, p, port);
490
			break;
491
		default:
492
			fatal("Internal error: get_host_port");
493
		}
497
		break;
494
		break;
498
495
499
	case sAddressFamily:
496
	case sAddressFamily:
(-)sshconnect.c (-26 / +36 lines)
Lines 520-526 check_host_key(char *host, struct sockad Link Here
520
{
520
{
521
	Key *file_key;
521
	Key *file_key;
522
	const char *type = key_type(host_key);
522
	const char *type = key_type(host_key);
523
	char *ip = NULL;
523
	char *ip = NULL, *hoststr = NULL, *ipstr = NULL;
524
	char hostline[1000], *hostp, *fp;
524
	char hostline[1000], *hostp, *fp;
525
	HostStatus host_status;
525
	HostStatus host_status;
526
	HostStatus ip_status;
526
	HostStatus ip_status;
Lines 580-593 check_host_key(char *host, struct sockad Link Here
580
		options.check_host_ip = 0;
580
		options.check_host_ip = 0;
581
581
582
	/*
582
	/*
583
	 * Allow the user to record the key under a different name. This is
583
	 * Allow the user to record the key under a different name or
584
	 * useful for ssh tunneling over forwarded connections or if you run
584
	 * differentiate a non-standard port.  This is useful for ssh
585
	 * multiple sshd's on different ports on the same machine.
585
	 * tunneling over forwarded connections or if you run multiple
586
	 * sshd's on different ports on the same machine.
586
	 */
587
	 */
587
	if (options.host_key_alias != NULL) {
588
	if (options.host_key_alias != NULL) {
588
		host = options.host_key_alias;
589
		host = options.host_key_alias;
589
		debug("using hostkeyalias: %s", host);
590
		debug("using hostkeyalias: %s", host);
591
		hoststr = xstrdup(host);
592
	} else {
593
		hoststr = put_host_port(host, options.port);
590
	}
594
	}
595
	ipstr = put_host_port(ip, options.port);
591
596
592
	/*
597
	/*
593
	 * Store the host key from the known host file in here so that we can
598
	 * Store the host key from the known host file in here so that we can
Lines 600-611 check_host_key(char *host, struct sockad Link Here
600
	 * hosts or in the systemwide list.
605
	 * hosts or in the systemwide list.
601
	 */
606
	 */
602
	host_file = user_hostfile;
607
	host_file = user_hostfile;
603
	host_status = check_host_in_hostfile(host_file, host, host_key,
608
	host_status = check_host_in_hostfile(host_file, hoststr, host_key,
604
	    file_key, &host_line);
609
	    file_key, &host_line);
605
	if (host_status == HOST_NEW) {
610
	if (host_status == HOST_NEW) {
606
		host_file = system_hostfile;
611
		host_file = system_hostfile;
607
		host_status = check_host_in_hostfile(host_file, host, host_key,
612
		host_status = check_host_in_hostfile(host_file, hoststr,
608
		    file_key, &host_line);
613
		    host_key, file_key, &host_line);
609
	}
614
	}
610
	/*
615
	/*
611
	 * Also perform check for the ip address, skip the check if we are
616
	 * Also perform check for the ip address, skip the check if we are
Lines 615-625 check_host_key(char *host, struct sockad Link Here
615
		Key *ip_key = key_new(host_key->type);
620
		Key *ip_key = key_new(host_key->type);
616
621
617
		ip_file = user_hostfile;
622
		ip_file = user_hostfile;
618
		ip_status = check_host_in_hostfile(ip_file, ip, host_key,
623
		ip_status = check_host_in_hostfile(ip_file, ipstr, host_key,
619
		    ip_key, &ip_line);
624
		    ip_key, &ip_line);
620
		if (ip_status == HOST_NEW) {
625
		if (ip_status == HOST_NEW) {
621
			ip_file = system_hostfile;
626
			ip_file = system_hostfile;
622
			ip_status = check_host_in_hostfile(ip_file, ip,
627
			ip_status = check_host_in_hostfile(ip_file, ipstr,
623
			    host_key, ip_key, &ip_line);
628
			    host_key, ip_key, &ip_line);
624
		}
629
		}
625
		if (host_status == HOST_CHANGED &&
630
		if (host_status == HOST_CHANGED &&
Lines 636-657 check_host_key(char *host, struct sockad Link Here
636
	case HOST_OK:
641
	case HOST_OK:
637
		/* The host is known and the key matches. */
642
		/* The host is known and the key matches. */
638
		debug("Host '%.200s' is known and matches the %s host key.",
643
		debug("Host '%.200s' is known and matches the %s host key.",
639
		    host, type);
644
		    hoststr, type);
640
		debug("Found key in %s:%d", host_file, host_line);
645
		debug("Found key in %s:%d", host_file, host_line);
641
		if (options.check_host_ip && ip_status == HOST_NEW) {
646
		if (options.check_host_ip && ip_status == HOST_NEW) {
642
			if (readonly)
647
			if (readonly)
643
				logit("%s host key for IP address "
648
				logit("%s host key for IP address "
644
				    "'%.128s' not in list of known hosts.",
649
				    "'%.128s' not in list of known hosts.",
645
				    type, ip);
650
				    type, ipstr);
646
			else if (!add_host_to_hostfile(user_hostfile, ip,
651
			else if (!add_host_to_hostfile(user_hostfile, ip,
647
			    host_key, options.hash_known_hosts))
652
			    host_key, options.hash_known_hosts))
648
				logit("Failed to add the %s host key for IP "
653
				logit("Failed to add the %s host key for IP "
649
				    "address '%.128s' to the list of known "
654
				    "address '%.128s' to the list of known "
650
				    "hosts (%.30s).", type, ip, user_hostfile);
655
				    "hosts (%.30s).", type, ipstr,
656
				    user_hostfile);
651
			else
657
			else
652
				logit("Warning: Permanently added the %s host "
658
				logit("Warning: Permanently added the %s host "
653
				    "key for IP address '%.128s' to the list "
659
				    "key for IP address '%.128s' to the list "
654
				    "of known hosts.", type, ip);
660
				    "of known hosts.", type, ipstr);
655
		}
661
		}
656
		break;
662
		break;
657
	case HOST_NEW:
663
	case HOST_NEW:
Lines 665-676 check_host_key(char *host, struct sockad Link Here
665
			 * alternative left is to abort.
671
			 * alternative left is to abort.
666
			 */
672
			 */
667
			error("No %s host key is known for %.200s and you "
673
			error("No %s host key is known for %.200s and you "
668
			    "have requested strict checking.", type, host);
674
			    "have requested strict checking.", type, hoststr);
669
			goto fail;
675
			goto fail;
670
		} else if (options.strict_host_key_checking == 2) {
676
		} else if (options.strict_host_key_checking == 2) {
671
			char msg1[1024], msg2[1024];
677
			char msg1[1024], msg2[1024];
672
678
673
			if (show_other_keys(host, host_key))
679
			if (show_other_keys(hoststr, host_key))
674
				snprintf(msg1, sizeof(msg1),
680
				snprintf(msg1, sizeof(msg1),
675
				    "\nbut keys of different type are already"
681
				    "\nbut keys of different type are already"
676
				    " known for this host.");
682
				    " known for this host.");
Lines 695-701 check_host_key(char *host, struct sockad Link Here
695
			    "%s key fingerprint is %s.\n%s"
701
			    "%s key fingerprint is %s.\n%s"
696
			    "Are you sure you want to continue connecting "
702
			    "Are you sure you want to continue connecting "
697
			    "(yes/no)? ",
703
			    "(yes/no)? ",
698
			    host, ip, msg1, type, fp, msg2);
704
			    hoststr, ipstr, msg1, type, fp, msg2);
699
			xfree(fp);
705
			xfree(fp);
700
			if (!confirm(msg))
706
			if (!confirm(msg))
701
				goto fail;
707
				goto fail;
Lines 706-718 check_host_key(char *host, struct sockad Link Here
706
		 */
712
		 */
707
		if (options.check_host_ip && ip_status == HOST_NEW) {
713
		if (options.check_host_ip && ip_status == HOST_NEW) {
708
			snprintf(hostline, sizeof(hostline), "%s,%s",
714
			snprintf(hostline, sizeof(hostline), "%s,%s",
709
			    host, ip);
715
			    hoststr, ipstr);
710
			hostp = hostline;
716
			hostp = hostline;
711
			if (options.hash_known_hosts) {
717
			if (options.hash_known_hosts) {
712
				/* Add hash of host and IP separately */
718
				/* Add hash of host and IP separately */
713
				r = add_host_to_hostfile(user_hostfile, host,
719
				r = add_host_to_hostfile(user_hostfile, hoststr,
714
				    host_key, options.hash_known_hosts) &&
720
				    host_key, options.hash_known_hosts) &&
715
				    add_host_to_hostfile(user_hostfile, ip,
721
				    add_host_to_hostfile(user_hostfile, ipstr,
716
				    host_key, options.hash_known_hosts);
722
				    host_key, options.hash_known_hosts);
717
			} else {
723
			} else {
718
				/* Add unhashed "host,ip" */
724
				/* Add unhashed "host,ip" */
Lines 721-729 check_host_key(char *host, struct sockad Link Here
721
				    options.hash_known_hosts);
727
				    options.hash_known_hosts);
722
			}
728
			}
723
		} else {
729
		} else {
724
			r = add_host_to_hostfile(user_hostfile, host, host_key,
730
			r = add_host_to_hostfile(user_hostfile, hoststr,
725
			    options.hash_known_hosts);
731
			    host_key, options.hash_known_hosts);
726
			hostp = host;
732
			hostp = hoststr;
727
		}
733
		}
728
734
729
		if (!r)
735
		if (!r)
Lines 745-752 check_host_key(char *host, struct sockad Link Here
745
			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
751
			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
746
			error("@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @");
752
			error("@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @");
747
			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
753
			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
748
			error("The %s host key for %s has changed,", type, host);
754
			error("The %s host key for %s has changed,", type, hoststr);
749
			error("and the key for the according IP address %s", ip);
755
			error("and the key for the according IP address %s", ipstr);
750
			error("%s. This could either mean that", key_msg);
756
			error("%s. This could either mean that", key_msg);
751
			error("DNS SPOOFING is happening or the IP address for the host");
757
			error("DNS SPOOFING is happening or the IP address for the host");
752
			error("and its host key have changed at the same time.");
758
			error("and its host key have changed at the same time.");
Lines 765-771 check_host_key(char *host, struct sockad Link Here
765
		 */
771
		 */
766
		if (options.strict_host_key_checking) {
772
		if (options.strict_host_key_checking) {
767
			error("%s host key for %.200s has changed and you have "
773
			error("%s host key for %.200s has changed and you have "
768
			    "requested strict checking.", type, host);
774
			    "requested strict checking.", type, hoststr);
769
			goto fail;
775
			goto fail;
770
		}
776
		}
771
777
Lines 826-832 check_host_key(char *host, struct sockad Link Here
826
		    "Warning: the %s host key for '%.200s' "
832
		    "Warning: the %s host key for '%.200s' "
827
		    "differs from the key for the IP address '%.128s'"
833
		    "differs from the key for the IP address '%.128s'"
828
		    "\nOffending key for IP in %s:%d",
834
		    "\nOffending key for IP in %s:%d",
829
		    type, host, ip, ip_file, ip_line);
835
		    type, hoststr, ipstr, ip_file, ip_line);
830
		if (host_status == HOST_OK) {
836
		if (host_status == HOST_OK) {
831
			len = strlen(msg);
837
			len = strlen(msg);
832
			snprintf(msg + len, sizeof(msg) - len,
838
			snprintf(msg + len, sizeof(msg) - len,
Lines 848-857 check_host_key(char *host, struct sockad Link Here
848
	}
854
	}
849
855
850
	xfree(ip);
856
	xfree(ip);
857
	xfree(hoststr);
858
	xfree(ipstr);
851
	return 0;
859
	return 0;
852
860
853
fail:
861
fail:
854
	xfree(ip);
862
	xfree(ip);
863
	xfree(hoststr);
864
	xfree(ipstr);
855
	return -1;
865
	return -1;
856
}
866
}
857
867
(-)sshd.8 (+9 lines)
Lines 530-535 A pattern may also be preceded by Link Here
530
to indicate negation: if the host name matches a negated
530
to indicate negation: if the host name matches a negated
531
pattern, it is not accepted (by that line) even if it matched another
531
pattern, it is not accepted (by that line) even if it matched another
532
pattern on the line.
532
pattern on the line.
533
A hostname may optionally be followed by a
534
.Ql :
535
and then a non-standard port number.
536
If an IPv6 address has a non-standard port number then the address must
537
be enclosed within
538
.Ql [
539
and
540
.Ql ]
541
brackets.
533
.Pp
542
.Pp
534
Alternately, hostnames may be stored in a hashed form which hides host names
543
Alternately, hostnames may be stored in a hashed form which hides host names
535
and addresses should the file's contents be disclosed.
544
and addresses should the file's contents be disclosed.

Return to bug 910