diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0f95713 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +addons: + apt: + update: true + packages: + - libnetfilter-queue-dev +dist: xenial +language: c +compiler: + - clang + - gcc +before_script: + - mkdir build +script: + - cd build + - cmake .. + - make -j2 diff --git a/CHANGELOG.md b/CHANGELOG.md index fedb047..562f36f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## 0.5.3 - 2019-08-06 +### Fixed +- Fix two format arguments in debug output printing (fairly pedantic; not even + caught by clang analyser). +- Limit DHCP options to 255 bytes (not 256). +- Exit if a DHCP option is too long. + ## 0.5.2 - 2019-05-09 ### Added - Add example output "screenshot" to README. diff --git a/CMakeLists.txt b/CMakeLists.txt index 4770252..e8730e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ endif() project( ${PROJECT} - VERSION 0.5.2 + VERSION 0.5.3 DESCRIPTION "DHCP option injector" LANGUAGES C ) diff --git a/README.md b/README.md index 44bbded..d1501ed 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # DHCP option injector +[![Build Status](https://travis-ci.org/misje/dhcpoptinj.svg?branch=dev)](https://travis-ci.org/misje/dhcpoptinj) [![Total alerts](https://img.shields.io/lgtm/alerts/g/misje/dhcpoptinj.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/misje/dhcpoptinj/alerts/) Have you ever wanted to intercept DHCP requests and squeeze in a few extra DHCP options, unbeknownst to the sender? Probably not. However, should the need ever @@ -104,13 +105,13 @@ Sending mangled packet ``` ## Installing +[![Packaging status](https://repology.org/badge/vertical-allrepos/dhcpoptinj.svg)](https://repology.org/project/dhcpoptinj/versions) -dhcpoptinj is submitted to Debian and will hopefully make it to unstable (and -consequently testing and stable) in not too long. The deb package is under -source control at [salsa](https://salsa.debian.org/misje-guest/dhcpoptinj). -Installing dhcpoptinj from the deb package is recommended over the following -manual installation procedure, because it also includes a man page, bash -completion rules, example files etc. +dhcpoptinj is in Debian/Ubuntu. The deb package is under source control at +[salsa](https://salsa.debian.org/misje-guest/dhcpoptinj). Installing +dhcpoptinj from the deb package is recommended over the following manual +installation procedure, because it also includes a man page, bash completion +rules, example files etc. ### Prerequisites diff --git a/src/config.c b/src/config.c index f307c78..539de8d 100644 --- a/src/config.c +++ b/src/config.c @@ -317,7 +317,7 @@ static void printHelp(void) "The option hex string is written as a series of two-digit pairs,\n" "optionally delimited by one or more non-hexadecimal characters:\n" "'466A6173','46 6A 61 73', '46:6A:61:73' etc. There is a maximum limit\n" - "of 256 bytes per option, excluding the option code (the first byte)\n" + "of 255 bytes per option, excluding the option code (the first byte)\n" "and the automatically inserted length byte. At least one option must\n" "be provided.\n" "\n" @@ -371,8 +371,8 @@ static void addDHCPOption(struct DHCPOptList *list, const char *string) if (!string) return; - /* Make room for length byte and payload */ - uint8_t buffer[1 + 256]; + /* Make room for option code byte and payload */ + uint8_t buffer[1 + UINT8_MAX]; size_t length = 0; for (size_t i = 0; i < strlen(string) && length < sizeof(buffer);) { @@ -384,8 +384,15 @@ static void addDHCPOption(struct DHCPOptList *list, const char *string) else ++i; } + /* Will not happen; the cmd.line parsing code expects an argument: */ if (!length) return; + if (length > UINT8_MAX) + { + fprintf(stderr, "DHCP option size exceeds the limit of %u bytes\n", + UINT8_MAX); + exit(EXIT_FAILURE); + } uint16_t optCode = buffer[0]; @@ -522,6 +529,7 @@ static void parseOption(struct Config *config, int option, char *arg, enum Sourc fputs("Could not allocate space for PID file name\n", stderr); exit(EXIT_FAILURE); } + // NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.strcpy) strcpy(config->pidFile, src); } break; diff --git a/src/dhcpoptinj.c b/src/dhcpoptinj.c index b4fdb89..8c4c0fc 100644 --- a/src/dhcpoptinj.c +++ b/src/dhcpoptinj.c @@ -500,6 +500,7 @@ static void logMessage(int priority, const char *format, ...) if (priority == LOG_NOTICE || priority == LOG_INFO || priority == LOG_DEBUG) f = stdout; + /* NOLINTNEXTLINE(clang-analyzer-valist.Uninitialized) */ vfprintf(f, format, args1); } va_end(args1); @@ -586,7 +587,7 @@ static void debugLogOptions(void) if (!config->debug) return; - logMessage(LOG_DEBUG, "%u DHCP option(s) to inject (with a total of %zu bytes): ", + logMessage(LOG_DEBUG, "%zu DHCP option(s) to inject (with a total of %zu bytes): ", config->dhcpOptCodeCount, config->dhcpOptsSize); for (size_t i = 0; i < config->dhcpOptCodeCount; ++i) @@ -654,9 +655,9 @@ static void debugLogOptionFound(const struct DHCPOption *option) static void debugLogOption(const char *action, const struct DHCPOption *option) { - /* String buffer for hex string (maximum DHCP option length (256) times + /* String buffer for hex string (maximum DHCP option length (255) times * three characters (two digits and a space)) */ - char optPayload[256 * 3]; + char optPayload[UINT8_MAX * 3]; size_t i = 0; for (; i < option->length; ++i) sprintf(optPayload + 3*i, "%02X ", option->data[i]); @@ -673,7 +674,7 @@ static void debugLogOption(const char *action, const struct DHCPOption *option) option->code, option->code, optName, - optNameLen > alignedWidth ? 0 : alignedWidth - optNameLen, + (int)(optNameLen > alignedWidth ? 0 : alignedWidth - optNameLen), "", option->length, optPayload); diff --git a/src/options.c b/src/options.c index c23c887..846db5b 100644 --- a/src/options.c +++ b/src/options.c @@ -28,7 +28,7 @@ struct DHCPOpt { uint8_t code; uint8_t length; - uint8_t data[256]; + uint8_t data[UINT8_MAX]; }; struct DHCPOptList