libxt_string.c revision 1829ed482efbc8b390cc760d012b3a4450494e1a
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 */ 2337b4bde745698bf140d74e59a2561f34deeb8726Jan Engelhardt#define _GNU_SOURCE 1 243071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <stdio.h> 253071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <netdb.h> 263071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <string.h> 273071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <stdlib.h> 283071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <getopt.h> 29f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash#include <ctype.h> 306ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI#include <xtables.h> 31c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira#include <stddef.h> 326ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI#include <linux/netfilter/xt_string.h> 333071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 34181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_help(void) 353071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 363071913784b69423fd25c3db2344e585872920ccEmmanuel Roger printf( 378b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"string match options:\n" 38c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira"--from Offset to start searching from\n" 39c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira"--to Offset to stop searching\n" 4078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park"--algo Algorithm\n" 4178d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park"--icase Ignore case (default: 0)\n" 429b488b992872d4d2b7ebf7897d74d52f4fb59e1cJan Engelhardt"[!] --string string Match a string in a packet\n" 439b488b992872d4d2b7ebf7897d74d52f4fb59e1cJan Engelhardt"[!] --hex-string string Match a hex string in a packet\n"); 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' }, 5278d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park { "icase", 0, NULL, '6' }, 539ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann { .name = NULL } 543071913784b69423fd25c3db2344e585872920ccEmmanuel Roger}; 553071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 56181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_init(struct xt_entry_match *m) 57c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira{ 586ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI struct xt_string_info *i = (struct xt_string_info *) m->data; 59c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira 60c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (i->to_offset == 0) 61a80975497968e69b23f56bf15d346c65bec381f2Jan Engelhardt i->to_offset = UINT16_MAX; 62c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira} 63c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira 64c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neirastatic void 656ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAIparse_string(const char *s, struct xt_string_info *info) 663071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 676ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI if (strlen(s) <= XT_STRING_MAX_PATTERN_SIZE) { 686ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI strncpy(info->pattern, s, XT_STRING_MAX_PATTERN_SIZE); 69c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->patlen = strlen(s); 70c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira return; 71c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira } 721829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "STRING too long \"%s\"", s); 7396d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash} 7496d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash 75c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neirastatic void 766ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAIparse_algo(const char *s, struct xt_string_info *info) 77c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira{ 786ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI if (strlen(s) <= XT_STRING_MAX_ALGO_NAME_SIZE) { 796ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI strncpy(info->algo, s, XT_STRING_MAX_ALGO_NAME_SIZE); 80c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira return; 81c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira } 821829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "ALGO too long \"%s\"", s); 83c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira} 84451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 8596d8593fffe816b3ee1bcd27df33beff5c404058Michael Rashstatic void 866ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAIparse_hex_string(const char *s, struct xt_string_info *info) 8796d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash{ 88f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash int i=0, slen, sindex=0, schar; 89f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash short hex_f = 0, literal_f = 0; 90f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash char hextmp[3]; 91f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 92f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash slen = strlen(s); 93f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 94f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (slen == 0) { 951829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 96f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "STRING must contain at least one char"); 97f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 98f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 99f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash while (i < slen) { 100f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (s[i] == '\\' && !hex_f) { 101f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash literal_f = 1; 102f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (s[i] == '\\') { 1031829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 104f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Cannot include literals in hex data"); 105f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (s[i] == '|') { 106f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (hex_f) 107f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hex_f = 0; 108b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash else { 109f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hex_f = 1; 110b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* get past any initial whitespace just after the '|' */ 111b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash while (s[i+1] == ' ') 112b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash i++; 113b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 114f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) 115f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash break; 116f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash else 117f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i++; /* advance to the next character */ 118f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 119f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 120f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (literal_f) { 121f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) { 1221829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 123f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Bad literal placement at end of string"); 124f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 125c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = s[i+1]; 126f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 2; /* skip over literal char */ 127f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash literal_f = 0; 128f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (hex_f) { 129f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) { 1301829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 131f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Odd number of hex digits"); 132f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 133f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+2 >= slen) { 134f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash /* must end with a "|" */ 1351829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Invalid hex block"); 136f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 13796d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash if (! isxdigit(s[i])) /* check for valid hex char */ 1381829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Invalid hex char '%c'", s[i]); 13996d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash if (! isxdigit(s[i+1])) /* check for valid hex char */ 1401829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Invalid hex char '%c'", s[i+1]); 141f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[0] = s[i]; 142f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[1] = s[i+1]; 143f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[2] = '\0'; 144f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (! sscanf(hextmp, "%x", &schar)) 1451829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 146f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Invalid hex char `%c'", s[i]); 147c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = (char) schar; 148f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (s[i+2] == ' ') 149f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 3; /* spaces included in the hex block */ 150f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash else 151f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 2; 152f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else { /* the char is not part of hex data, so just copy */ 153c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = s[i]; 154f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i++; 155f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 1566ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI if (sindex > XT_STRING_MAX_PATTERN_SIZE) 1571829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "STRING too long \"%s\"", s); 158f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash sindex++; 159f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 160c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->patlen = sindex; 1613071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 1623071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 163c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira#define STRING 0x1 164c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira#define ALGO 0x2 165c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira#define FROM 0x4 166c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira#define TO 0x8 16778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park#define ICASE 0x10 168451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 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{ 17378d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park struct xt_string_info *stringinfo = 17478d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park (struct xt_string_info *)(*match)->data; 17578d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park const int revision = (*match)->u.user.revision; 1763071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 1773071913784b69423fd25c3db2344e585872920ccEmmanuel Roger switch (c) { 1783071913784b69423fd25c3db2344e585872920ccEmmanuel Roger case '1': 179c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (*flags & FROM) 1801829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 181c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "Can't specify multiple --from"); 182c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira stringinfo->from_offset = atoi(optarg); 183c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira *flags |= FROM; 184c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira break; 185c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira case '2': 186c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (*flags & TO) 1871829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 188c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "Can't specify multiple --to"); 189c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira stringinfo->to_offset = atoi(optarg); 190c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira *flags |= TO; 191c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira break; 192c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira case '3': 193c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (*flags & ALGO) 1941829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 195c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "Can't specify multiple --algo"); 196c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira parse_algo(optarg, stringinfo); 197c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira *flags |= ALGO; 198c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira break; 199c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira case '4': 200c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (*flags & STRING) 2011829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 202c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "Can't specify multiple --string"); 2030f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt xtables_check_inverse(optarg, &invert, &optind, 0); 2043071913784b69423fd25c3db2344e585872920ccEmmanuel Roger parse_string(argv[optind-1], stringinfo); 20578d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (invert) { 20678d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision == 0) 20778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v0.invert = 1; 20878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park else 20978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT; 21078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park } 21137b4bde745698bf140d74e59a2561f34deeb8726Jan Engelhardt stringinfo->patlen = strnlen((char *)&stringinfo->pattern, 21237b4bde745698bf140d74e59a2561f34deeb8726Jan Engelhardt sizeof(stringinfo->patlen)); 213c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira *flags |= STRING; 21496d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash break; 21596d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash 216c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira case '5': 217c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (*flags & STRING) 2181829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 219c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "Can't specify multiple --hex-string"); 220451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 2210f16c725aadaac7e670d632ecbaea3661ff00827Jan Engelhardt xtables_check_inverse(optarg, &invert, &optind, 0); 22296d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash parse_hex_string(argv[optind-1], stringinfo); /* sets length */ 22378d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (invert) { 22478d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision == 0) 22578d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v0.invert = 1; 22678d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park else 22778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT; 22878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park } 229c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira *flags |= STRING; 2303071913784b69423fd25c3db2344e585872920ccEmmanuel Roger break; 2313071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 23278d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park case '6': 23378d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision == 0) 2341829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(VERSION_PROBLEM, 23578d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park "Kernel doesn't support --icase"); 23678d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park 23778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v1.flags |= XT_STRING_FLAG_IGNORECASE; 23878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park *flags |= ICASE; 23978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park break; 24078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park 2413071913784b69423fd25c3db2344e585872920ccEmmanuel Roger default: 2423071913784b69423fd25c3db2344e585872920ccEmmanuel Roger return 0; 2433071913784b69423fd25c3db2344e585872920ccEmmanuel Roger } 2443071913784b69423fd25c3db2344e585872920ccEmmanuel Roger return 1; 2453071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 2463071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 247181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_check(unsigned int flags) 2483071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 249c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (!(flags & STRING)) 2501829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 251c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "STRING match: You must specify `--string' or " 252c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "`--hex-string'"); 253c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (!(flags & ALGO)) 2541829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 255c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "STRING match: You must specify `--algo'"); 2563071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 2573071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 258b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash/* Test to see if the string contains non-printable chars or quotes */ 259b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic unsigned short int 260b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashis_hex_string(const char *str, const unsigned short int len) 261b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 262b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 263b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) 264b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if (! isprint(str[i])) 265b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 1; /* string contains at least one non-printable char */ 266b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* use hex output if the last char is a "\" */ 267b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if ((unsigned char) str[len-1] == 0x5c) 268b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 1; 269b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 0; 270b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 271b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash 272b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash/* Print string with "|" chars included as one would pass to --hex-string */ 273b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic void 274b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashprint_hex_string(const char *str, const unsigned short int len) 275b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 276b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 277b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* start hex block */ 278b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("\"|"); 279b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) { 280b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* see if we need to prepend a zero */ 281b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if ((unsigned char) str[i] <= 0x0F) 282b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("0%x", (unsigned char) str[i]); 283b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash else 284b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("%x", (unsigned char) str[i]); 285b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 286b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* close hex block */ 287b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("|\" "); 288b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 289b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash 290b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic void 291b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashprint_string(const char *str, const unsigned short int len) 292b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 293b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 294b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("\""); 295b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) { 296b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if ((unsigned char) str[i] == 0x22) /* escape any embedded quotes */ 297b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("%c", 0x5c); 298b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("%c", (unsigned char) str[i]); 299b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 300b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("\" "); /* closing space and quote */ 301b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 302451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 3033071913784b69423fd25c3db2344e585872920ccEmmanuel Rogerstatic void 304181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstring_print(const void *ip, const struct xt_entry_match *match, int numeric) 3053071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 3066ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI const struct xt_string_info *info = 3076ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI (const struct xt_string_info*) match->data; 30878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park const int revision = match->u.user.revision; 30978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park int invert = (revision == 0 ? info->u.v0.invert : 31078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park info->u.v1.flags & XT_STRING_FLAG_INVERT); 311451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 312c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (is_hex_string(info->pattern, info->patlen)) { 31378d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park printf("STRING match %s", invert ? "!" : ""); 314c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_hex_string(info->pattern, info->patlen); 315b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } else { 31678d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park printf("STRING match %s", invert ? "!" : ""); 317c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_string(info->pattern, info->patlen); 318b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 319c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira printf("ALGO name %s ", info->algo); 320c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->from_offset != 0) 321c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira printf("FROM %u ", info->from_offset); 322c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->to_offset != 0) 3238a0b6ead35931422fbe02c63d9262ad9e40daaccPatrick McHardy printf("TO %u ", info->to_offset); 32478d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision > 0 && info->u.v1.flags & XT_STRING_FLAG_IGNORECASE) 32578d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park printf("ICASE "); 3263071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 3273071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 328181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_save(const void *ip, const struct xt_entry_match *match) 3293071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 3306ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI const struct xt_string_info *info = 3316ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI (const struct xt_string_info*) match->data; 33278d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park const int revision = match->u.user.revision; 33378d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park int invert = (revision == 0 ? info->u.v0.invert : 33478d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park info->u.v1.flags & XT_STRING_FLAG_INVERT); 335451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 336c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (is_hex_string(info->pattern, info->patlen)) { 337cea9f71f5618250a38acb21c31fbbf93a752f7d4Jan Engelhardt printf("%s--hex-string ", (invert) ? "! ": ""); 338c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_hex_string(info->pattern, info->patlen); 339b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } else { 340cea9f71f5618250a38acb21c31fbbf93a752f7d4Jan Engelhardt printf("%s--string ", (invert) ? "! ": ""); 341c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_string(info->pattern, info->patlen); 342b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 343c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira printf("--algo %s ", info->algo); 344c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->from_offset != 0) 3450829a2b72caa06c07e6eb710a81a04295c9f2621Michael Rash printf("--from %u ", info->from_offset); 346c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->to_offset != 0) 3470829a2b72caa06c07e6eb710a81a04295c9f2621Michael Rash printf("--to %u ", info->to_offset); 34878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision > 0 && info->u.v1.flags & XT_STRING_FLAG_IGNORECASE) 34978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park printf("--icase "); 3503071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 3513071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 352451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 353181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match string_match = { 354c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira .name = "string", 35578d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .revision = 0, 35678d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .family = AF_UNSPEC, 35778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .version = XTABLES_VERSION, 35878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .size = XT_ALIGN(sizeof(struct xt_string_info)), 35978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .userspacesize = offsetof(struct xt_string_info, config), 36078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .help = string_help, 36178d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .init = string_init, 36278d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .parse = string_parse, 36378d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .final_check = string_check, 36478d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .print = string_print, 36578d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .save = string_save, 36678d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .extra_opts = string_opts, 36778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park}; 36878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park 36978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Parkstatic struct xtables_match string_match_v1 = { 37078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .name = "string", 37178d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park .revision = 1, 37223545c2a7a31c68c1e49c7c901b632c2f1c59968Jan Engelhardt .family = AF_UNSPEC, 3738b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 3744ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI .size = XT_ALIGN(sizeof(struct xt_string_info)), 3754ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI .userspacesize = offsetof(struct xt_string_info, config), 376181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .help = string_help, 377181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .init = string_init, 378181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .parse = string_parse, 379181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .final_check = string_check, 380181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .print = string_print, 381181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .save = string_save, 382181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .extra_opts = string_opts, 3834ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI}; 3844ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI 3853071913784b69423fd25c3db2344e585872920ccEmmanuel Rogervoid _init(void) 3863071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 387181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt xtables_register_match(&string_match); 38878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park xtables_register_match(&string_match_v1); 3893071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 390