|
Lines 194-202
u_int session_id2_len = 0;
Link Here
|
| 194 |
/* record remote hostname or ip */ |
194 |
/* record remote hostname or ip */ |
| 195 |
u_int utmp_len = HOST_NAME_MAX+1; |
195 |
u_int utmp_len = HOST_NAME_MAX+1; |
| 196 |
|
196 |
|
| 197 |
/* options.max_startup sized array of fd ints */ |
197 |
/* |
|
|
198 |
* startup_pipes/flags are used for tracking children of the listening sshd |
| 199 |
* process early in their lifespans. This tracking is needed for three things: |
| 200 |
* |
| 201 |
* 1) Implementing the MaxStartups limit of concurrent unauthenticated |
| 202 |
* connections. |
| 203 |
* 2) Avoiding a race condition for SIGHUP processing, where child processes |
| 204 |
* may have listen_socks open that could collide with main listener process |
| 205 |
* after it restarts. |
| 206 |
* 3) Ensuring that rexec'd sshd processes have received their initial state |
| 207 |
* from the parent listen process before handling SIGHUP. |
| 208 |
* |
| 209 |
* Child processes signal that they have completed closure of the listen_socks |
| 210 |
* and (if applicable) received their rexec state by sending a char over their |
| 211 |
* sock. Child processes signal that authentication has completed by closing |
| 212 |
* the sock (or by exiting). |
| 213 |
*/ |
| 198 |
static int *startup_pipes = NULL; |
214 |
static int *startup_pipes = NULL; |
| 199 |
static int startup_pipe; /* in child */ |
215 |
static int *startup_flags = NULL; /* Indicates child closed listener */ |
|
|
216 |
static int startup_pipe = -1; /* in child */ |
| 200 |
|
217 |
|
| 201 |
/* variables used for privilege separation */ |
218 |
/* variables used for privilege separation */ |
| 202 |
int use_privsep = -1; |
219 |
int use_privsep = -1; |
|
Lines 850-863
server_accept_inetd(int *sock_in, int *sock_out)
Link Here
|
| 850 |
{ |
867 |
{ |
| 851 |
int fd; |
868 |
int fd; |
| 852 |
|
869 |
|
| 853 |
startup_pipe = -1; |
|
|
| 854 |
if (rexeced_flag) { |
870 |
if (rexeced_flag) { |
| 855 |
close(REEXEC_CONFIG_PASS_FD); |
871 |
close(REEXEC_CONFIG_PASS_FD); |
| 856 |
*sock_in = *sock_out = dup(STDIN_FILENO); |
872 |
*sock_in = *sock_out = dup(STDIN_FILENO); |
| 857 |
if (!debug_flag) { |
|
|
| 858 |
startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); |
| 859 |
close(REEXEC_STARTUP_PIPE_FD); |
| 860 |
} |
| 861 |
} else { |
873 |
} else { |
| 862 |
*sock_in = dup(STDIN_FILENO); |
874 |
*sock_in = dup(STDIN_FILENO); |
| 863 |
*sock_out = dup(STDOUT_FILENO); |
875 |
*sock_out = dup(STDOUT_FILENO); |
|
Lines 978-985
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
Link Here
|
| 978 |
{ |
990 |
{ |
| 979 |
fd_set *fdset; |
991 |
fd_set *fdset; |
| 980 |
int i, j, ret, maxfd; |
992 |
int i, j, ret, maxfd; |
| 981 |
int startups = 0; |
993 |
int startups = 0, listening = 0, lameduck = 0; |
| 982 |
int startup_p[2] = { -1 , -1 }; |
994 |
int startup_p[2] = { -1 , -1 }; |
|
|
995 |
char c = 0; |
| 983 |
struct sockaddr_storage from; |
996 |
struct sockaddr_storage from; |
| 984 |
socklen_t fromlen; |
997 |
socklen_t fromlen; |
| 985 |
pid_t pid; |
998 |
pid_t pid; |
|
Lines 992-997
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
Link Here
|
| 992 |
maxfd = listen_socks[i]; |
1005 |
maxfd = listen_socks[i]; |
| 993 |
/* pipes connected to unauthenticated childs */ |
1006 |
/* pipes connected to unauthenticated childs */ |
| 994 |
startup_pipes = xcalloc(options.max_startups, sizeof(int)); |
1007 |
startup_pipes = xcalloc(options.max_startups, sizeof(int)); |
|
|
1008 |
startup_flags = xcalloc(options.max_startups, sizeof(int)); |
| 995 |
for (i = 0; i < options.max_startups; i++) |
1009 |
for (i = 0; i < options.max_startups; i++) |
| 996 |
startup_pipes[i] = -1; |
1010 |
startup_pipes[i] = -1; |
| 997 |
|
1011 |
|
|
Lines 1000-1007
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
Link Here
|
| 1000 |
* the daemon is killed with a signal. |
1014 |
* the daemon is killed with a signal. |
| 1001 |
*/ |
1015 |
*/ |
| 1002 |
for (;;) { |
1016 |
for (;;) { |
| 1003 |
if (received_sighup) |
1017 |
if (received_sighup) { |
| 1004 |
sighup_restart(); |
1018 |
if (!lameduck) { |
|
|
1019 |
debug("Received SIGHUP; waiting for children"); |
| 1020 |
close_listen_socks(); |
| 1021 |
lameduck = 1; |
| 1022 |
} |
| 1023 |
if (listening <= 0) |
| 1024 |
sighup_restart(); |
| 1025 |
} |
| 1005 |
free(fdset); |
1026 |
free(fdset); |
| 1006 |
fdset = xcalloc(howmany(maxfd + 1, NFDBITS), |
1027 |
fdset = xcalloc(howmany(maxfd + 1, NFDBITS), |
| 1007 |
sizeof(fd_mask)); |
1028 |
sizeof(fd_mask)); |
|
Lines 1027-1045
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
Link Here
|
| 1027 |
if (ret < 0) |
1048 |
if (ret < 0) |
| 1028 |
continue; |
1049 |
continue; |
| 1029 |
|
1050 |
|
| 1030 |
for (i = 0; i < options.max_startups; i++) |
1051 |
for (i = 0; i < options.max_startups; i++) { |
| 1031 |
if (startup_pipes[i] != -1 && |
1052 |
if (startup_pipes[i] == -1 || |
| 1032 |
FD_ISSET(startup_pipes[i], fdset)) { |
1053 |
!FD_ISSET(startup_pipes[i], fdset)) |
| 1033 |
/* |
1054 |
continue; |
| 1034 |
* the read end of the pipe is ready |
1055 |
switch (read(startup_pipes[i], &c, sizeof(c))) { |
| 1035 |
* if the child has closed the pipe |
1056 |
case -1: |
| 1036 |
* after successful authentication |
1057 |
if (errno == EINTR || errno == EAGAIN) |
| 1037 |
* or if the child has died |
1058 |
continue; |
| 1038 |
*/ |
1059 |
error("%s: startup pipe %d: read %s", |
|
|
1060 |
__func__, i, strerror(errno)); |
| 1061 |
/* FALLTHROUGH */ |
| 1062 |
case 0: |
| 1063 |
/* child exited or completed auth */ |
| 1039 |
close(startup_pipes[i]); |
1064 |
close(startup_pipes[i]); |
| 1040 |
startup_pipes[i] = -1; |
1065 |
startup_pipes[i] = -1; |
| 1041 |
startups--; |
1066 |
startups--; |
|
|
1067 |
if (startup_flags[i]) |
| 1068 |
listening--; |
| 1069 |
break; |
| 1070 |
case 1: |
| 1071 |
/* child has finished preliminaries */ |
| 1072 |
listening--; |
| 1073 |
startup_flags[i] = 0; |
| 1074 |
break; |
| 1042 |
} |
1075 |
} |
|
|
1076 |
} |
| 1043 |
for (i = 0; i < num_listen_socks; i++) { |
1077 |
for (i = 0; i < num_listen_socks; i++) { |
| 1044 |
if (!FD_ISSET(listen_socks[i], fdset)) |
1078 |
if (!FD_ISSET(listen_socks[i], fdset)) |
| 1045 |
continue; |
1079 |
continue; |
|
Lines 1093-1098
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
Link Here
|
| 1093 |
if (maxfd < startup_p[0]) |
1127 |
if (maxfd < startup_p[0]) |
| 1094 |
maxfd = startup_p[0]; |
1128 |
maxfd = startup_p[0]; |
| 1095 |
startups++; |
1129 |
startups++; |
|
|
1130 |
startup_flags[j] = 1; |
| 1096 |
break; |
1131 |
break; |
| 1097 |
} |
1132 |
} |
| 1098 |
|
1133 |
|
|
Lines 1118-1124
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
Link Here
|
| 1118 |
send_rexec_state(config_s[0], cfg); |
1153 |
send_rexec_state(config_s[0], cfg); |
| 1119 |
close(config_s[0]); |
1154 |
close(config_s[0]); |
| 1120 |
} |
1155 |
} |
| 1121 |
break; |
1156 |
return; |
| 1122 |
} |
1157 |
} |
| 1123 |
|
1158 |
|
| 1124 |
/* |
1159 |
/* |
|
Lines 1126-1138
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
Link Here
|
| 1126 |
* the child process the connection. The |
1161 |
* the child process the connection. The |
| 1127 |
* parent continues listening. |
1162 |
* parent continues listening. |
| 1128 |
*/ |
1163 |
*/ |
|
|
1164 |
listening++; |
| 1129 |
if ((pid = fork()) == 0) { |
1165 |
if ((pid = fork()) == 0) { |
| 1130 |
/* |
1166 |
/* |
| 1131 |
* Child. Close the listening and |
1167 |
* Child. Close the listening and |
| 1132 |
* max_startup sockets. Start using |
1168 |
* max_startup sockets. Start using |
| 1133 |
* the accepted socket. Reinitialize |
1169 |
* the accepted socket. Reinitialize |
| 1134 |
* logging (since our pid has changed). |
1170 |
* logging (since our pid has changed). |
| 1135 |
* We break out of the loop to handle |
1171 |
* We return from this function to handle |
| 1136 |
* the connection. |
1172 |
* the connection. |
| 1137 |
*/ |
1173 |
*/ |
| 1138 |
startup_pipe = startup_p[1]; |
1174 |
startup_pipe = startup_p[1]; |
|
Lines 1146-1152
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
Link Here
|
| 1146 |
log_stderr); |
1182 |
log_stderr); |
| 1147 |
if (rexec_flag) |
1183 |
if (rexec_flag) |
| 1148 |
close(config_s[0]); |
1184 |
close(config_s[0]); |
| 1149 |
break; |
1185 |
else { |
|
|
1186 |
/* |
| 1187 |
* Signal parent that the preliminaries |
| 1188 |
* for this child are complete. For the |
| 1189 |
* re-exec case, this happens after the |
| 1190 |
* child has received the rexec state |
| 1191 |
* from the server. |
| 1192 |
*/ |
| 1193 |
(void)atomicio(vwrite, startup_pipe, |
| 1194 |
"\0", 1); |
| 1195 |
} |
| 1196 |
return; |
| 1150 |
} |
1197 |
} |
| 1151 |
|
1198 |
|
| 1152 |
/* Parent. Stay in the loop. */ |
1199 |
/* Parent. Stay in the loop. */ |
|
Lines 1164-1173
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
Link Here
|
| 1164 |
} |
1211 |
} |
| 1165 |
close(*newsock); |
1212 |
close(*newsock); |
| 1166 |
} |
1213 |
} |
| 1167 |
|
|
|
| 1168 |
/* child process check (or debug mode) */ |
| 1169 |
if (num_listen_socks < 0) |
| 1170 |
break; |
| 1171 |
} |
1214 |
} |
| 1172 |
} |
1215 |
} |
| 1173 |
|
1216 |
|
|
Lines 1456-1463
main(int ac, char **av)
Link Here
|
| 1456 |
/* Fetch our configuration */ |
1499 |
/* Fetch our configuration */ |
| 1457 |
if ((cfg = sshbuf_new()) == NULL) |
1500 |
if ((cfg = sshbuf_new()) == NULL) |
| 1458 |
fatal("%s: sshbuf_new failed", __func__); |
1501 |
fatal("%s: sshbuf_new failed", __func__); |
| 1459 |
if (rexeced_flag) |
1502 |
if (rexeced_flag) { |
| 1460 |
recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg); |
1503 |
recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg); |
|
|
1504 |
if (!debug_flag) { |
| 1505 |
startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); |
| 1506 |
close(REEXEC_STARTUP_PIPE_FD); |
| 1507 |
/* |
| 1508 |
* Signal parent that this child is at a point where |
| 1509 |
* they can go away if they have a SIGHUP pending. |
| 1510 |
*/ |
| 1511 |
(void)atomicio(vwrite, startup_pipe, "\0", 1); |
| 1512 |
} |
| 1513 |
} |
| 1461 |
else if (strcasecmp(config_file_name, "none") != 0) |
1514 |
else if (strcasecmp(config_file_name, "none") != 0) |
| 1462 |
load_server_config(config_file_name, cfg); |
1515 |
load_server_config(config_file_name, cfg); |
| 1463 |
|
1516 |
|