]> mj.ucw.cz Git - eval.git/blobdiff - submit/submitd.c
Added command-line clients for remote submit and status.
[eval.git] / submit / submitd.c
index a58ae69255bb4ff914c5bab27a5853ca4f3f7bed..b3c39280614d0e12ae8399b40ae0dd83dbace72e 100644 (file)
@@ -7,6 +7,7 @@
 /*
  *  FIXME:
  *     - competition timeout & per-contestant exceptions
 /*
  *  FIXME:
  *     - competition timeout & per-contestant exceptions
+ *     - open-data problems
  */
 
 #undef LOCAL_DEBUG
  */
 
 #undef LOCAL_DEBUG
@@ -14,8 +15,6 @@
 #include "lib/lib.h"
 #include "lib/conf.h"
 #include "lib/getopt.h"
 #include "lib/lib.h"
 #include "lib/conf.h"
 #include "lib/getopt.h"
-#include "lib/ipaccess.h"
-#include "lib/fastbuf.h"
 
 #include <string.h>
 #include <stdlib.h>
 
 #include <string.h>
 #include <stdlib.h>
@@ -27,8 +26,8 @@
 #include <sys/wait.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <sys/wait.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
-#include <gnutls/gnutls.h>
-#include <gnutls/x509.h>
+
+#include "submitd.h"
 
 /*** CONFIGURATION ***/
 
 
 /*** CONFIGURATION ***/
 
@@ -40,14 +39,10 @@ static byte *ca_cert_name = "?";
 static byte *server_cert_name = "?";
 static byte *server_key_name = "?";
 static clist access_rules;
 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),
 
 static struct cf_section access_conf = {
   CF_TYPE(struct access_rule),
@@ -60,41 +55,26 @@ static struct cf_section access_conf = {
   }
 };
 
   }
 };
 
-static byte *
-config_init(void)
-{
-  clist_init(&access_rules);
-  return NULL;
-}
-
 static struct cf_section submitd_conf = {
 static struct cf_section submitd_conf = {
-  CF_INIT(config_init),
   CF_ITEMS {
     CF_UNS("Port", &port),
     CF_UNS("DHBits", &dh_bits),
     CF_UNS("MaxConn", &max_conn),
     CF_UNS("SessionTimeout", &session_timeout),
   CF_ITEMS {
     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_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 ***/
 
     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;
 static clist connections;
 static uns last_conn_id;
 static uns num_conn;
@@ -108,7 +88,7 @@ conn_init(void)
 static struct conn *
 conn_new(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++;
   c->id = ++last_conn_id;
   clist_add_tail(&connections, &c->n);
   num_conn++;
@@ -118,6 +98,8 @@ conn_new(void)
 static void
 conn_free(struct conn *c)
 {
 static void
 conn_free(struct conn *c)
 {
+  xfree(c->ip_string);
+  xfree(c->cert_name);
   clist_remove(&c->n);
   num_conn--;
   xfree(c);
   clist_remove(&c->n);
   num_conn--;
   xfree(c);
@@ -187,8 +169,9 @@ tls_new_session(int sk)
 }
 
 static const char *
 }
 
 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;
   uns status, num_certs;
   int err;
   gnutls_x509_crt_t cert;
@@ -223,7 +206,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";
   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)
+    log(L_INFO, "Cert CN: %s", dn);
+  c->cert_name = xstrdup(dn);
 
   /* Check certificate purpose */
   byte purp[256];
 
   /* Check certificate purpose */
   byte purp[256];
@@ -244,8 +229,11 @@ tls_verify_cert(gnutls_session_t s)
 }
 
 static void
 }
 
 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 *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));
@@ -256,9 +244,9 @@ tls_log_params(gnutls_session_t s)
     proto, kx, cert, comp, cipher, mac);
 }
 
     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;
 client_error(char *msg, ...)
 {
   va_list args;
@@ -360,6 +348,7 @@ sigalrm_handler(int sig UNUSED)
 static void
 client_loop(struct conn *c)
 {
 static void
 client_loop(struct conn *c)
 {
+  setproctitle("submitd: client %s", c->ip_string);
   log_pid = c->id;
   init_sk_fastbufs(c);
 
   log_pid = c->id;
   init_sk_fastbufs(c);
 
@@ -383,21 +372,25 @@ client_loop(struct conn *c)
       int err = gnutls_handshake(c->tls);
       if (err < 0)
        client_error("TLS handshake failed: %s", gnutls_strerror(err));
       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);
     }
 
       if (cert_err)
        client_error("TLS certificate failure: %s", cert_err);
       init_tls_fastbufs(c);
     }
 
-  for (;;)
+  alarm(session_timeout);
+  if (!process_init(c))
+    log(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)
     }
 
   if (c->tls)
@@ -499,6 +492,7 @@ sk_accept(void)
        (rule->plain_text ? "plain-text" : "TLS"),
        (rule->allow_admin ? "admin" : "user"));
   c->ip = addr;
        (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;
 
   c->sk = sk;
   c->rule = rule;
 
@@ -537,6 +531,7 @@ int main(int argc, char **argv)
   setproctitle_init(argc, argv);
   cf_def_file = "config";
   cf_declare_section("SubmitD", &submitd_conf, 0);
   setproctitle_init(argc, argv);
   cf_def_file = "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)
 
   int opt;
   if ((opt = cf_getopt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL)) >= 0)
@@ -557,6 +552,7 @@ int main(int argc, char **argv)
 
   for (;;)
     {
 
   for (;;)
     {
+      setproctitle("submitd: %d connections", num_conn);
       int status;
       pid_t pid = waitpid(-1, &status, WNOHANG);
       if (pid > 0)
       int status;
       pid_t pid = waitpid(-1, &status, WNOHANG);
       if (pid > 0)