summaryrefslogtreecommitdiff
path: root/ct_servmgmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'ct_servmgmt.c')
-rw-r--r--ct_servmgmt.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/ct_servmgmt.c b/ct_servmgmt.c
new file mode 100644
index 0000000..a63eb57
--- /dev/null
+++ b/ct_servmgmt.c
@@ -0,0 +1,278 @@
+/*
+ * netsniff-ng - the packet sniffing beast
+ * Copyright 2011 Daniel Borkmann.
+ * Subject to the GPL, version 2.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <syslog.h>
+
+#include "die.h"
+#include "built_in.h"
+#include "locking.h"
+#include "xmalloc.h"
+#include "curvetun.h"
+#include "xutils.h"
+#include "curve.h"
+#include "ct_servmgmt.h"
+#include "crypto_box_curve25519xsalsa20poly1305.h"
+#include "crypto_auth_hmacsha512256.h"
+
+#define crypto_box_pub_key_size crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
+
+/* Config line format: alias;serverip|servername;port;udp|tcp;pubkey\n */
+
+struct server_store {
+ int udp;
+ char alias[256];
+ char host[256];
+ char port[6]; /* 5 + \0 */
+ unsigned char publickey[crypto_box_pub_key_size];
+ struct curve25519_proto proto_inf;
+ unsigned char auth_token[crypto_auth_hmacsha512256_KEYBYTES];
+ struct server_store *next;
+};
+
+static struct server_store *store = NULL;
+static struct server_store *selected = NULL;
+static struct rwlock store_lock;
+
+static struct server_store *server_store_alloc(void)
+{
+ return xzmalloc(sizeof(struct server_store));
+}
+
+static void server_store_free(struct server_store *ss)
+{
+ if (!ss)
+ return;
+ memset(ss, 0, sizeof(struct server_store));
+ xfree(ss);
+}
+
+enum parse_states {
+ PARSE_ALIAS,
+ PARSE_SERVER,
+ PARSE_PORT,
+ PARSE_CARRIER,
+ PARSE_PUBKEY,
+ PARSE_DONE,
+};
+
+static int parse_line(char *line, char *homedir)
+{
+ int ret;
+ char *str;
+ enum parse_states s = PARSE_ALIAS;
+ struct server_store *elem;
+ unsigned char pkey[crypto_box_pub_key_size];
+
+ elem = server_store_alloc();
+ elem->next = store;
+
+ str = strtok(line, ";");
+ for (; str != NULL;) {
+ switch (s) {
+ case PARSE_ALIAS:
+ strlcpy(elem->alias, str, sizeof(elem->alias));
+ s = PARSE_SERVER;
+ break;
+ case PARSE_SERVER:
+ strlcpy(elem->host, str, sizeof(elem->host));
+ s = PARSE_PORT;
+ break;
+ case PARSE_PORT:
+ strlcpy(elem->port, str, sizeof(elem->port));
+ s = PARSE_CARRIER;
+ break;
+ case PARSE_CARRIER:
+ if (!strncmp("udp", str, strlen("udp")))
+ elem->udp = 1;
+ else if (!strncmp("tcp", str, strlen("tcp")))
+ elem->udp = 0;
+ else {
+ syslog(LOG_ERR, "Incorrect carrier type !(udp|tcp) in server spec.\n");
+ return -EIO;
+ }
+ s = PARSE_PUBKEY;
+ break;
+ case PARSE_PUBKEY:
+ if (!curve25519_pubkey_hexparse_32(pkey, sizeof(pkey),
+ str, strlen(str)))
+ return -EINVAL;
+ memcpy(elem->publickey, pkey, sizeof(elem->publickey));
+ memcpy(elem->auth_token, pkey, sizeof(elem->auth_token));
+ ret = curve25519_proto_init(&elem->proto_inf,
+ elem->publickey,
+ sizeof(elem->publickey),
+ homedir, 1);
+ if (ret)
+ return -EIO;
+ s = PARSE_DONE;
+ break;
+ case PARSE_DONE:
+ break;
+ default:
+ return -EIO;
+ }
+
+ str = strtok(NULL, ";");
+ }
+
+ store = elem;
+ return s == PARSE_DONE ? 0 : -EIO;
+}
+
+void parse_userfile_and_generate_serv_store_or_die(char *homedir)
+{
+ FILE *fp;
+ char path[PATH_MAX], buff[1024];
+ int line = 1, ret;
+
+ memset(path, 0, sizeof(path));
+ slprintf(path, sizeof(path), "%s/%s", homedir, FILE_SERVERS);
+
+ rwlock_init(&store_lock);
+ rwlock_wr_lock(&store_lock);
+
+ fp = fopen(path, "r");
+ if (!fp)
+ panic("Cannot open server file!\n");
+
+ memset(buff, 0, sizeof(buff));
+ while (fgets(buff, sizeof(buff), fp) != NULL) {
+ buff[sizeof(buff) - 1] = 0;
+ /* A comment. Skip this line */
+ if (buff[0] == '#' || buff[0] == '\n') {
+ memset(buff, 0, sizeof(buff));
+ line++;
+ continue;
+ }
+
+ ret = parse_line(buff, homedir);
+ if (ret < 0)
+ panic("Cannot parse line %d from clients!\n", line);
+ line++;
+ memset(buff, 0, sizeof(buff));
+ }
+
+ fclose(fp);
+
+ if (store == NULL)
+ panic("No registered servers found!\n");
+
+ rwlock_unlock(&store_lock);
+}
+
+void dump_serv_store(void)
+{
+ int i;
+ struct server_store *elem;
+
+ rwlock_rd_lock(&store_lock);
+ elem = store;
+ while (elem) {
+ printf("[%s] -> %s:%s via %s -> ", elem->alias,
+ elem->host, elem->port,
+ elem->udp ? "udp" : "tcp");
+ for (i = 0; i < sizeof(elem->publickey); ++i)
+ if (i == (sizeof(elem->publickey) - 1))
+ printf("%02x\n", (unsigned char)
+ elem->publickey[i]);
+ else
+ printf("%02x:", (unsigned char)
+ elem->publickey[i]);
+ elem = elem->next;
+ }
+ rwlock_unlock(&store_lock);
+}
+
+void destroy_serv_store(void)
+{
+ struct server_store *elem, *nelem = NULL;
+
+ rwlock_wr_lock(&store_lock);
+ selected = NULL;
+ elem = store;
+ while (elem) {
+ nelem = elem->next;
+ elem->next = NULL;
+ server_store_free(elem);
+ elem = nelem;
+ }
+ rwlock_unlock(&store_lock);
+ rwlock_destroy(&store_lock);
+}
+
+void get_serv_store_entry_by_alias(char *alias, size_t len,
+ char **host, char **port, int *udp)
+{
+ struct server_store *elem;
+
+ rwlock_rd_lock(&store_lock);
+ elem = store;
+ if (!alias) {
+ while (elem && elem->next)
+ elem = elem->next;
+ if (elem) {
+ (*host) = elem->host;
+ (*port) = elem->port;
+ (*udp) = elem->udp;
+ selected = elem;
+ } else {
+ rwlock_unlock(&store_lock);
+ goto nothing;
+ }
+ } else {
+ while (elem) {
+ if (!strncmp(elem->alias, alias,
+ min(len, strlen(elem->alias) + 1)))
+ break;
+ elem = elem->next;
+ }
+ if (elem) {
+ (*host) = elem->host;
+ (*port) = elem->port;
+ (*udp) = elem->udp;
+ selected = elem;
+ } else {
+ rwlock_unlock(&store_lock);
+ goto nothing;
+ }
+ }
+ rwlock_unlock(&store_lock);
+
+ return;
+nothing:
+ (*host) = NULL;
+ (*port) = NULL;
+ (*udp) = -1;
+}
+
+struct curve25519_proto *get_serv_store_entry_proto_inf(void)
+{
+ struct curve25519_proto *ret = NULL;
+
+ rwlock_rd_lock(&store_lock);
+ if (selected)
+ ret = &selected->proto_inf;
+ rwlock_unlock(&store_lock);
+
+ return ret;
+}
+
+unsigned char *get_serv_store_entry_auth_token(void)
+{
+ unsigned char *ret = NULL;
+
+ rwlock_rd_lock(&store_lock);
+ if (selected)
+ ret = selected->auth_token;
+ rwlock_unlock(&store_lock);
+
+ return ret;
+}