4 * (c) 2007 Martin Mares <mj@ucw.cz>
11 #include "lib/getopt.h"
18 #include <sys/types.h>
19 #include <sys/socket.h>
21 #include <arpa/inet.h>
22 #include <netinet/in.h>
26 /*** CONFIGURATION ***/
28 static char *log_name;
29 static uns port = 8888;
30 static uns dh_bits = 1024;
31 static uns max_conn = 10;
32 static uns session_timeout;
34 static char *ca_cert_name = "?";
35 static char *server_cert_name = "?";
36 static char *server_key_name = "?";
38 static clist access_rules;
41 uns max_attachment_size;
44 static struct cf_section ip_node_conf = {
45 CF_TYPE(struct ip_node),
47 CF_USER("IP", PTR_TO(struct ip_node, addrmask), &ip_addrmask_type),
52 static struct cf_section access_conf = {
53 CF_TYPE(struct access_rule),
55 CF_LIST("IP", PTR_TO(struct access_rule, ip_list), &ip_node_conf),
56 CF_UNS("Admin", PTR_TO(struct access_rule, allow_admin)),
57 CF_UNS("PlainText", PTR_TO(struct access_rule, plain_text)),
58 CF_UNS("MaxConn", PTR_TO(struct access_rule, max_conn)),
63 static struct cf_section submitd_conf = {
65 CF_STRING("LogFile", &log_name),
66 CF_UNS("Port", &port),
67 CF_UNS("DHBits", &dh_bits),
68 CF_UNS("MaxConn", &max_conn),
69 CF_UNS("SessionTimeout", &session_timeout),
70 CF_UNS("MaxRequestSize", &max_request_size),
71 CF_UNS("MaxAttachSize", &max_attachment_size),
72 CF_UNS("MaxVersions", &max_versions),
73 CF_STRING("CACert", &ca_cert_name),
74 CF_STRING("ServerCert", &server_cert_name),
75 CF_STRING("ServerKey", &server_key_name),
76 CF_STRING("History", &history_format),
77 CF_LIST("Access", &access_rules, &access_conf),
78 CF_UNS("TraceTLS", &trace_tls),
79 CF_UNS("TraceCommands", &trace_commands),
86 static clist connections;
87 static uns last_conn_id;
93 clist_init(&connections);
99 struct conn *c = xmalloc_zero(sizeof(*c));
100 c->id = ++last_conn_id;
101 clist_add_tail(&connections, &c->n);
107 conn_free(struct conn *c)
116 static struct access_rule *
119 CLIST_FOR_EACH(struct access_rule *, r, access_rules)
120 CLIST_FOR_EACH(struct ip_node *, n, r->ip_list)
121 if (ip_addrmask_match(&n->addrmask, ip))
130 CLIST_FOR_EACH(struct conn *, c, connections)
138 static gnutls_certificate_credentials_t cert_cred;
139 static gnutls_dh_params_t dh_params;
141 #define TLS_CHECK(name) if (err < 0) die(#name " failed: %s", gnutls_strerror(err))
148 gnutls_global_init();
149 err = gnutls_certificate_allocate_credentials(&cert_cred);
150 TLS_CHECK(gnutls_certificate_allocate_credentials);
151 err = gnutls_certificate_set_x509_trust_file(cert_cred, ca_cert_name, GNUTLS_X509_FMT_PEM);
153 die("No CA certificate found");
155 die("Unable to load X509 trust file: %s", gnutls_strerror(err));
156 err = gnutls_certificate_set_x509_key_file(cert_cred, server_cert_name, server_key_name, GNUTLS_X509_FMT_PEM);
158 die("Unable to load X509 key file: %s", gnutls_strerror(err));
160 err = gnutls_dh_params_init(&dh_params); TLS_CHECK(gnutls_dh_params_init);
161 err = gnutls_dh_params_generate2(dh_params, dh_bits); TLS_CHECK(gnutls_dh_params_generate2);
162 gnutls_certificate_set_dh_params(cert_cred, dh_params);
165 static gnutls_session_t
166 tls_new_session(int sk)
171 err = gnutls_init(&s, GNUTLS_SERVER); TLS_CHECK(gnutls_init);
172 err = gnutls_set_default_priority(s); TLS_CHECK(gnutls_set_default_priority);
173 gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, cert_cred);
174 gnutls_certificate_server_set_request(s, GNUTLS_CERT_REQUEST);
175 gnutls_dh_set_prime_bits(s, dh_bits);
176 gnutls_transport_set_ptr(s, (gnutls_transport_ptr_t) sk);
181 tls_verify_cert(struct conn *c)
183 gnutls_session_t s = c->tls;
184 uns status, num_certs;
186 gnutls_x509_crt_t cert;
187 const gnutls_datum_t *certs;
189 DBG("Verifying peer certificates");
190 err = gnutls_certificate_verify_peers2(s, &status);
192 return gnutls_strerror(err);
193 DBG("Verify status: %04x", status);
194 if (status & GNUTLS_CERT_INVALID)
195 return "Certificate is invalid";
196 /* XXX: We do not handle revokation. */
197 if (gnutls_certificate_type_get(s) != GNUTLS_CRT_X509)
198 return "Certificate is not X509";
200 err = gnutls_x509_crt_init(&cert);
202 return "gnutls_x509_crt_init() failed";
203 certs = gnutls_certificate_get_peers(s, &num_certs);
205 return "No peer certificate found";
206 DBG("Got certificate list with %d peers", num_certs);
208 err = gnutls_x509_crt_import(cert, &certs[0], GNUTLS_X509_FMT_DER);
210 return "Cannot import certificate";
211 /* XXX: We do not check expiration and activation since the keys are generated for a single contest only anyway. */
214 size_t dn_len = sizeof(dn);
215 err = gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, dn, &dn_len);
217 return "Cannot retrieve common name";
219 msg(L_INFO, "Cert CN: %s", dn);
220 c->cert_name = xstrdup(dn);
222 /* Check certificate purpose */
227 size_t purp_len = sizeof(purp);
229 err = gnutls_x509_crt_get_key_purpose_oid(cert, purpi++, purp, &purp_len, &crit);
230 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
231 return "Not a client certificate";
232 TLS_CHECK(gnutls_x509_crt_get_key_purpose_oid);
234 while (strcmp(purp, GNUTLS_KP_TLS_WWW_CLIENT));
241 tls_log_params(struct conn *c)
245 gnutls_session_t s = c->tls;
246 const char *proto = gnutls_protocol_get_name(gnutls_protocol_get_version(s));
247 const char *kx = gnutls_kx_get_name(gnutls_kx_get(s));
248 const char *cert = gnutls_certificate_type_get_name(gnutls_certificate_type_get(s));
249 const char *comp = gnutls_compression_get_name(gnutls_compression_get(s));
250 const char *cipher = gnutls_cipher_get_name(gnutls_cipher_get(s));
251 const char *mac = gnutls_mac_get_name(gnutls_mac_get(s));
252 msg(L_DEBUG, "TLS params: proto=%s kx=%s cert=%s comp=%s cipher=%s mac=%s",
253 proto, kx, cert, comp, cipher, mac);
256 /*** FASTBUFS OVER SOCKETS AND TLS ***/
258 void NONRET // Fatal protocol violation
259 client_error(char *msg, ...)
263 vmsg(L_ERROR_R, msg, args);
268 sk_fb_refill(struct fastbuf *f)
270 struct conn *c = SKIP_BACK(struct conn, rx_fb, f);
271 int cnt = read(c->sk, f->buffer, f->bufend - f->buffer);
273 client_error("Read error: %m");
275 f->bstop = f->buffer + cnt;
280 sk_fb_spout(struct fastbuf *f)
282 struct conn *c = SKIP_BACK(struct conn, tx_fb, f);
283 int len = f->bptr - f->buffer;
286 int cnt = careful_write(c->sk, f->buffer, len);
288 client_error("Write error");
293 init_sk_fastbufs(struct conn *c)
295 struct fastbuf *rf = &c->rx_fb, *tf = &c->tx_fb;
297 rf->buffer = xmalloc(1024);
298 rf->bufend = rf->buffer + 1024;
299 rf->bptr = rf->bstop = rf->buffer;
301 rf->refill = sk_fb_refill;
303 tf->buffer = xmalloc(1024);
304 tf->bufend = tf->buffer + 1024;
305 tf->bptr = tf->bstop = tf->buffer;
307 tf->spout = sk_fb_spout;
311 tls_fb_refill(struct fastbuf *f)
313 struct conn *c = SKIP_BACK(struct conn, rx_fb, f);
315 int cnt = gnutls_record_recv(c->tls, f->buffer, f->bufend - f->buffer);
316 DBG("TLS: Received %d bytes", cnt);
318 client_error("TLS read error: %s", gnutls_strerror(cnt));
320 f->bstop = f->buffer + cnt;
325 tls_fb_spout(struct fastbuf *f)
327 struct conn *c = SKIP_BACK(struct conn, tx_fb, f);
328 int len = f->bptr - f->buffer;
331 int cnt = gnutls_record_send(c->tls, f->buffer, len);
332 DBG("TLS: Sent %d bytes", cnt);
334 client_error("TLS write error: %s", gnutls_strerror(cnt));
339 init_tls_fastbufs(struct conn *c)
341 struct fastbuf *rf = &c->rx_fb, *tf = &c->tx_fb;
343 ASSERT(rf->buffer && tf->buffer); // Already set up for the plaintext connection
344 rf->refill = tls_fb_refill;
345 tf->spout = tls_fb_spout;
348 /*** CLIENT LOOP (runs in a child process) ***/
351 sigalrm_handler(int sig UNUSED)
353 // We do not try to do any gracious shutdown to avoid races
354 client_error("Timed out");
358 client_loop(struct conn *c)
360 setproctitle("submitd: client %s", c->ip_string);
364 signal(SIGPIPE, SIG_IGN);
365 struct sigaction sa = {
366 .sa_handler = sigalrm_handler
368 if (sigaction(SIGALRM, &sa, NULL) < 0)
369 die("Cannot setup SIGALRM handler: %m");
371 if (c->rule->plain_text)
373 bputsn(&c->tx_fb, "+OK");
378 bputsn(&c->tx_fb, "+TLS");
380 c->tls = tls_new_session(c->sk);
381 int err = gnutls_handshake(c->tls);
383 client_error("TLS handshake failed: %s", gnutls_strerror(err));
385 const char *cert_err = tls_verify_cert(c);
387 client_error("TLS certificate failure: %s", cert_err);
388 init_tls_fastbufs(c);
391 alarm(session_timeout);
392 if (!process_init(c))
393 msg(L_ERROR, "Protocol handshake failed");
396 setproctitle("submitd: client %s (%s)", c->ip_string, c->user);
399 alarm(session_timeout);
400 if (!process_command(c))
406 gnutls_bye(c->tls, GNUTLS_SHUT_WR);
409 gnutls_deinit(c->tls);
415 sigchld_handler(int sig UNUSED)
417 /* We do not need to do anything, just interrupt the accept syscall */
421 reap_child(pid_t pid, int status)
423 char buf[EXIT_STATUS_MSG_SIZE];
424 if (format_exit_status(buf, status))
425 msg(L_ERROR, "Child %d %s", (int)pid, buf);
427 CLIST_FOR_EACH(struct conn *, c, connections)
430 msg(L_INFO, "Connection %d closed", c->id);
434 msg(L_ERROR, "Cannot find connection for child process %d", (int)pid);
437 static int listen_sk;
442 listen_sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
446 if (setsockopt(listen_sk, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
447 die("setsockopt(SO_REUSEADDR): %m");
449 struct sockaddr_in sa;
450 bzero(&sa, sizeof(sa));
451 sa.sin_family = AF_INET;
452 sa.sin_addr.s_addr = INADDR_ANY;
453 sa.sin_port = htons(port);
454 if (bind(listen_sk, (struct sockaddr *) &sa, sizeof(sa)) < 0)
455 die("Cannot bind to port %d: %m", port);
456 if (listen(listen_sk, 1024) < 0)
457 die("Cannot listen on port %d: %m", port);
463 struct sockaddr_in sa;
464 int salen = sizeof(sa);
465 int sk = accept(listen_sk, (struct sockaddr *) &sa, &salen);
473 char ipbuf[INET_ADDRSTRLEN];
474 inet_ntop(AF_INET, &sa.sin_addr, ipbuf, sizeof(ipbuf));
475 u32 addr = ntohl(sa.sin_addr.s_addr);
476 uns port = ntohs(sa.sin_port);
479 struct access_rule *rule = lookup_rule(addr);
482 err = "Unauthorized";
486 if (num_conn >= max_conn)
488 err = "Too many connections";
492 if (conn_count(addr) >= rule->max_conn)
494 err = "Too many connections from this address";
498 struct conn *c = conn_new();
499 msg(L_INFO, "Connection from %s:%d (id %d, %s, %s)",
501 (rule->plain_text ? "plain-text" : "TLS"),
502 (rule->allow_admin ? "admin" : "user"));
504 c->ip_string = xstrdup(ipbuf);
512 err = "Server overloaded";
513 msg(L_ERROR, "Fork failed: %m");
526 msg(L_ERROR_R, "Connection from %s:%d rejected (%s)", ipbuf, port, err);
528 // Write an error message to the socket, but do not allow it to slow us down
529 struct linger ling = { .l_onoff=0 };
530 if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)) < 0)
531 msg(L_ERROR, "Cannot set SO_LINGER: %m");
533 write(sk, err, strlen(err));
538 int main(int argc, char **argv)
540 setproctitle_init(argc, argv);
541 cf_def_file = "cf/submitd";
542 cf_declare_section("SubmitD", &submitd_conf, 0);
543 cf_declare_section("Tasks", &tasks_conf, 0);
546 if ((opt = cf_getopt(argc, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL)) >= 0)
547 die("This program has no options");
551 msg(L_INFO, "Initializing TLS");
556 msg(L_INFO, "Listening on port %d", port);
558 struct sigaction sa = {
559 .sa_handler = sigchld_handler
561 if (sigaction(SIGCHLD, &sa, NULL) < 0)
562 die("Cannot setup SIGCHLD handler: %m");
566 setproctitle("submitd: %d connections", num_conn);
568 pid_t pid = waitpid(-1, &status, WNOHANG);
570 reap_child(pid, status);