X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=submit%2Fsubmitd.c;h=e8578f601437ee06ca87ddea4506b77c56d6be00;hb=6324cb417d421274a384cfae916b039cbe56d6e0;hp=a58ae69255bb4ff914c5bab27a5853ca4f3f7bed;hpb=4d6c0022e700db3c7584ad5b58bbda69090ecf0d;p=moe.git diff --git a/submit/submitd.c b/submit/submitd.c index a58ae69..e8578f6 100644 --- a/submit/submitd.c +++ b/submit/submitd.c @@ -4,18 +4,11 @@ * (c) 2007 Martin Mares */ -/* - * FIXME: - * - competition timeout & per-contestant exceptions - */ - #undef LOCAL_DEBUG #include "lib/lib.h" #include "lib/conf.h" #include "lib/getopt.h" -#include "lib/ipaccess.h" -#include "lib/fastbuf.h" #include #include @@ -27,11 +20,12 @@ #include #include #include -#include -#include + +#include "submitd.h" /*** CONFIGURATION ***/ +static byte *log_name; static uns port = 8888; static uns dh_bits = 1024; static uns max_conn = 10; @@ -40,14 +34,10 @@ static byte *ca_cert_name = "?"; static byte *server_cert_name = "?"; static byte *server_key_name = "?"; static clist access_rules; - -struct access_rule { - cnode n; - struct ip_addrmask addrmask; - uns allow_admin; - uns plain_text; - uns max_conn; -}; +static uns trace_tls; +uns max_request_size; +uns max_attachment_size; +uns trace_commands; static struct cf_section access_conf = { CF_TYPE(struct access_rule), @@ -60,41 +50,27 @@ static struct cf_section access_conf = { } }; -static byte * -config_init(void) -{ - clist_init(&access_rules); - return NULL; -} - static struct cf_section submitd_conf = { - CF_INIT(config_init), CF_ITEMS { + CF_STRING("LogFile", &log_name), CF_UNS("Port", &port), CF_UNS("DHBits", &dh_bits), CF_UNS("MaxConn", &max_conn), CF_UNS("SessionTimeout", &session_timeout), + CF_UNS("MaxRequestSize", &max_request_size), + CF_UNS("MaxAttachSize", &max_attachment_size), CF_STRING("CACert", &ca_cert_name), CF_STRING("ServerCert", &server_cert_name), CF_STRING("ServerKey", &server_key_name), CF_LIST("Access", &access_rules, &access_conf), + CF_UNS("TraceTLS", &trace_tls), + CF_UNS("TraceCommands", &trace_commands), CF_END } }; /*** CONNECTIONS ***/ -struct conn { - cnode n; - u32 ip; // Used by the main loop connection logic - pid_t pid; - uns id; - struct access_rule *rule; // Rule matched by this connection - int sk; // Client socket - gnutls_session_t tls; // TLS session - struct fastbuf rx_fb, tx_fb; // Fastbufs for communication with the client -}; - static clist connections; static uns last_conn_id; static uns num_conn; @@ -108,7 +84,7 @@ conn_init(void) static struct conn * conn_new(void) { - struct conn *c = xmalloc(sizeof(*c)); + struct conn *c = xmalloc_zero(sizeof(*c)); c->id = ++last_conn_id; clist_add_tail(&connections, &c->n); num_conn++; @@ -118,6 +94,8 @@ conn_new(void) static void conn_free(struct conn *c) { + xfree(c->ip_string); + xfree(c->cert_name); clist_remove(&c->n); num_conn--; xfree(c); @@ -187,8 +165,9 @@ tls_new_session(int sk) } static const char * -tls_verify_cert(gnutls_session_t s) +tls_verify_cert(struct conn *c) { + gnutls_session_t s = c->tls; uns status, num_certs; int err; gnutls_x509_crt_t cert; @@ -223,7 +202,9 @@ tls_verify_cert(gnutls_session_t s) err = gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, dn, &dn_len); if (err < 0) return "Cannot retrieve common name"; - log(L_INFO, "Cert CN: %s", dn); + if (trace_tls) + msg(L_INFO, "Cert CN: %s", dn); + c->cert_name = xstrdup(dn); /* Check certificate purpose */ byte purp[256]; @@ -244,26 +225,29 @@ tls_verify_cert(gnutls_session_t s) } static void -tls_log_params(gnutls_session_t s) +tls_log_params(struct conn *c) { + if (!trace_tls) + return; + gnutls_session_t s = c->tls; const char *proto = gnutls_protocol_get_name(gnutls_protocol_get_version(s)); const char *kx = gnutls_kx_get_name(gnutls_kx_get(s)); const char *cert = gnutls_certificate_type_get_name(gnutls_certificate_type_get(s)); const char *comp = gnutls_compression_get_name(gnutls_compression_get(s)); const char *cipher = gnutls_cipher_get_name(gnutls_cipher_get(s)); const char *mac = gnutls_mac_get_name(gnutls_mac_get(s)); - log(L_DEBUG, "TLS params: proto=%s kx=%s cert=%s comp=%s cipher=%s mac=%s", + msg(L_DEBUG, "TLS params: proto=%s kx=%s cert=%s comp=%s cipher=%s mac=%s", proto, kx, cert, comp, cipher, mac); } -/*** SOCKET FASTBUFS ***/ +/*** FASTBUFS OVER SOCKETS AND TLS ***/ -static void NONRET +void NONRET // Fatal protocol violation client_error(char *msg, ...) { va_list args; va_start(args, msg); - vlog_msg(L_ERROR_R, msg, args); + vmsg(L_ERROR_R, msg, args); exit(0); } @@ -360,6 +344,7 @@ sigalrm_handler(int sig UNUSED) static void client_loop(struct conn *c) { + setproctitle("submitd: client %s", c->ip_string); log_pid = c->id; init_sk_fastbufs(c); @@ -383,21 +368,25 @@ client_loop(struct conn *c) int err = gnutls_handshake(c->tls); if (err < 0) client_error("TLS handshake failed: %s", gnutls_strerror(err)); - tls_log_params(c->tls); - const char *cert_err = tls_verify_cert(c->tls); + tls_log_params(c); + const char *cert_err = tls_verify_cert(c); if (cert_err) client_error("TLS certificate failure: %s", cert_err); init_tls_fastbufs(c); } - for (;;) + alarm(session_timeout); + if (!process_init(c)) + msg(L_ERROR, "Protocol handshake failed"); + else { - alarm(session_timeout); - byte buf[1024]; - if (!bgets(&c->rx_fb, buf, sizeof(buf))) - break; - bputsn(&c->tx_fb, buf); - bflush(&c->tx_fb); + setproctitle("submitd: client %s (%s)", c->ip_string, c->user); + for (;;) + { + alarm(session_timeout); + if (!process_command(c)) + break; + } } if (c->tls) @@ -418,18 +407,18 @@ sigchld_handler(int sig UNUSED) static void reap_child(pid_t pid, int status) { - byte msg[EXIT_STATUS_MSG_SIZE]; - if (format_exit_status(msg, status)) - log(L_ERROR, "Child %d %s", (int)pid, msg); + byte buf[EXIT_STATUS_MSG_SIZE]; + if (format_exit_status(buf, status)) + msg(L_ERROR, "Child %d %s", (int)pid, buf); CLIST_FOR_EACH(struct conn *, c, connections) if (c->pid == pid) { - log(L_INFO, "Connection %d closed", c->id); + msg(L_INFO, "Connection %d closed", c->id); conn_free(c); return; } - log(L_ERROR, "Cannot find connection for child process %d", (int)pid); + msg(L_ERROR, "Cannot find connection for child process %d", (int)pid); } static int listen_sk; @@ -494,11 +483,12 @@ sk_accept(void) } struct conn *c = conn_new(); - log(L_INFO, "Connection from %s:%d (id %d, %s, %s)", + msg(L_INFO, "Connection from %s:%d (id %d, %s, %s)", ipbuf, port, c->id, (rule->plain_text ? "plain-text" : "TLS"), (rule->allow_admin ? "admin" : "user")); c->ip = addr; + c->ip_string = xstrdup(ipbuf); c->sk = sk; c->rule = rule; @@ -507,7 +497,7 @@ sk_accept(void) { conn_free(c); err = "Server overloaded"; - log(L_ERROR, "Fork failed: %m"); + msg(L_ERROR, "Fork failed: %m"); goto reject2; } if (!c->pid) @@ -520,12 +510,12 @@ sk_accept(void) return; reject: - log(L_ERROR_R, "Connection from %s:%d rejected (%s)", ipbuf, port, err); + msg(L_ERROR_R, "Connection from %s:%d rejected (%s)", ipbuf, port, err); reject2: ; // Write an error message to the socket, but do not allow it to slow us down struct linger ling = { .l_onoff=0 }; if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)) < 0) - log(L_ERROR, "Cannot set SO_LINGER: %m"); + msg(L_ERROR, "Cannot set SO_LINGER: %m"); write(sk, "-", 1); write(sk, err, strlen(err)); write(sk, "\n", 1); @@ -535,19 +525,22 @@ reject2: ; int main(int argc, char **argv) { setproctitle_init(argc, argv); - cf_def_file = "config"; + cf_def_file = "submit/config"; cf_declare_section("SubmitD", &submitd_conf, 0); + cf_declare_section("Tasks", &tasks_conf, 0); int opt; if ((opt = cf_getopt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL)) >= 0) die("This program has no options"); - log(L_INFO, "Initializing TLS"); + log_file(log_name); + + msg(L_INFO, "Initializing TLS"); tls_init(); conn_init(); sk_init(); - log(L_INFO, "Listening on port %d", port); + msg(L_INFO, "Listening on port %d", port); struct sigaction sa = { .sa_handler = sigchld_handler @@ -557,6 +550,7 @@ int main(int argc, char **argv) for (;;) { + setproctitle("submitd: %d connections", num_conn); int status; pid_t pid = waitpid(-1, &status, WNOHANG); if (pid > 0)