52 |
|
"Error during DNS lookup", "connect timeout", "Error during connect()", |
53 |
|
"Comm Error" }; |
54 |
|
|
55 |
– |
struct Callback *setup_socket_cb = NULL; |
56 |
– |
|
55 |
|
static void comm_connect_callback(fde_t *, int); |
56 |
|
static PF comm_connect_timeout; |
57 |
|
static void comm_connect_dns_callback(void *, const struct irc_ssaddr *, const char *); |
137 |
|
* |
138 |
|
* Set the socket non-blocking, and other wonderful bits. |
139 |
|
*/ |
140 |
< |
static void * |
141 |
< |
setup_socket(va_list args) |
140 |
> |
static void |
141 |
> |
setup_socket(int fd) |
142 |
|
{ |
145 |
– |
int fd = va_arg(args, int); |
143 |
|
int opt = 1; |
144 |
|
|
145 |
|
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); |
150 |
|
#endif |
151 |
|
|
152 |
|
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); |
156 |
– |
|
157 |
– |
return NULL; |
158 |
– |
} |
159 |
– |
|
160 |
– |
/* |
161 |
– |
* init_comm() |
162 |
– |
* |
163 |
– |
* Initializes comm subsystem. |
164 |
– |
*/ |
165 |
– |
void |
166 |
– |
init_comm(void) |
167 |
– |
{ |
168 |
– |
setup_socket_cb = register_callback("setup_socket", setup_socket); |
169 |
– |
init_netio(); |
153 |
|
} |
154 |
|
|
155 |
|
/* |
234 |
|
static void |
235 |
|
ssl_handshake(int fd, struct Client *client_p) |
236 |
|
{ |
237 |
< |
int ret = SSL_accept(client_p->localClient->fd.ssl); |
237 |
> |
X509 *cert = NULL; |
238 |
> |
int ret = 0; |
239 |
> |
|
240 |
> |
if ((ret = SSL_accept(client_p->localClient->fd.ssl)) <= 0) |
241 |
> |
{ |
242 |
> |
if ((CurrentTime - client_p->localClient->firsttime) > 30) |
243 |
> |
{ |
244 |
> |
exit_client(client_p, client_p, "Timeout during SSL handshake"); |
245 |
> |
return; |
246 |
> |
} |
247 |
|
|
256 |
– |
if (ret <= 0) |
248 |
|
switch (SSL_get_error(client_p->localClient->fd.ssl, ret)) |
249 |
|
{ |
250 |
|
case SSL_ERROR_WANT_WRITE: |
251 |
|
comm_setselect(&client_p->localClient->fd, COMM_SELECT_WRITE, |
252 |
< |
(PF *) ssl_handshake, client_p, 0); |
252 |
> |
(PF *) ssl_handshake, client_p, 30); |
253 |
|
return; |
254 |
|
|
255 |
|
case SSL_ERROR_WANT_READ: |
256 |
|
comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ, |
257 |
< |
(PF *) ssl_handshake, client_p, 0); |
257 |
> |
(PF *) ssl_handshake, client_p, 30); |
258 |
|
return; |
259 |
|
|
260 |
|
default: |
261 |
|
exit_client(client_p, client_p, "Error during SSL handshake"); |
262 |
|
return; |
263 |
|
} |
264 |
+ |
} |
265 |
+ |
|
266 |
+ |
comm_settimeout(&client_p->localClient->fd, 0, NULL, NULL); |
267 |
+ |
|
268 |
+ |
if ((cert = SSL_get_peer_certificate(client_p->localClient->fd.ssl))) |
269 |
+ |
{ |
270 |
+ |
int res = SSL_get_verify_result(client_p->localClient->fd.ssl); |
271 |
+ |
char buf[EVP_MAX_MD_SIZE * 2 + 1] = { '\0' }; |
272 |
+ |
unsigned char md[EVP_MAX_MD_SIZE] = { '\0' }; |
273 |
+ |
|
274 |
+ |
if (res == X509_V_OK || res == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN || |
275 |
+ |
res == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE || |
276 |
+ |
res == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) |
277 |
+ |
{ |
278 |
+ |
unsigned int i = 0, n = 0; |
279 |
+ |
|
280 |
+ |
if (X509_digest(cert, EVP_sha256(), md, &n)) |
281 |
+ |
{ |
282 |
+ |
for (; i < n; ++i) |
283 |
+ |
snprintf(buf + 2 * i, 3, "%02X", md[i]); |
284 |
+ |
client_p->certfp = xstrdup(buf); |
285 |
+ |
} |
286 |
+ |
} |
287 |
+ |
else |
288 |
+ |
ilog(LOG_TYPE_IRCD, "Client %s!%s@%s gave bad SSL client certificate: %d", |
289 |
+ |
client_p->name, client_p->username, client_p->host, res); |
290 |
+ |
X509_free(cert); |
291 |
+ |
} |
292 |
|
|
293 |
|
start_auth(client_p); |
294 |
|
} |
356 |
|
return; |
357 |
|
} |
358 |
|
|
359 |
+ |
AddFlag(new_client, FLAGS_SSL); |
360 |
|
SSL_set_fd(new_client->localClient->fd.ssl, fd); |
361 |
|
ssl_handshake(0, new_client); |
362 |
|
} |
703 |
|
if (fd < 0) |
704 |
|
return -1; /* errno will be passed through, yay.. */ |
705 |
|
|
706 |
< |
execute_callback(setup_socket_cb, fd); |
706 |
> |
setup_socket(fd); |
707 |
|
|
708 |
|
/* update things in our fd tracking */ |
709 |
|
fd_open(F, fd, 1, note); |
744 |
|
pn->ss_len = addrlen; |
745 |
|
#endif |
746 |
|
|
747 |
< |
execute_callback(setup_socket_cb, newfd); |
747 |
> |
setup_socket(newfd); |
748 |
|
|
749 |
|
/* .. and return */ |
750 |
|
return newfd; |