static int configure_domain(char **argv) { if (argv[2] == NULL) return (KORE_RESULT_ERROR); if (current_domain != NULL) { kore_debug("previous domain configuration not closed"); return (KORE_RESULT_ERROR); } if (strcmp(argv[2], "{")) { kore_debug("missing { for domain directive"); return (KORE_RESULT_ERROR); } if (!kore_domain_new(argv[1])) { kore_debug("could not create new domain %s", current_domain); return (KORE_RESULT_ERROR); } current_domain = kore_domain_lookup(argv[1]); return (KORE_RESULT_OK); }
int kore_accesslog_wait(void) { ssize_t len; time_t now; struct kore_domain *dom; struct pollfd pfd[1]; int nfds, l; struct kore_log_packet logpacket; char addr[INET6_ADDRSTRLEN]; char *method, *buf, *tbuf, *cn; pfd[0].fd = accesslog_fd[0]; pfd[0].events = POLLIN; pfd[0].revents = 0; nfds = poll(pfd, 1, 1000); if (nfds == -1 || (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))) { if (nfds == -1 && errno == EINTR) return (KORE_RESULT_OK); kore_log(LOG_WARNING, "poll(): %s", errno_s); return (KORE_RESULT_ERROR); } if (nfds == 0) return (KORE_RESULT_OK); len = recv(accesslog_fd[0], &logpacket, sizeof(logpacket), 0); if (len == -1) { kore_log(LOG_WARNING, "recv(): %s", errno_s); return (KORE_RESULT_ERROR); } if (len != sizeof(logpacket)) return (KORE_RESULT_ERROR); if ((dom = kore_domain_lookup(logpacket.host)) == NULL) { kore_log(LOG_WARNING, "got accesslog packet for unknown domain: %s", logpacket.host); return (KORE_RESULT_OK); } switch (logpacket.method) { case HTTP_METHOD_GET: method = "GET"; break; case HTTP_METHOD_POST: method = "POST"; break; default: method = "UNKNOWN"; break; } if (logpacket.cn[0] != '\0') cn = logpacket.cn; else cn = "none"; if (inet_ntop(logpacket.addrtype, &(logpacket.addr), addr, sizeof(addr)) == NULL) kore_strlcpy(addr, "unknown", sizeof(addr)); time(&now); tbuf = kore_time_to_date(now); l = asprintf(&buf, "[%s] %s %d %s %s (w#%d) (%dms) (%s) (%s)\n", tbuf, addr, logpacket.status, method, logpacket.path, logpacket.worker_id, logpacket.time_req, cn, logpacket.agent); if (l == -1) { kore_log(LOG_WARNING, "kore_accesslog_wait(): asprintf() == -1"); return (KORE_RESULT_ERROR); } len = write(dom->accesslog, buf, l); if (len == -1) { free(buf); kore_log(LOG_WARNING, "kore_accesslog_wait(): write(): %s", errno_s); return (KORE_RESULT_ERROR); } if (len != l) kore_log(LOG_NOTICE, "accesslog: %s", buf); free(buf); return (KORE_RESULT_OK); }
int kore_accesslog_wait(void) { ssize_t len; time_t now; size_t slen; int nfds; struct kore_domain *dom; struct pollfd pfd[1]; struct kore_log_packet logpacket; char *method, buf[4096], *tbuf; pfd[0].fd = accesslog_fd[0]; pfd[0].events = POLLIN; pfd[0].revents = 0; nfds = poll(pfd, 1, 1000); if (nfds == -1 || (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))) { if (nfds == -1 && errno == EINTR) return (KORE_RESULT_OK); kore_log(LOG_WARNING, "poll(): %s", errno_s); return (KORE_RESULT_ERROR); } if (nfds == 0) return (KORE_RESULT_OK); len = recv(accesslog_fd[0], &logpacket, sizeof(logpacket), 0); if (len == -1) { kore_log(LOG_WARNING, "recv(): %s", errno_s); return (KORE_RESULT_ERROR); } if (len != sizeof(logpacket)) return (KORE_RESULT_ERROR); if ((dom = kore_domain_lookup(logpacket.host)) == NULL) { kore_log(LOG_WARNING, "got accesslog packet for unknown domain: %s", logpacket.host); return (KORE_RESULT_OK); } if (logpacket.method == HTTP_METHOD_GET) method = "GET"; else method = "POST"; time(&now); tbuf = kore_time_to_date(now); snprintf(buf, sizeof(buf), "[%s] %s %d %s %s (w#%d) (%dms) (%s)\n", tbuf, inet_ntoa(logpacket.src), logpacket.status, method, logpacket.path, logpacket.worker_id, logpacket.time_req, logpacket.agent); slen = strlen(buf); len = write(dom->accesslog, buf, slen); if (len == -1) { kore_log(LOG_WARNING, "kore_accesslog_wait(): write(): %s", errno_s); return (KORE_RESULT_ERROR); } if ((size_t)len != slen) kore_log(LOG_NOTICE, "accesslog: %s", buf); return (KORE_RESULT_OK); }
int main(int argc, char *argv[]) { int ch, flags; flags = 0; #if !defined(KORE_SINGLE_BINARY) while ((ch = getopt(argc, argv, "c:dfhnrv")) != -1) { #else while ((ch = getopt(argc, argv, "dfhnrv")) != -1) { #endif flags++; switch (ch) { #if !defined(KORE_SINGLE_BINARY) case 'c': config_file = optarg; break; #endif #if defined(KORE_DEBUG) case 'd': kore_debug = 1; break; #endif case 'f': foreground = 1; break; case 'h': usage(); break; case 'n': skip_chroot = 1; break; case 'r': skip_runas = 1; break; case 'v': version(); break; default: usage(); } } argc -= optind; argv += optind; kore_mem_init(); #if !defined(KORE_SINGLE_BINARY) if (argc > 0) { if (flags) fatal("You cannot specify kore flags and a command"); return (kore_cli_main(argc, argv)); } #endif kore_pid = getpid(); nlisteners = 0; LIST_INIT(&listeners); kore_log_init(); #if !defined(KORE_NO_HTTP) kore_auth_init(); kore_validator_init(); #endif kore_domain_init(); kore_module_init(); kore_server_sslstart(); #if !defined(KORE_SINGLE_BINARY) if (config_file == NULL) usage(); #else kore_module_load(NULL, NULL); #endif kore_parse_config(); kore_platform_init(); #if !defined(KORE_NO_HTTP) kore_accesslog_init(); if (http_body_disk_offload > 0) { if (mkdir(http_body_disk_path, 0700) == -1 && errno != EEXIST) { printf("can't create http_body_disk_path '%s': %s\n", http_body_disk_path, errno_s); return (KORE_RESULT_ERROR); } } #endif sig_recv = 0; signal(SIGHUP, kore_signal); signal(SIGQUIT, kore_signal); signal(SIGTERM, kore_signal); if (foreground) signal(SIGINT, kore_signal); else signal(SIGINT, SIG_IGN); kore_server_start(); kore_log(LOG_NOTICE, "server shutting down"); kore_worker_shutdown(); if (!foreground) unlink(kore_pidfile); kore_listener_cleanup(); kore_log(LOG_NOTICE, "goodbye"); return (0); } #if !defined(KORE_NO_TLS) int kore_tls_sni_cb(SSL *ssl, int *ad, void *arg) { struct kore_domain *dom; const char *sname; sname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); kore_debug("kore_tls_sni_cb(): received host %s", sname); if (sname != NULL && (dom = kore_domain_lookup(sname)) != NULL) { kore_debug("kore_ssl_sni_cb(): Using %s CTX", sname); SSL_set_SSL_CTX(ssl, dom->ssl_ctx); if (dom->cafile != NULL) { SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); } else { SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); } return (SSL_TLSEXT_ERR_OK); } return (SSL_TLSEXT_ERR_NOACK); } void kore_tls_info_callback(const SSL *ssl, int flags, int ret) { struct connection *c; if (flags & SSL_CB_HANDSHAKE_START) { if ((c = SSL_get_app_data(ssl)) == NULL) fatal("no SSL_get_app_data"); c->tls_reneg++; } } #endif int kore_server_bind(const char *ip, const char *port, const char *ccb) { struct listener *l; int on, r; struct addrinfo hints, *results; kore_debug("kore_server_bind(%s, %s)", ip, port); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = 0; r = getaddrinfo(ip, port, &hints, &results); if (r != 0) fatal("getaddrinfo(%s): %s", ip, gai_strerror(r)); l = kore_malloc(sizeof(struct listener)); l->type = KORE_TYPE_LISTENER; l->addrtype = results->ai_family; if (l->addrtype != AF_INET && l->addrtype != AF_INET6) fatal("getaddrinfo(): unknown address family %d", l->addrtype); if ((l->fd = socket(results->ai_family, SOCK_STREAM, 0)) == -1) { kore_free(l); freeaddrinfo(results); kore_debug("socket(): %s", errno_s); printf("failed to create socket: %s\n", errno_s); return (KORE_RESULT_ERROR); } if (!kore_connection_nonblock(l->fd, 1)) { kore_free(l); freeaddrinfo(results); printf("failed to make socket non blocking: %s\n", errno_s); return (KORE_RESULT_ERROR); } on = 1; if (setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)) == -1) { close(l->fd); kore_free(l); freeaddrinfo(results); kore_debug("setsockopt(): %s", errno_s); printf("failed to set SO_REUSEADDR: %s\n", errno_s); return (KORE_RESULT_ERROR); } if (bind(l->fd, results->ai_addr, results->ai_addrlen) == -1) { close(l->fd); kore_free(l); freeaddrinfo(results); kore_debug("bind(): %s", errno_s); printf("failed to bind to %s port %s: %s\n", ip, port, errno_s); return (KORE_RESULT_ERROR); } freeaddrinfo(results); if (listen(l->fd, kore_socket_backlog) == -1) { close(l->fd); kore_free(l); kore_debug("listen(): %s", errno_s); printf("failed to listen on socket: %s\n", errno_s); return (KORE_RESULT_ERROR); } if (ccb != NULL) { *(void **)&(l->connect) = kore_module_getsym(ccb); if (l->connect == NULL) { printf("no such callback: '%s'\n", ccb); close(l->fd); kore_free(l); return (KORE_RESULT_ERROR); } } else { l->connect = NULL; } nlisteners++; LIST_INSERT_HEAD(&listeners, l, list); if (foreground) { #if !defined(KORE_NO_TLS) kore_log(LOG_NOTICE, "running on https://%s:%s", ip, port); #else kore_log(LOG_NOTICE, "running on http://%s:%s", ip, port); #endif } return (KORE_RESULT_OK); } void kore_listener_cleanup(void) { struct listener *l; while (!LIST_EMPTY(&listeners)) { l = LIST_FIRST(&listeners); LIST_REMOVE(l, list); close(l->fd); kore_free(l); } } void kore_signal(int sig) { sig_recv = sig; } static void kore_server_sslstart(void) { #if !defined(KORE_NO_TLS) kore_debug("kore_server_sslstart()"); SSL_library_init(); SSL_load_error_strings(); #endif }
int kore_accesslog_write(const void *data, u_int32_t len) { int l; time_t now; ssize_t sent; struct kore_domain *dom; struct kore_log_packet logpacket; char addr[INET6_ADDRSTRLEN]; char *method, *buf, *tbuf, *cn; if (len != sizeof(struct kore_log_packet)) return (KORE_RESULT_ERROR); (void)memcpy(&logpacket, data, sizeof(logpacket)); if ((dom = kore_domain_lookup(logpacket.host)) == NULL) { kore_log(LOG_WARNING, "got accesslog packet for unknown domain: %s", logpacket.host); return (KORE_RESULT_OK); } switch (logpacket.method) { case HTTP_METHOD_GET: method = "GET"; break; case HTTP_METHOD_POST: method = "POST"; break; case HTTP_METHOD_PUT: method = "PUT"; break; case HTTP_METHOD_DELETE: method = "DELETE"; break; case HTTP_METHOD_HEAD: method = "HEAD"; break; default: method = "UNKNOWN"; break; } cn = "none"; #if !defined(KORE_NO_TLS) if (logpacket.cn[0] != '\0') cn = logpacket.cn; #endif if (inet_ntop(logpacket.addrtype, &(logpacket.addr), addr, sizeof(addr)) == NULL) (void)kore_strlcpy(addr, "unknown", sizeof(addr)); time(&now); tbuf = kore_time_to_date(now); l = asprintf(&buf, "[%s] %s %d %s %s (w#%d) (%dms) (%s) (%s)\n", tbuf, addr, logpacket.status, method, logpacket.path, logpacket.worker_id, logpacket.time_req, cn, logpacket.agent); if (l == -1) { kore_log(LOG_WARNING, "kore_accesslog_write(): asprintf() == -1"); return (KORE_RESULT_ERROR); } sent = write(dom->accesslog, buf, l); if (sent == -1) { free(buf); kore_log(LOG_WARNING, "kore_accesslog_write(): write(): %s", errno_s); return (KORE_RESULT_ERROR); } if (sent != l) kore_log(LOG_NOTICE, "accesslog: %s", buf); free(buf); return (KORE_RESULT_OK); }