Annotation of embedaddon/lighttpd/src/network.c, revision 1.1
1.1 ! misho 1: #include "network.h"
! 2: #include "fdevent.h"
! 3: #include "log.h"
! 4: #include "connections.h"
! 5: #include "plugin.h"
! 6: #include "joblist.h"
! 7: #include "configfile.h"
! 8:
! 9: #include "network_backends.h"
! 10: #include "sys-mmap.h"
! 11: #include "sys-socket.h"
! 12:
! 13: #include <sys/types.h>
! 14: #include <sys/stat.h>
! 15: #include <sys/time.h>
! 16:
! 17: #include <errno.h>
! 18: #include <fcntl.h>
! 19: #include <unistd.h>
! 20: #include <string.h>
! 21: #include <stdlib.h>
! 22: #include <assert.h>
! 23:
! 24: #ifdef USE_OPENSSL
! 25: # include <openssl/ssl.h>
! 26: # include <openssl/err.h>
! 27: # include <openssl/rand.h>
! 28: # ifndef OPENSSL_NO_DH
! 29: # include <openssl/dh.h>
! 30: # endif
! 31: # include <openssl/bn.h>
! 32:
! 33: # if OPENSSL_VERSION_NUMBER >= 0x0090800fL
! 34: # ifndef OPENSSL_NO_ECDH
! 35: # include <openssl/ecdh.h>
! 36: # endif
! 37: # endif
! 38: #endif
! 39:
! 40: #ifdef USE_OPENSSL
! 41: static void ssl_info_callback(const SSL *ssl, int where, int ret) {
! 42: UNUSED(ret);
! 43:
! 44: if (0 != (where & SSL_CB_HANDSHAKE_START)) {
! 45: connection *con = SSL_get_app_data(ssl);
! 46: ++con->renegotiations;
! 47: }
! 48: }
! 49: #endif
! 50:
! 51: static handler_t network_server_handle_fdevent(server *srv, void *context, int revents) {
! 52: server_socket *srv_socket = (server_socket *)context;
! 53: connection *con;
! 54: int loops = 0;
! 55:
! 56: UNUSED(context);
! 57:
! 58: if (0 == (revents & FDEVENT_IN)) {
! 59: log_error_write(srv, __FILE__, __LINE__, "sdd",
! 60: "strange event for server socket",
! 61: srv_socket->fd,
! 62: revents);
! 63: return HANDLER_ERROR;
! 64: }
! 65:
! 66: /* accept()s at most 100 connections directly
! 67: *
! 68: * we jump out after 100 to give the waiting connections a chance */
! 69: for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
! 70: handler_t r;
! 71:
! 72: connection_state_machine(srv, con);
! 73:
! 74: switch(r = plugins_call_handle_joblist(srv, con)) {
! 75: case HANDLER_FINISHED:
! 76: case HANDLER_GO_ON:
! 77: break;
! 78: default:
! 79: log_error_write(srv, __FILE__, __LINE__, "d", r);
! 80: break;
! 81: }
! 82: }
! 83: return HANDLER_GO_ON;
! 84: }
! 85:
! 86: #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
! 87: static int network_ssl_servername_callback(SSL *ssl, int *al, server *srv) {
! 88: const char *servername;
! 89: connection *con = (connection *) SSL_get_app_data(ssl);
! 90: UNUSED(al);
! 91:
! 92: buffer_copy_string(con->uri.scheme, "https");
! 93:
! 94: if (NULL == (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
! 95: #if 0
! 96: /* this "error" just means the client didn't support it */
! 97: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
! 98: "failed to get TLS server name");
! 99: #endif
! 100: return SSL_TLSEXT_ERR_NOACK;
! 101: }
! 102: buffer_copy_string(con->tlsext_server_name, servername);
! 103: buffer_to_lower(con->tlsext_server_name);
! 104:
! 105: /* Sometimes this is still set, confusing COMP_HTTP_HOST */
! 106: buffer_reset(con->uri.authority);
! 107:
! 108: config_cond_cache_reset(srv, con);
! 109: config_setup_connection(srv, con);
! 110:
! 111: config_patch_connection(srv, con, COMP_SERVER_SOCKET);
! 112: config_patch_connection(srv, con, COMP_HTTP_SCHEME);
! 113: config_patch_connection(srv, con, COMP_HTTP_HOST);
! 114:
! 115: if (NULL == con->conf.ssl_ctx) {
! 116: /* ssl_ctx <=> pemfile was set <=> ssl_ctx got patched: so this should never happen */
! 117: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
! 118: "null SSL_CTX for TLS server name", con->tlsext_server_name);
! 119: return SSL_TLSEXT_ERR_ALERT_FATAL;
! 120: }
! 121:
! 122: /* switch to new SSL_CTX in reaction to a client's server_name extension */
! 123: if (con->conf.ssl_ctx != SSL_set_SSL_CTX(ssl, con->conf.ssl_ctx)) {
! 124: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
! 125: "failed to set SSL_CTX for TLS server name", con->tlsext_server_name);
! 126: return SSL_TLSEXT_ERR_ALERT_FATAL;
! 127: }
! 128:
! 129: return SSL_TLSEXT_ERR_OK;
! 130: }
! 131: #endif
! 132:
! 133: static int network_server_init(server *srv, buffer *host_token, specific_config *s) {
! 134: int val;
! 135: socklen_t addr_len;
! 136: server_socket *srv_socket;
! 137: char *sp;
! 138: unsigned int port = 0;
! 139: const char *host;
! 140: buffer *b;
! 141: int is_unix_domain_socket = 0;
! 142: int fd;
! 143:
! 144: #ifdef __WIN32
! 145: WORD wVersionRequested;
! 146: WSADATA wsaData;
! 147: int err;
! 148:
! 149: wVersionRequested = MAKEWORD( 2, 2 );
! 150:
! 151: err = WSAStartup( wVersionRequested, &wsaData );
! 152: if ( err != 0 ) {
! 153: /* Tell the user that we could not find a usable */
! 154: /* WinSock DLL. */
! 155: return -1;
! 156: }
! 157: #endif
! 158:
! 159: srv_socket = calloc(1, sizeof(*srv_socket));
! 160: srv_socket->fd = -1;
! 161: srv_socket->fde_ndx = -1;
! 162:
! 163: srv_socket->srv_token = buffer_init();
! 164: buffer_copy_string_buffer(srv_socket->srv_token, host_token);
! 165:
! 166: b = buffer_init();
! 167: buffer_copy_string_buffer(b, host_token);
! 168:
! 169: /* ipv4:port
! 170: * [ipv6]:port
! 171: */
! 172: if (NULL == (sp = strrchr(b->ptr, ':'))) {
! 173: log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
! 174:
! 175: goto error_free_socket;
! 176: }
! 177:
! 178: host = b->ptr;
! 179:
! 180: /* check for [ and ] */
! 181: if (b->ptr[0] == '[' && *(sp-1) == ']') {
! 182: *(sp-1) = '\0';
! 183: host++;
! 184:
! 185: s->use_ipv6 = 1;
! 186: }
! 187:
! 188: *(sp++) = '\0';
! 189:
! 190: port = strtol(sp, NULL, 10);
! 191:
! 192: if (host[0] == '/') {
! 193: /* host is a unix-domain-socket */
! 194: is_unix_domain_socket = 1;
! 195: } else if (port == 0 || port > 65535) {
! 196: log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
! 197:
! 198: goto error_free_socket;
! 199: }
! 200:
! 201: if (*host == '\0') host = NULL;
! 202:
! 203: if (is_unix_domain_socket) {
! 204: #ifdef HAVE_SYS_UN_H
! 205:
! 206: srv_socket->addr.plain.sa_family = AF_UNIX;
! 207:
! 208: if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
! 209: log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
! 210: goto error_free_socket;
! 211: }
! 212: #else
! 213: log_error_write(srv, __FILE__, __LINE__, "s",
! 214: "ERROR: Unix Domain sockets are not supported.");
! 215: goto error_free_socket;
! 216: #endif
! 217: }
! 218:
! 219: #ifdef HAVE_IPV6
! 220: if (s->use_ipv6) {
! 221: srv_socket->addr.plain.sa_family = AF_INET6;
! 222:
! 223: if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
! 224: log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
! 225: goto error_free_socket;
! 226: }
! 227: srv_socket->use_ipv6 = 1;
! 228: }
! 229: #endif
! 230:
! 231: if (srv_socket->fd == -1) {
! 232: srv_socket->addr.plain.sa_family = AF_INET;
! 233: if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
! 234: log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
! 235: goto error_free_socket;
! 236: }
! 237: }
! 238:
! 239: #ifdef FD_CLOEXEC
! 240: /* set FD_CLOEXEC now, fdevent_fcntl_set is called later; needed for pipe-logger forks */
! 241: fcntl(srv_socket->fd, F_SETFD, FD_CLOEXEC);
! 242: #endif
! 243:
! 244: /* */
! 245: srv->cur_fds = srv_socket->fd;
! 246:
! 247: val = 1;
! 248: if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
! 249: log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt(SO_REUSEADDR) failed:", strerror(errno));
! 250: goto error_free_socket;
! 251: }
! 252:
! 253: switch(srv_socket->addr.plain.sa_family) {
! 254: #ifdef HAVE_IPV6
! 255: case AF_INET6:
! 256: memset(&srv_socket->addr, 0, sizeof(struct sockaddr_in6));
! 257: srv_socket->addr.ipv6.sin6_family = AF_INET6;
! 258: if (host == NULL) {
! 259: srv_socket->addr.ipv6.sin6_addr = in6addr_any;
! 260: log_error_write(srv, __FILE__, __LINE__, "s", "warning: please use server.use-ipv6 only for hostnames, not without server.bind / empty address; your config will break if the kernel default for IPV6_V6ONLY changes");
! 261: } else {
! 262: struct addrinfo hints, *res;
! 263: int r;
! 264:
! 265: if (s->set_v6only) {
! 266: val = 1;
! 267: if (-1 == setsockopt(srv_socket->fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val))) {
! 268: log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt(IPV6_V6ONLY) failed:", strerror(errno));
! 269: goto error_free_socket;
! 270: }
! 271: } else {
! 272: log_error_write(srv, __FILE__, __LINE__, "s", "warning: server.set-v6only will be removed soon, update your config to have different sockets for ipv4 and ipv6");
! 273: }
! 274:
! 275: memset(&hints, 0, sizeof(hints));
! 276:
! 277: hints.ai_family = AF_INET6;
! 278: hints.ai_socktype = SOCK_STREAM;
! 279: hints.ai_protocol = IPPROTO_TCP;
! 280:
! 281: if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
! 282: log_error_write(srv, __FILE__, __LINE__,
! 283: "sssss", "getaddrinfo failed: ",
! 284: gai_strerror(r), "'", host, "'");
! 285:
! 286: goto error_free_socket;
! 287: }
! 288:
! 289: memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
! 290:
! 291: freeaddrinfo(res);
! 292: }
! 293: srv_socket->addr.ipv6.sin6_port = htons(port);
! 294: addr_len = sizeof(struct sockaddr_in6);
! 295: break;
! 296: #endif
! 297: case AF_INET:
! 298: memset(&srv_socket->addr, 0, sizeof(struct sockaddr_in));
! 299: srv_socket->addr.ipv4.sin_family = AF_INET;
! 300: if (host == NULL) {
! 301: srv_socket->addr.ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
! 302: } else {
! 303: struct hostent *he;
! 304: if (NULL == (he = gethostbyname(host))) {
! 305: log_error_write(srv, __FILE__, __LINE__,
! 306: "sds", "gethostbyname failed: ",
! 307: h_errno, host);
! 308: goto error_free_socket;
! 309: }
! 310:
! 311: if (he->h_addrtype != AF_INET) {
! 312: log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
! 313: goto error_free_socket;
! 314: }
! 315:
! 316: if (he->h_length != sizeof(struct in_addr)) {
! 317: log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
! 318: goto error_free_socket;
! 319: }
! 320:
! 321: memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
! 322: }
! 323: srv_socket->addr.ipv4.sin_port = htons(port);
! 324:
! 325: addr_len = sizeof(struct sockaddr_in);
! 326:
! 327: break;
! 328: case AF_UNIX:
! 329: srv_socket->addr.un.sun_family = AF_UNIX;
! 330: strcpy(srv_socket->addr.un.sun_path, host);
! 331:
! 332: #ifdef SUN_LEN
! 333: addr_len = SUN_LEN(&srv_socket->addr.un);
! 334: #else
! 335: /* stevens says: */
! 336: addr_len = strlen(host) + 1 + sizeof(srv_socket->addr.un.sun_family);
! 337: #endif
! 338:
! 339: /* check if the socket exists and try to connect to it. */
! 340: if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
! 341: close(fd);
! 342:
! 343: log_error_write(srv, __FILE__, __LINE__, "ss",
! 344: "server socket is still in use:",
! 345: host);
! 346:
! 347:
! 348: goto error_free_socket;
! 349: }
! 350:
! 351: /* connect failed */
! 352: switch(errno) {
! 353: case ECONNREFUSED:
! 354: unlink(host);
! 355: break;
! 356: case ENOENT:
! 357: break;
! 358: default:
! 359: log_error_write(srv, __FILE__, __LINE__, "sds",
! 360: "testing socket failed:",
! 361: host, strerror(errno));
! 362:
! 363: goto error_free_socket;
! 364: }
! 365:
! 366: break;
! 367: default:
! 368: goto error_free_socket;
! 369: }
! 370:
! 371: if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
! 372: switch(srv_socket->addr.plain.sa_family) {
! 373: case AF_UNIX:
! 374: log_error_write(srv, __FILE__, __LINE__, "sds",
! 375: "can't bind to socket:",
! 376: host, strerror(errno));
! 377: break;
! 378: default:
! 379: log_error_write(srv, __FILE__, __LINE__, "ssds",
! 380: "can't bind to port:",
! 381: host, port, strerror(errno));
! 382: break;
! 383: }
! 384: goto error_free_socket;
! 385: }
! 386:
! 387: if (-1 == listen(srv_socket->fd, 128 * 8)) {
! 388: log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
! 389: goto error_free_socket;
! 390: }
! 391:
! 392: if (s->ssl_enabled) {
! 393: #ifdef USE_OPENSSL
! 394: if (NULL == (srv_socket->ssl_ctx = s->ssl_ctx)) {
! 395: log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
! 396: goto error_free_socket;
! 397: }
! 398: #else
! 399:
! 400: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
! 401: "ssl requested but openssl support is not compiled in");
! 402:
! 403: goto error_free_socket;
! 404: #endif
! 405: #ifdef TCP_DEFER_ACCEPT
! 406: } else if (s->defer_accept) {
! 407: int v = s->defer_accept;
! 408: if (-1 == setsockopt(srv_socket->fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &v, sizeof(v))) {
! 409: log_error_write(srv, __FILE__, __LINE__, "ss", "can't set TCP_DEFER_ACCEPT: ", strerror(errno));
! 410: }
! 411: #endif
! 412: } else {
! 413: #ifdef SO_ACCEPTFILTER
! 414: /* FreeBSD accf_http filter */
! 415: struct accept_filter_arg afa;
! 416: memset(&afa, 0, sizeof(afa));
! 417: strcpy(afa.af_name, "httpready");
! 418: if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0) {
! 419: if (errno != ENOENT) {
! 420: log_error_write(srv, __FILE__, __LINE__, "ss", "can't set accept-filter 'httpready': ", strerror(errno));
! 421: }
! 422: }
! 423: #endif
! 424: }
! 425:
! 426: srv_socket->is_ssl = s->ssl_enabled;
! 427:
! 428: if (srv->srv_sockets.size == 0) {
! 429: srv->srv_sockets.size = 4;
! 430: srv->srv_sockets.used = 0;
! 431: srv->srv_sockets.ptr = malloc(srv->srv_sockets.size * sizeof(server_socket));
! 432: } else if (srv->srv_sockets.used == srv->srv_sockets.size) {
! 433: srv->srv_sockets.size += 4;
! 434: srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
! 435: }
! 436:
! 437: srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
! 438:
! 439: buffer_free(b);
! 440:
! 441: return 0;
! 442:
! 443: error_free_socket:
! 444: if (srv_socket->fd != -1) {
! 445: /* check if server fd are already registered */
! 446: if (srv_socket->fde_ndx != -1) {
! 447: fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
! 448: fdevent_unregister(srv->ev, srv_socket->fd);
! 449: }
! 450:
! 451: close(srv_socket->fd);
! 452: }
! 453: buffer_free(srv_socket->srv_token);
! 454: free(srv_socket);
! 455:
! 456: buffer_free(b);
! 457:
! 458: return -1;
! 459: }
! 460:
! 461: int network_close(server *srv) {
! 462: size_t i;
! 463: for (i = 0; i < srv->srv_sockets.used; i++) {
! 464: server_socket *srv_socket = srv->srv_sockets.ptr[i];
! 465:
! 466: if (srv_socket->fd != -1) {
! 467: /* check if server fd are already registered */
! 468: if (srv_socket->fde_ndx != -1) {
! 469: fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
! 470: fdevent_unregister(srv->ev, srv_socket->fd);
! 471: }
! 472:
! 473: close(srv_socket->fd);
! 474: }
! 475:
! 476: buffer_free(srv_socket->srv_token);
! 477:
! 478: free(srv_socket);
! 479: }
! 480:
! 481: free(srv->srv_sockets.ptr);
! 482:
! 483: return 0;
! 484: }
! 485:
! 486: typedef enum {
! 487: NETWORK_BACKEND_UNSET,
! 488: NETWORK_BACKEND_WRITE,
! 489: NETWORK_BACKEND_WRITEV,
! 490: NETWORK_BACKEND_LINUX_SENDFILE,
! 491: NETWORK_BACKEND_FREEBSD_SENDFILE,
! 492: NETWORK_BACKEND_SOLARIS_SENDFILEV
! 493: } network_backend_t;
! 494:
! 495: int network_init(server *srv) {
! 496: buffer *b;
! 497: size_t i;
! 498: network_backend_t backend;
! 499:
! 500: #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
! 501: #ifndef OPENSSL_NO_ECDH
! 502: EC_KEY *ecdh;
! 503: int nid;
! 504: #endif
! 505: #endif
! 506:
! 507: #ifdef USE_OPENSSL
! 508: # ifndef OPENSSL_NO_DH
! 509: DH *dh;
! 510: # endif
! 511: BIO *bio;
! 512:
! 513: /* 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114)
! 514: * -----BEGIN DH PARAMETERS-----
! 515: * MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y
! 516: * mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4
! 517: * +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV
! 518: * w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0
! 519: * sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR
! 520: * jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA=
! 521: * -----END DH PARAMETERS-----
! 522: */
! 523:
! 524: static const unsigned char dh1024_p[]={
! 525: 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E,
! 526: 0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6,
! 527: 0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86,
! 528: 0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0,
! 529: 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C,
! 530: 0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70,
! 531: 0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA,
! 532: 0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0,
! 533: 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF,
! 534: 0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08,
! 535: 0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71,
! 536: };
! 537:
! 538: static const unsigned char dh1024_g[]={
! 539: 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42,
! 540: 0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F,
! 541: 0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E,
! 542: 0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13,
! 543: 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F,
! 544: 0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1,
! 545: 0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08,
! 546: 0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A,
! 547: 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59,
! 548: 0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24,
! 549: 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5,
! 550: };
! 551: #endif
! 552:
! 553: struct nb_map {
! 554: network_backend_t nb;
! 555: const char *name;
! 556: } network_backends[] = {
! 557: /* lowest id wins */
! 558: #if defined USE_LINUX_SENDFILE
! 559: { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" },
! 560: #endif
! 561: #if defined USE_FREEBSD_SENDFILE
! 562: { NETWORK_BACKEND_FREEBSD_SENDFILE, "freebsd-sendfile" },
! 563: #endif
! 564: #if defined USE_SOLARIS_SENDFILEV
! 565: { NETWORK_BACKEND_SOLARIS_SENDFILEV, "solaris-sendfilev" },
! 566: #endif
! 567: #if defined USE_WRITEV
! 568: { NETWORK_BACKEND_WRITEV, "writev" },
! 569: #endif
! 570: { NETWORK_BACKEND_WRITE, "write" },
! 571: { NETWORK_BACKEND_UNSET, NULL }
! 572: };
! 573:
! 574: #ifdef USE_OPENSSL
! 575: /* load SSL certificates */
! 576: for (i = 0; i < srv->config_context->used; i++) {
! 577: specific_config *s = srv->config_storage[i];
! 578: #ifndef SSL_OP_NO_COMPRESSION
! 579: # define SSL_OP_NO_COMPRESSION 0
! 580: #endif
! 581: long ssloptions =
! 582: SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION;
! 583:
! 584: if (buffer_is_empty(s->ssl_pemfile)) continue;
! 585:
! 586: #ifdef OPENSSL_NO_TLSEXT
! 587: {
! 588: data_config *dc = (data_config *)srv->config_context->data[i];
! 589: if (COMP_HTTP_HOST == dc->comp) {
! 590: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
! 591: "can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
! 592: return -1;
! 593: }
! 594: }
! 595: #endif
! 596:
! 597: if (srv->ssl_is_init == 0) {
! 598: SSL_load_error_strings();
! 599: SSL_library_init();
! 600: OpenSSL_add_all_algorithms();
! 601: srv->ssl_is_init = 1;
! 602:
! 603: if (0 == RAND_status()) {
! 604: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
! 605: "not enough entropy in the pool");
! 606: return -1;
! 607: }
! 608: }
! 609:
! 610: if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
! 611: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
! 612: ERR_error_string(ERR_get_error(), NULL));
! 613: return -1;
! 614: }
! 615:
! 616: if (s->ssl_empty_fragments) {
! 617: #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
! 618: ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
! 619: #else
! 620: ssloptions &= ~0x00000800L; /* hardcode constant */
! 621: log_error_write(srv, __FILE__, __LINE__, "ss", "WARNING: SSL:",
! 622: "'insert empty fragments' not supported by the openssl version used to compile lighttpd with");
! 623: #endif
! 624: }
! 625:
! 626: SSL_CTX_set_options(s->ssl_ctx, ssloptions);
! 627: SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);
! 628:
! 629: if (!s->ssl_use_sslv2) {
! 630: /* disable SSLv2 */
! 631: if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) {
! 632: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
! 633: ERR_error_string(ERR_get_error(), NULL));
! 634: return -1;
! 635: }
! 636: }
! 637:
! 638: if (!s->ssl_use_sslv3) {
! 639: /* disable SSLv3 */
! 640: if (!(SSL_OP_NO_SSLv3 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3))) {
! 641: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
! 642: ERR_error_string(ERR_get_error(), NULL));
! 643: return -1;
! 644: }
! 645: }
! 646:
! 647: if (!buffer_is_empty(s->ssl_cipher_list)) {
! 648: /* Disable support for low encryption ciphers */
! 649: if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
! 650: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
! 651: ERR_error_string(ERR_get_error(), NULL));
! 652: return -1;
! 653: }
! 654:
! 655: if (s->ssl_honor_cipher_order) {
! 656: SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
! 657: }
! 658: }
! 659:
! 660: #ifndef OPENSSL_NO_DH
! 661: /* Support for Diffie-Hellman key exchange */
! 662: if (!buffer_is_empty(s->ssl_dh_file)) {
! 663: /* DH parameters from file */
! 664: bio = BIO_new_file((char *) s->ssl_dh_file->ptr, "r");
! 665: if (bio == NULL) {
! 666: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to open file", s->ssl_dh_file->ptr);
! 667: return -1;
! 668: }
! 669: dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
! 670: BIO_free(bio);
! 671: if (dh == NULL) {
! 672: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: PEM_read_bio_DHparams failed", s->ssl_dh_file->ptr);
! 673: return -1;
! 674: }
! 675: } else {
! 676: /* Default DH parameters from RFC5114 */
! 677: dh = DH_new();
! 678: if (dh == NULL) {
! 679: log_error_write(srv, __FILE__, __LINE__, "s", "SSL: DH_new () failed");
! 680: return -1;
! 681: }
! 682: dh->p = BN_bin2bn(dh1024_p,sizeof(dh1024_p), NULL);
! 683: dh->g = BN_bin2bn(dh1024_g,sizeof(dh1024_g), NULL);
! 684: dh->length = 160;
! 685: if ((dh->p == NULL) || (dh->g == NULL)) {
! 686: DH_free(dh);
! 687: log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BN_bin2bn () failed");
! 688: return -1;
! 689: }
! 690: }
! 691: SSL_CTX_set_tmp_dh(s->ssl_ctx,dh);
! 692: SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE);
! 693: DH_free(dh);
! 694: #else
! 695: if (!buffer_is_empty(s->ssl_dh_file)) {
! 696: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: openssl compiled without DH support, can't load parameters from", s->ssl_dh_file->ptr);
! 697: }
! 698: #endif
! 699:
! 700: #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
! 701: #ifndef OPENSSL_NO_ECDH
! 702: /* Support for Elliptic-Curve Diffie-Hellman key exchange */
! 703: if (!buffer_is_empty(s->ssl_ec_curve)) {
! 704: /* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */
! 705: nid = OBJ_sn2nid((char *) s->ssl_ec_curve->ptr);
! 706: if (nid == 0) {
! 707: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unknown curve name", s->ssl_ec_curve->ptr);
! 708: return -1;
! 709: }
! 710: } else {
! 711: /* Default curve */
! 712: nid = OBJ_sn2nid("prime256v1");
! 713: }
! 714: ecdh = EC_KEY_new_by_curve_name(nid);
! 715: if (ecdh == NULL) {
! 716: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to create curve", s->ssl_ec_curve->ptr);
! 717: return -1;
! 718: }
! 719: SSL_CTX_set_tmp_ecdh(s->ssl_ctx,ecdh);
! 720: SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_ECDH_USE);
! 721: EC_KEY_free(ecdh);
! 722: #endif
! 723: #endif
! 724:
! 725: if (!buffer_is_empty(s->ssl_ca_file)) {
! 726: if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
! 727: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
! 728: ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
! 729: return -1;
! 730: }
! 731: if (s->ssl_verifyclient) {
! 732: STACK_OF(X509_NAME) *certs = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
! 733: if (!certs) {
! 734: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
! 735: ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
! 736: }
! 737: if (SSL_CTX_set_session_id_context(s->ssl_ctx, (void*) &srv, sizeof(srv)) != 1) {
! 738: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
! 739: ERR_error_string(ERR_get_error(), NULL));
! 740: return -1;
! 741: }
! 742: SSL_CTX_set_client_CA_list(s->ssl_ctx, certs);
! 743: SSL_CTX_set_verify(
! 744: s->ssl_ctx,
! 745: SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
! 746: NULL
! 747: );
! 748: SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
! 749: }
! 750: } else if (s->ssl_verifyclient) {
! 751: log_error_write(
! 752: srv, __FILE__, __LINE__, "s",
! 753: "SSL: You specified ssl.verifyclient.activate but no ca_file"
! 754: );
! 755: }
! 756:
! 757: if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
! 758: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
! 759: ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
! 760: return -1;
! 761: }
! 762:
! 763: if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
! 764: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
! 765: ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
! 766: return -1;
! 767: }
! 768:
! 769: if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
! 770: log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
! 771: "Private key does not match the certificate public key, reason:",
! 772: ERR_error_string(ERR_get_error(), NULL),
! 773: s->ssl_pemfile);
! 774: return -1;
! 775: }
! 776: SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1);
! 777: SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
! 778:
! 779: # ifndef OPENSSL_NO_TLSEXT
! 780: if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) ||
! 781: !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) {
! 782: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
! 783: "failed to initialize TLS servername callback, openssl library does not support TLS servername extension");
! 784: return -1;
! 785: }
! 786: # endif
! 787: }
! 788: #endif
! 789:
! 790: b = buffer_init();
! 791:
! 792: buffer_copy_string_buffer(b, srv->srvconf.bindhost);
! 793: buffer_append_string_len(b, CONST_STR_LEN(":"));
! 794: buffer_append_long(b, srv->srvconf.port);
! 795:
! 796: if (0 != network_server_init(srv, b, srv->config_storage[0])) {
! 797: return -1;
! 798: }
! 799: buffer_free(b);
! 800:
! 801: #ifdef USE_OPENSSL
! 802: srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
! 803: #endif
! 804:
! 805: /* get a usefull default */
! 806: backend = network_backends[0].nb;
! 807:
! 808: /* match name against known types */
! 809: if (!buffer_is_empty(srv->srvconf.network_backend)) {
! 810: for (i = 0; network_backends[i].name; i++) {
! 811: /**/
! 812: if (buffer_is_equal_string(srv->srvconf.network_backend, network_backends[i].name, strlen(network_backends[i].name))) {
! 813: backend = network_backends[i].nb;
! 814: break;
! 815: }
! 816: }
! 817: if (NULL == network_backends[i].name) {
! 818: /* we don't know it */
! 819:
! 820: log_error_write(srv, __FILE__, __LINE__, "sb",
! 821: "server.network-backend has a unknown value:",
! 822: srv->srvconf.network_backend);
! 823:
! 824: return -1;
! 825: }
! 826: }
! 827:
! 828: switch(backend) {
! 829: case NETWORK_BACKEND_WRITE:
! 830: srv->network_backend_write = network_write_chunkqueue_write;
! 831: break;
! 832: #ifdef USE_WRITEV
! 833: case NETWORK_BACKEND_WRITEV:
! 834: srv->network_backend_write = network_write_chunkqueue_writev;
! 835: break;
! 836: #endif
! 837: #ifdef USE_LINUX_SENDFILE
! 838: case NETWORK_BACKEND_LINUX_SENDFILE:
! 839: srv->network_backend_write = network_write_chunkqueue_linuxsendfile;
! 840: break;
! 841: #endif
! 842: #ifdef USE_FREEBSD_SENDFILE
! 843: case NETWORK_BACKEND_FREEBSD_SENDFILE:
! 844: srv->network_backend_write = network_write_chunkqueue_freebsdsendfile;
! 845: break;
! 846: #endif
! 847: #ifdef USE_SOLARIS_SENDFILEV
! 848: case NETWORK_BACKEND_SOLARIS_SENDFILEV:
! 849: srv->network_backend_write = network_write_chunkqueue_solarissendfilev;
! 850: break;
! 851: #endif
! 852: default:
! 853: return -1;
! 854: }
! 855:
! 856: /* check for $SERVER["socket"] */
! 857: for (i = 1; i < srv->config_context->used; i++) {
! 858: data_config *dc = (data_config *)srv->config_context->data[i];
! 859: specific_config *s = srv->config_storage[i];
! 860: size_t j;
! 861:
! 862: /* not our stage */
! 863: if (COMP_SERVER_SOCKET != dc->comp) continue;
! 864:
! 865: if (dc->cond != CONFIG_COND_EQ) continue;
! 866:
! 867: /* check if we already know this socket,
! 868: * if yes, don't init it */
! 869: for (j = 0; j < srv->srv_sockets.used; j++) {
! 870: if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) {
! 871: break;
! 872: }
! 873: }
! 874:
! 875: if (j == srv->srv_sockets.used) {
! 876: if (0 != network_server_init(srv, dc->string, s)) return -1;
! 877: }
! 878: }
! 879:
! 880: return 0;
! 881: }
! 882:
! 883: int network_register_fdevents(server *srv) {
! 884: size_t i;
! 885:
! 886: if (-1 == fdevent_reset(srv->ev)) {
! 887: return -1;
! 888: }
! 889:
! 890: /* register fdevents after reset */
! 891: for (i = 0; i < srv->srv_sockets.used; i++) {
! 892: server_socket *srv_socket = srv->srv_sockets.ptr[i];
! 893:
! 894: fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
! 895: fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
! 896: }
! 897: return 0;
! 898: }
! 899:
! 900: int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq, off_t max_bytes) {
! 901: int ret = -1;
! 902: off_t written = 0;
! 903: #ifdef TCP_CORK
! 904: int corked = 0;
! 905: #endif
! 906: server_socket *srv_socket = con->srv_socket;
! 907:
! 908: if (con->conf.global_kbytes_per_second) {
! 909: off_t limit = con->conf.global_kbytes_per_second * 1024 - *(con->conf.global_bytes_per_second_cnt_ptr);
! 910: if (limit <= 0) {
! 911: /* we reached the global traffic limit */
! 912:
! 913: con->traffic_limit_reached = 1;
! 914: joblist_append(srv, con);
! 915:
! 916: return 1;
! 917: } else {
! 918: if (max_bytes > limit) max_bytes = limit;
! 919: }
! 920: }
! 921:
! 922: if (con->conf.kbytes_per_second) {
! 923: off_t limit = con->conf.kbytes_per_second * 1024 - con->bytes_written_cur_second;
! 924: if (limit <= 0) {
! 925: /* we reached the traffic limit */
! 926:
! 927: con->traffic_limit_reached = 1;
! 928: joblist_append(srv, con);
! 929:
! 930: return 1;
! 931: } else {
! 932: if (max_bytes > limit) max_bytes = limit;
! 933: }
! 934: }
! 935:
! 936: written = cq->bytes_out;
! 937:
! 938: #ifdef TCP_CORK
! 939: /* Linux: put a cork into the socket as we want to combine the write() calls
! 940: * but only if we really have multiple chunks
! 941: */
! 942: if (cq->first && cq->first->next) {
! 943: corked = 1;
! 944: setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
! 945: }
! 946: #endif
! 947:
! 948: if (srv_socket->is_ssl) {
! 949: #ifdef USE_OPENSSL
! 950: ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq, max_bytes);
! 951: #endif
! 952: } else {
! 953: ret = srv->network_backend_write(srv, con, con->fd, cq, max_bytes);
! 954: }
! 955:
! 956: if (ret >= 0) {
! 957: chunkqueue_remove_finished_chunks(cq);
! 958: ret = chunkqueue_is_empty(cq) ? 0 : 1;
! 959: }
! 960:
! 961: #ifdef TCP_CORK
! 962: if (corked) {
! 963: corked = 0;
! 964: setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
! 965: }
! 966: #endif
! 967:
! 968: written = cq->bytes_out - written;
! 969: con->bytes_written += written;
! 970: con->bytes_written_cur_second += written;
! 971:
! 972: *(con->conf.global_bytes_per_second_cnt_ptr) += written;
! 973:
! 974: return ret;
! 975: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>