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 <string.h> 253071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <stdlib.h> 26f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash#include <ctype.h> 276ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI#include <xtables.h> 286ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI#include <linux/netfilter/xt_string.h> 293071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 30c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardtenum { 31c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_FROM = 0, 32c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_TO, 33c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_ALGO, 34c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_ICASE, 35c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_STRING, 36c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_HEX_STRING, 37c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt F_STRING = 1 << O_STRING, 38c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt F_HEX_STRING = 1 << O_HEX_STRING, 39c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt F_OP_ANY = F_STRING | F_HEX_STRING, 40c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt}; 41c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt 42181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_help(void) 433071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 443071913784b69423fd25c3db2344e585872920ccEmmanuel Roger printf( 458b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"string match options:\n" 46c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira"--from Offset to start searching from\n" 47c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira"--to Offset to stop searching\n" 4878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park"--algo Algorithm\n" 4978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park"--icase Ignore case (default: 0)\n" 509b488b992872d4d2b7ebf7897d74d52f4fb59e1cJan Engelhardt"[!] --string string Match a string in a packet\n" 519b488b992872d4d2b7ebf7897d74d52f4fb59e1cJan Engelhardt"[!] --hex-string string Match a hex string in a packet\n"); 523071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 533071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 54c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt#define s struct xt_string_info 55c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardtstatic const struct xt_option_entry string_opts[] = { 56c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "from", .id = O_FROM, .type = XTTYPE_UINT16, 57c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .flags = XTOPT_PUT, XTOPT_POINTER(s, from_offset)}, 58c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "to", .id = O_TO, .type = XTTYPE_UINT16, 59c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .flags = XTOPT_PUT, XTOPT_POINTER(s, to_offset)}, 60c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "algo", .id = O_ALGO, .type = XTTYPE_STRING, 61c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, algo)}, 62c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "string", .id = O_STRING, .type = XTTYPE_STRING, 63c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .flags = XTOPT_INVERT, .excl = F_HEX_STRING}, 64c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "hex-string", .id = O_HEX_STRING, .type = XTTYPE_STRING, 65c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .flags = XTOPT_INVERT, .excl = F_STRING}, 66c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "icase", .id = O_ICASE, .type = XTTYPE_NONE}, 67c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt XTOPT_TABLEEND, 683071913784b69423fd25c3db2344e585872920ccEmmanuel Roger}; 69c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt#undef s 703071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 71181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_init(struct xt_entry_match *m) 72c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira{ 736ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI struct xt_string_info *i = (struct xt_string_info *) m->data; 74c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira 75e88a7c2c7175742b58b6aa03f2b5aba2d80330a1Jan Engelhardt i->to_offset = UINT16_MAX; 76c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira} 77c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira 78c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neirastatic void 796ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAIparse_string(const char *s, struct xt_string_info *info) 803071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 81409f2a8e3b2706c8c6c5e345a4bc77fca8ad7105Pablo Neira Ayuso /* xt_string does not need \0 at the end of the pattern */ 826ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI if (strlen(s) <= XT_STRING_MAX_PATTERN_SIZE) { 836ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI strncpy(info->pattern, s, XT_STRING_MAX_PATTERN_SIZE); 84409f2a8e3b2706c8c6c5e345a4bc77fca8ad7105Pablo Neira Ayuso info->patlen = strnlen(s, XT_STRING_MAX_PATTERN_SIZE); 85c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira return; 86c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira } 871829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "STRING too long \"%s\"", s); 8896d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash} 8996d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash 90c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neirastatic void 916ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAIparse_hex_string(const char *s, struct xt_string_info *info) 9296d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash{ 93f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash int i=0, slen, sindex=0, schar; 94f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash short hex_f = 0, literal_f = 0; 95f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash char hextmp[3]; 96f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 97f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash slen = strlen(s); 98f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 99f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (slen == 0) { 1001829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 101f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "STRING must contain at least one char"); 102f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 103f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 104f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash while (i < slen) { 105f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (s[i] == '\\' && !hex_f) { 106f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash literal_f = 1; 107f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (s[i] == '\\') { 1081829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 109f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Cannot include literals in hex data"); 110f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (s[i] == '|') { 111f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (hex_f) 112f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hex_f = 0; 113b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash else { 114f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hex_f = 1; 115b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* get past any initial whitespace just after the '|' */ 116b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash while (s[i+1] == ' ') 117b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash i++; 118b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 119f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) 120f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash break; 121f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash else 122f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i++; /* advance to the next character */ 123f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 124f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 125f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (literal_f) { 126f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) { 1271829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 128f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Bad literal placement at end of string"); 129f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 130c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = s[i+1]; 131f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 2; /* skip over literal char */ 132f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash literal_f = 0; 133f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (hex_f) { 134f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) { 1351829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 136f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Odd number of hex digits"); 137f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 138f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+2 >= slen) { 139f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash /* must end with a "|" */ 1401829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Invalid hex block"); 141f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 14296d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash if (! isxdigit(s[i])) /* check for valid hex char */ 1431829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Invalid hex char '%c'", s[i]); 14496d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash if (! isxdigit(s[i+1])) /* check for valid hex char */ 1451829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Invalid hex char '%c'", s[i+1]); 146f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[0] = s[i]; 147f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[1] = s[i+1]; 148f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[2] = '\0'; 149f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (! sscanf(hextmp, "%x", &schar)) 1501829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 151f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Invalid hex char `%c'", s[i]); 152c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = (char) schar; 153f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (s[i+2] == ' ') 154f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 3; /* spaces included in the hex block */ 155f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash else 156f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 2; 157f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else { /* the char is not part of hex data, so just copy */ 158c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = s[i]; 159f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i++; 160f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 1616ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI if (sindex > XT_STRING_MAX_PATTERN_SIZE) 1621829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "STRING too long \"%s\"", s); 163f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash sindex++; 164f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 165c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->patlen = sindex; 1663071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 1673071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 168c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardtstatic void string_parse(struct xt_option_call *cb) 1693071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 170c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt struct xt_string_info *stringinfo = cb->data; 171c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt const unsigned int revision = (*cb->match)->u.user.revision; 1723071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 173c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt xtables_option_parse(cb); 174c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt switch (cb->entry->id) { 175c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt case O_STRING: 176c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt parse_string(cb->arg, stringinfo); 177c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt if (cb->invert) { 17878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision == 0) 17978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v0.invert = 1; 18078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park else 18178d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT; 18278d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park } 18396d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash break; 184c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt case O_HEX_STRING: 185c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt parse_hex_string(cb->arg, stringinfo); /* sets length */ 186c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt if (cb->invert) { 18778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision == 0) 18878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v0.invert = 1; 18978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park else 19078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT; 19178d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park } 1923071913784b69423fd25c3db2344e585872920ccEmmanuel Roger break; 193c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt case O_ICASE: 19478d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision == 0) 1951829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(VERSION_PROBLEM, 19678d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park "Kernel doesn't support --icase"); 19778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park 19878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v1.flags |= XT_STRING_FLAG_IGNORECASE; 19978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park break; 2003071913784b69423fd25c3db2344e585872920ccEmmanuel Roger } 2013071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 2023071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 203c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardtstatic void string_check(struct xt_fcheck_call *cb) 2043071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 205c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt if (!(cb->xflags & F_OP_ANY)) 2061829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 207c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "STRING match: You must specify `--string' or " 208c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "`--hex-string'"); 2093071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 2103071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 211b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash/* Test to see if the string contains non-printable chars or quotes */ 212b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic unsigned short int 213b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashis_hex_string(const char *str, const unsigned short int len) 214b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 215b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 216b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) 217b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if (! isprint(str[i])) 218b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 1; /* string contains at least one non-printable char */ 219b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* use hex output if the last char is a "\" */ 220b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if ((unsigned char) str[len-1] == 0x5c) 221b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 1; 222b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 0; 223b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 224b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash 225b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash/* Print string with "|" chars included as one would pass to --hex-string */ 226b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic void 227b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashprint_hex_string(const char *str, const unsigned short int len) 228b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 229b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 230b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* start hex block */ 231b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("\"|"); 232b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) { 233b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* see if we need to prepend a zero */ 234b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if ((unsigned char) str[i] <= 0x0F) 235b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("0%x", (unsigned char) str[i]); 236b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash else 237b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("%x", (unsigned char) str[i]); 238b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 239b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* close hex block */ 240b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("|\" "); 241b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 242b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash 243b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic void 244b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashprint_string(const char *str, const unsigned short int len) 245b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 246b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 24773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" \""); 248b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) { 249b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if ((unsigned char) str[i] == 0x22) /* escape any embedded quotes */ 250b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("%c", 0x5c); 251b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("%c", (unsigned char) str[i]); 252b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 25373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf("\""); /* closing quote */ 254b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 255451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 2563071913784b69423fd25c3db2344e585872920ccEmmanuel Rogerstatic void 257181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstring_print(const void *ip, const struct xt_entry_match *match, int numeric) 2583071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 2596ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI const struct xt_string_info *info = 2606ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI (const struct xt_string_info*) match->data; 26178d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park const int revision = match->u.user.revision; 26278d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park int invert = (revision == 0 ? info->u.v0.invert : 26378d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park info->u.v1.flags & XT_STRING_FLAG_INVERT); 264451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 265c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (is_hex_string(info->pattern, info->patlen)) { 26673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" STRING match %s", invert ? "!" : ""); 267c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_hex_string(info->pattern, info->patlen); 268b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } else { 26973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" STRING match %s", invert ? "!" : ""); 270c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_string(info->pattern, info->patlen); 271b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 27273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" ALGO name %s", info->algo); 273c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->from_offset != 0) 27473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" FROM %u", info->from_offset); 275c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->to_offset != 0) 27673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" TO %u", info->to_offset); 27778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision > 0 && info->u.v1.flags & XT_STRING_FLAG_IGNORECASE) 27873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" ICASE"); 2793071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 2803071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 281181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_save(const void *ip, const struct xt_entry_match *match) 2823071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 2836ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI const struct xt_string_info *info = 2846ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI (const struct xt_string_info*) match->data; 28578d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park const int revision = match->u.user.revision; 28678d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park int invert = (revision == 0 ? info->u.v0.invert : 28778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park info->u.v1.flags & XT_STRING_FLAG_INVERT); 288451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 289c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (is_hex_string(info->pattern, info->patlen)) { 29073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf("%s --hex-string", (invert) ? " !" : ""); 291c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_hex_string(info->pattern, info->patlen); 292b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } else { 29373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf("%s --string", (invert) ? " !": ""); 294c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_string(info->pattern, info->patlen); 295b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 29673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --algo %s", info->algo); 297c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->from_offset != 0) 29873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --from %u", info->from_offset); 299c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->to_offset != 0) 30073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --to %u", info->to_offset); 30178d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision > 0 && info->u.v1.flags & XT_STRING_FLAG_IGNORECASE) 30273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --icase"); 3033071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 3043071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 305451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 306f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardtstatic struct xtables_match string_mt_reg[] = { 307f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt { 308f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .name = "string", 309f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .revision = 0, 310f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .family = NFPROTO_UNSPEC, 311f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .version = XTABLES_VERSION, 312f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .size = XT_ALIGN(sizeof(struct xt_string_info)), 313f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .userspacesize = offsetof(struct xt_string_info, config), 314f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .help = string_help, 315f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .init = string_init, 316f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .print = string_print, 317f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .save = string_save, 318c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_parse = string_parse, 319c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_fcheck = string_check, 320c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_options = string_opts, 321f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt }, 322f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt { 323f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .name = "string", 324f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .revision = 1, 325f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .family = NFPROTO_UNSPEC, 326f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .version = XTABLES_VERSION, 327f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .size = XT_ALIGN(sizeof(struct xt_string_info)), 328f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .userspacesize = offsetof(struct xt_string_info, config), 329f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .help = string_help, 330f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .init = string_init, 331f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .print = string_print, 332f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .save = string_save, 333c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_parse = string_parse, 334c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_fcheck = string_check, 335c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_options = string_opts, 336f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt }, 3374ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI}; 3384ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI 3393071913784b69423fd25c3db2344e585872920ccEmmanuel Rogervoid _init(void) 3403071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 341f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt xtables_register_matches(string_mt_reg, ARRAY_SIZE(string_mt_reg)); 3423071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 343