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

Collapse All | Expand All

(-)a/sshd.c (-23 / +63 lines)
Lines 788-794 notify_hostkeys(struct ssh *ssh) Link Here
788
 * all connections are dropped for startups > max_startups
788
 * all connections are dropped for startups > max_startups
789
 */
789
 */
790
static int
790
static int
791
drop_connection(int startups)
791
should_drop_connection(int startups)
792
{
792
{
793
	int p, r;
793
	int p, r;
794
794
Lines 805-814 drop_connection(int startups) Link Here
805
	p += options.max_startups_rate;
805
	p += options.max_startups_rate;
806
	r = arc4random_uniform(100);
806
	r = arc4random_uniform(100);
807
807
808
	debug("drop_connection: p %d, r %d", p, r);
808
	debug("%s: p %d, r %d", __func__, p, r);
809
	return (r < p) ? 1 : 0;
809
	return (r < p) ? 1 : 0;
810
}
810
}
811
811
812
/*
813
 * Check whether connection should be accepted by MaxStartups.
814
 * Returns 0 if the connection is accepted. If the connection is refused,
815
 * returns 1 and attempts to send notification to client.
816
 * Logs when the MaxStartups condition is entered or exited, and periodically
817
 * while in that state.
818
 */
819
static int
820
drop_connection(int sock, int startups)
821
{
822
	char *laddr, *raddr;
823
	const char msg[] = "Exceeded MaxStartups\r\n";
824
	static time_t last_drop, first_drop;
825
	static u_int ndropped;
826
	LogLevel drop_level = SYSLOG_LEVEL_VERBOSE;
827
	time_t now;
828
829
	now = monotime();
830
	if (!should_drop_connection(startups)) {
831
		if (last_drop != 0 &&
832
		    startups < options.max_startups_begin - 1) {
833
			/* XXX maybe need better hysteresis here */
834
			logit("exited MaxStartups throttling after %s, "
835
			    "%u connections dropped",
836
			    fmt_interval((u_int)(now - first_drop)), ndropped);
837
			last_drop = 0;
838
		}
839
		return 0;
840
	}
841
842
#define SSHD_MAXSTARTUPS_LOG_INTERVAL	(5 * 60)
843
	if (last_drop == 0) {
844
		error("beginning MaxStartups throttling");
845
		drop_level = SYSLOG_LEVEL_INFO;
846
		first_drop = now;
847
		ndropped = 0;
848
	} else if (last_drop + SSHD_MAXSTARTUPS_LOG_INTERVAL < now) {
849
		/* Periodic logs */
850
		error("in MaxStartups throttling for %s, "
851
		    "%u connections dropped",
852
		    fmt_interval((u_int)(now - first_drop)), ndropped + 1);
853
		drop_level = SYSLOG_LEVEL_INFO;
854
	}
855
	last_drop = now;
856
	ndropped++;
857
858
	laddr = get_local_ipaddr(sock);
859
	raddr = get_peer_ipaddr(sock);
860
	do_log2(drop_level, "drop connection #%d from [%s]:%d on [%s]:%d "
861
	    "past MaxStartups", startups, raddr, get_peer_port(sock),
862
	    laddr, get_local_port(sock));
863
	free(laddr);
864
	free(raddr);
865
	/* best-effort notification to client */
866
	(void)write(sock, msg, sizeof(msg) - 1);
867
	return 1;
868
}
869
812
static void
870
static void
813
usage(void)
871
usage(void)
814
{
872
{
Lines 1152-1178 server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) Link Here
1152
					usleep(100 * 1000);
1210
					usleep(100 * 1000);
1153
				continue;
1211
				continue;
1154
			}
1212
			}
1155
			if (unset_nonblock(*newsock) == -1) {
1213
			if (unset_nonblock(*newsock) == -1 ||
1156
				close(*newsock);
1214
			    drop_connection(*newsock, startups) ||
1157
				continue;
1215
			    pipe(startup_p) == -1) {
1158
			}
1159
			if (drop_connection(startups) == 1) {
1160
				char *laddr = get_local_ipaddr(*newsock);
1161
				char *raddr = get_peer_ipaddr(*newsock);
1162
				char msg[] = "Exceeded MaxStartups\r\n";
1163
1164
				verbose("drop connection #%d from [%s]:%d "
1165
				    "on [%s]:%d past MaxStartups", startups,
1166
				    raddr, get_peer_port(*newsock),
1167
				    laddr, get_local_port(*newsock));
1168
				free(laddr);
1169
				free(raddr);
1170
				/* best-effort notification to client */
1171
				(void)write(*newsock, msg, strlen(msg));
1172
				close(*newsock);
1173
				continue;
1174
			}
1175
			if (pipe(startup_p) == -1) {
1176
				close(*newsock);
1216
				close(*newsock);
1177
				continue;
1217
				continue;
1178
			}
1218
			}

Return to bug 3055