libxt_string.c revision 9ee386a1b6d7704b259460152c959ab0e79e02aa
13071913784b69423fd25c3db2344e585872920ccEmmanuel Roger/* Shared library add-on to iptables to add string matching support. 23071913784b69423fd25c3db2344e585872920ccEmmanuel Roger * 33071913784b69423fd25c3db2344e585872920ccEmmanuel Roger * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be> 4764316a133db8e5e2d1f2a9d941ffae993d7c9d9András Kis-Szabó * 5c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira * 2005-08-05 Pablo Neira Ayuso <pablo@eurodev.net> 6c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira * - reimplemented to use new string matching iptables match 7c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira * - add functionality to match packets by using window offsets 8c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira * - add functionality to select the string matching algorithm 9c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira * 10764316a133db8e5e2d1f2a9d941ffae993d7c9d9András Kis-Szabó * ChangeLog 11b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash * 29.12.2003: Michael Rash <mbr@cipherdyne.org> 12b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash * Fixed iptables save/restore for ascii strings 13b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash * that contain space chars, and hex strings that 14b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash * contain embedded NULL chars. Updated to print 15b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash * strings in hex mode if any non-printable char 16b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash * is contained within the string. 17b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash * 18764316a133db8e5e2d1f2a9d941ffae993d7c9d9András Kis-Szabó * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk> 19764316a133db8e5e2d1f2a9d941ffae993d7c9d9András Kis-Szabó * Changed --tos to --string in save(). Also 20764316a133db8e5e2d1f2a9d941ffae993d7c9d9András Kis-Szabó * updated to work with slightly modified 21764316a133db8e5e2d1f2a9d941ffae993d7c9d9András Kis-Szabó * ipt_string_info. 223071913784b69423fd25c3db2344e585872920ccEmmanuel Roger */ 233071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <stdio.h> 243071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <netdb.h> 253071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <string.h> 263071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <stdlib.h> 273071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <getopt.h> 28f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash#include <ctype.h> 296ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI#include <xtables.h> 30c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira#include <stddef.h> 316ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI#include <linux/netfilter/xt_string.h> 323071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 333071913784b69423fd25c3db2344e585872920ccEmmanuel Roger/* Function which prints out usage message. */ 34181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_help(void) 353071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 363071913784b69423fd25c3db2344e585872920ccEmmanuel Roger printf( 373071913784b69423fd25c3db2344e585872920ccEmmanuel Roger"STRING match v%s options:\n" 38c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira"--from Offset to start searching from\n" 39c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira"--to Offset to stop searching\n" 40c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira"--algo Algorithm\n" 4196d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash"--string [!] string Match a string in a packet\n" 4296d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash"--hex-string [!] string Match a hex string in a packet\n", 4380fe35d6339b53a12ddaec41885613e4e37ed031Harald WelteIPTABLES_VERSION); 443071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 453071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 46181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic const struct option string_opts[] = { 47500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "from", 1, NULL, '1' }, 48500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "to", 1, NULL, '2' }, 49500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "algo", 1, NULL, '3' }, 50500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "string", 1, NULL, '4' }, 51500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "hex-string", 1, NULL, '5' }, 529ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann { .name = NULL } 533071913784b69423fd25c3db2344e585872920ccEmmanuel Roger}; 543071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 55181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_init(struct xt_entry_match *m) 56c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira{ 576ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI struct xt_string_info *i = (struct xt_string_info *) m->data; 58c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira 59c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (i->to_offset == 0) 60c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira i->to_offset = (u_int16_t) ~0UL; 61c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira} 62c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira 63c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neirastatic void 646ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAIparse_string(const char *s, struct xt_string_info *info) 653071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 666ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI if (strlen(s) <= XT_STRING_MAX_PATTERN_SIZE) { 676ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI strncpy(info->pattern, s, XT_STRING_MAX_PATTERN_SIZE); 68c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->patlen = strlen(s); 69c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira return; 70c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira } 71c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s); 7296d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash} 7396d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash 74c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neirastatic void 756ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAIparse_algo(const char *s, struct xt_string_info *info) 76c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira{ 776ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI if (strlen(s) <= XT_STRING_MAX_ALGO_NAME_SIZE) { 786ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI strncpy(info->algo, s, XT_STRING_MAX_ALGO_NAME_SIZE); 79c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira return; 80c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira } 81c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira exit_error(PARAMETER_PROBLEM, "ALGO too long `%s'", s); 82c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira} 83451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 8496d8593fffe816b3ee1bcd27df33beff5c404058Michael Rashstatic void 856ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAIparse_hex_string(const char *s, struct xt_string_info *info) 8696d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash{ 87f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash int i=0, slen, sindex=0, schar; 88f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash short hex_f = 0, literal_f = 0; 89f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash char hextmp[3]; 90f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 91f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash slen = strlen(s); 92f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 93f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (slen == 0) { 94f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash exit_error(PARAMETER_PROBLEM, 95f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "STRING must contain at least one char"); 96f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 97f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 98f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash while (i < slen) { 99f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (s[i] == '\\' && !hex_f) { 100f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash literal_f = 1; 101f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (s[i] == '\\') { 102f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash exit_error(PARAMETER_PROBLEM, 103f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Cannot include literals in hex data"); 104f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (s[i] == '|') { 105f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (hex_f) 106f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hex_f = 0; 107b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash else { 108f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hex_f = 1; 109b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* get past any initial whitespace just after the '|' */ 110b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash while (s[i+1] == ' ') 111b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash i++; 112b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 113f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) 114f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash break; 115f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash else 116f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i++; /* advance to the next character */ 117f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 118f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 119f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (literal_f) { 120f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) { 121f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash exit_error(PARAMETER_PROBLEM, 122f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Bad literal placement at end of string"); 123f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 124c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = s[i+1]; 125f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 2; /* skip over literal char */ 126f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash literal_f = 0; 127f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (hex_f) { 128f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) { 129f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash exit_error(PARAMETER_PROBLEM, 130f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Odd number of hex digits"); 131f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 132f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+2 >= slen) { 133f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash /* must end with a "|" */ 134f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash exit_error(PARAMETER_PROBLEM, "Invalid hex block"); 135f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 13696d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash if (! isxdigit(s[i])) /* check for valid hex char */ 13796d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash exit_error(PARAMETER_PROBLEM, "Invalid hex char `%c'", s[i]); 13896d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash if (! isxdigit(s[i+1])) /* check for valid hex char */ 13996d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash exit_error(PARAMETER_PROBLEM, "Invalid hex char `%c'", s[i+1]); 140f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[0] = s[i]; 141f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[1] = s[i+1]; 142f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[2] = '\0'; 143f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (! sscanf(hextmp, "%x", &schar)) 144f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash exit_error(PARAMETER_PROBLEM, 145f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Invalid hex char `%c'", s[i]); 146c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = (char) schar; 147f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (s[i+2] == ' ') 148f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 3; /* spaces included in the hex block */ 149f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash else 150f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 2; 151f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else { /* the char is not part of hex data, so just copy */ 152c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = s[i]; 153f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i++; 154f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 1556ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI if (sindex > XT_STRING_MAX_PATTERN_SIZE) 156f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s); 157f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash sindex++; 158f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 159c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->patlen = sindex; 1603071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 1613071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 162c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira#define STRING 0x1 163c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira#define ALGO 0x2 164c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira#define FROM 0x4 165c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira#define TO 0x8 166451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 1673071913784b69423fd25c3db2344e585872920ccEmmanuel Roger/* Function which parses command options; returns true if it 1683071913784b69423fd25c3db2344e585872920ccEmmanuel Roger ate an option */ 1693071913784b69423fd25c3db2344e585872920ccEmmanuel Rogerstatic int 170181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstring_parse(int c, char **argv, int invert, unsigned int *flags, 171181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt const void *entry, struct xt_entry_match **match) 1723071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 1736ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI struct xt_string_info *stringinfo = (struct xt_string_info *)(*match)->data; 1743071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 1753071913784b69423fd25c3db2344e585872920ccEmmanuel Roger switch (c) { 1763071913784b69423fd25c3db2344e585872920ccEmmanuel Roger case '1': 177c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (*flags & FROM) 178451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette exit_error(PARAMETER_PROBLEM, 179c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "Can't specify multiple --from"); 180c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira stringinfo->from_offset = atoi(optarg); 181c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira *flags |= FROM; 182c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira break; 183c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira case '2': 184c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (*flags & TO) 185c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira exit_error(PARAMETER_PROBLEM, 186c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "Can't specify multiple --to"); 187c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira stringinfo->to_offset = atoi(optarg); 188c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira *flags |= TO; 189c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira break; 190c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira case '3': 191c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (*flags & ALGO) 192c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira exit_error(PARAMETER_PROBLEM, 193c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "Can't specify multiple --algo"); 194c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira parse_algo(optarg, stringinfo); 195c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira *flags |= ALGO; 196c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira break; 197c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira case '4': 198c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (*flags & STRING) 199c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira exit_error(PARAMETER_PROBLEM, 200c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "Can't specify multiple --string"); 201b77f1dafb9f35752bb9685323bcacb32a0e6ddc5Harald Welte check_inverse(optarg, &invert, &optind, 0); 2023071913784b69423fd25c3db2344e585872920ccEmmanuel Roger parse_string(argv[optind-1], stringinfo); 2033071913784b69423fd25c3db2344e585872920ccEmmanuel Roger if (invert) 2043071913784b69423fd25c3db2344e585872920ccEmmanuel Roger stringinfo->invert = 1; 205c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira stringinfo->patlen=strlen((char *)&stringinfo->pattern); 206c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira *flags |= STRING; 20796d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash break; 20896d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash 209c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira case '5': 210c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (*flags & STRING) 211451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette exit_error(PARAMETER_PROBLEM, 212c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "Can't specify multiple --hex-string"); 213451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 21496d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash check_inverse(optarg, &invert, &optind, 0); 21596d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash parse_hex_string(argv[optind-1], stringinfo); /* sets length */ 21696d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash if (invert) 21796d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash stringinfo->invert = 1; 218c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira *flags |= STRING; 2193071913784b69423fd25c3db2344e585872920ccEmmanuel Roger break; 2203071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 2213071913784b69423fd25c3db2344e585872920ccEmmanuel Roger default: 2223071913784b69423fd25c3db2344e585872920ccEmmanuel Roger return 0; 2233071913784b69423fd25c3db2344e585872920ccEmmanuel Roger } 2243071913784b69423fd25c3db2344e585872920ccEmmanuel Roger return 1; 2253071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 2263071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 2273071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 2283071913784b69423fd25c3db2344e585872920ccEmmanuel Roger/* Final check; must have specified --string. */ 229181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_check(unsigned int flags) 2303071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 231c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (!(flags & STRING)) 232c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira exit_error(PARAMETER_PROBLEM, 233c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "STRING match: You must specify `--string' or " 234c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "`--hex-string'"); 235c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (!(flags & ALGO)) 2363071913784b69423fd25c3db2344e585872920ccEmmanuel Roger exit_error(PARAMETER_PROBLEM, 237c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "STRING match: You must specify `--algo'"); 2383071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 2393071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 240b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash/* Test to see if the string contains non-printable chars or quotes */ 241b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic unsigned short int 242b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashis_hex_string(const char *str, const unsigned short int len) 243b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 244b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 245b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) 246b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if (! isprint(str[i])) 247b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 1; /* string contains at least one non-printable char */ 248b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* use hex output if the last char is a "\" */ 249b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if ((unsigned char) str[len-1] == 0x5c) 250b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 1; 251b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 0; 252b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 253b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash 254b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash/* Print string with "|" chars included as one would pass to --hex-string */ 255b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic void 256b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashprint_hex_string(const char *str, const unsigned short int len) 257b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 258b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 259b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* start hex block */ 260b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("\"|"); 261b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) { 262b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* see if we need to prepend a zero */ 263b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if ((unsigned char) str[i] <= 0x0F) 264b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("0%x", (unsigned char) str[i]); 265b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash else 266b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("%x", (unsigned char) str[i]); 267b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 268b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* close hex block */ 269b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("|\" "); 270b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 271b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash 272b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic void 273b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashprint_string(const char *str, const unsigned short int len) 274b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 275b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 276b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("\""); 277b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) { 278b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if ((unsigned char) str[i] == 0x22) /* escape any embedded quotes */ 279b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("%c", 0x5c); 280b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("%c", (unsigned char) str[i]); 281b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 282b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("\" "); /* closing space and quote */ 283b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 284451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 2853071913784b69423fd25c3db2344e585872920ccEmmanuel Roger/* Prints out the matchinfo. */ 2863071913784b69423fd25c3db2344e585872920ccEmmanuel Rogerstatic void 287181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstring_print(const void *ip, const struct xt_entry_match *match, int numeric) 2883071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 2896ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI const struct xt_string_info *info = 2906ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI (const struct xt_string_info*) match->data; 291451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 292c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (is_hex_string(info->pattern, info->patlen)) { 293b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("STRING match %s", (info->invert) ? "!" : ""); 294c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_hex_string(info->pattern, info->patlen); 295b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } else { 296b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("STRING match %s", (info->invert) ? "!" : ""); 297c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_string(info->pattern, info->patlen); 298b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 299c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira printf("ALGO name %s ", info->algo); 300c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->from_offset != 0) 301c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira printf("FROM %u ", info->from_offset); 302c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->to_offset != 0) 3038a0b6ead35931422fbe02c63d9262ad9e40daaccPatrick McHardy printf("TO %u ", info->to_offset); 3043071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 3053071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 306451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 307451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette/* Saves the union ipt_matchinfo in parseable form to stdout. */ 308181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_save(const void *ip, const struct xt_entry_match *match) 3093071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 3106ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI const struct xt_string_info *info = 3116ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI (const struct xt_string_info*) match->data; 312451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 313c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (is_hex_string(info->pattern, info->patlen)) { 314b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("--hex-string %s", (info->invert) ? "! ": ""); 315c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_hex_string(info->pattern, info->patlen); 316b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } else { 317b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("--string %s", (info->invert) ? "! ": ""); 318c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_string(info->pattern, info->patlen); 319b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 320c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira printf("--algo %s ", info->algo); 321c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->from_offset != 0) 3220829a2b72caa06c07e6eb710a81a04295c9f2621Michael Rash printf("--from %u ", info->from_offset); 323c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->to_offset != 0) 3240829a2b72caa06c07e6eb710a81a04295c9f2621Michael Rash printf("--to %u ", info->to_offset); 3253071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 3263071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 327451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 328181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match string_match = { 329c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira .name = "string", 330181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .family = AF_INET, 331c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira .version = IPTABLES_VERSION, 3326ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI .size = XT_ALIGN(sizeof(struct xt_string_info)), 3336ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI .userspacesize = offsetof(struct xt_string_info, config), 334181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .help = string_help, 335181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .init = string_init, 336181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .parse = string_parse, 337181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .final_check = string_check, 338181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .print = string_print, 339181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .save = string_save, 340181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .extra_opts = string_opts, 3413071913784b69423fd25c3db2344e585872920ccEmmanuel Roger}; 3423071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 343451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 344181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match string_match6 = { 3454ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI .name = "string", 346181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .family = AF_INET6, 3474ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI .version = IPTABLES_VERSION, 3484ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI .size = XT_ALIGN(sizeof(struct xt_string_info)), 3494ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI .userspacesize = offsetof(struct xt_string_info, config), 350181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .help = string_help, 351181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .init = string_init, 352181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .parse = string_parse, 353181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .final_check = string_check, 354181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .print = string_print, 355181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .save = string_save, 356181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .extra_opts = string_opts, 3574ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI}; 3584ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI 3593071913784b69423fd25c3db2344e585872920ccEmmanuel Rogervoid _init(void) 3603071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 361181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt xtables_register_match(&string_match); 362181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt xtables_register_match(&string_match6); 3633071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 364