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 */ 2367156c0b9a3d35f5e7836e5683d8ca0b46ac36caJan Engelhardt#define _GNU_SOURCE 1 /* strnlen for older glibcs */ 243071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <stdio.h> 253071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <string.h> 263071913784b69423fd25c3db2344e585872920ccEmmanuel Roger#include <stdlib.h> 27f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash#include <ctype.h> 286ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI#include <xtables.h> 296ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI#include <linux/netfilter/xt_string.h> 303071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 31c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardtenum { 32c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_FROM = 0, 33c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_TO, 34c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_ALGO, 35c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_ICASE, 36c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_STRING, 37c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt O_HEX_STRING, 38c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt F_STRING = 1 << O_STRING, 39c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt F_HEX_STRING = 1 << O_HEX_STRING, 40c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt F_OP_ANY = F_STRING | F_HEX_STRING, 41c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt}; 42c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt 43181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_help(void) 443071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 453071913784b69423fd25c3db2344e585872920ccEmmanuel Roger printf( 468b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"string match options:\n" 47c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira"--from Offset to start searching from\n" 48c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira"--to Offset to stop searching\n" 4978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park"--algo Algorithm\n" 5078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park"--icase Ignore case (default: 0)\n" 519b488b992872d4d2b7ebf7897d74d52f4fb59e1cJan Engelhardt"[!] --string string Match a string in a packet\n" 529b488b992872d4d2b7ebf7897d74d52f4fb59e1cJan Engelhardt"[!] --hex-string string Match a hex string in a packet\n"); 533071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 543071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 55c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt#define s struct xt_string_info 56c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardtstatic const struct xt_option_entry string_opts[] = { 57c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "from", .id = O_FROM, .type = XTTYPE_UINT16, 58c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .flags = XTOPT_PUT, XTOPT_POINTER(s, from_offset)}, 59c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "to", .id = O_TO, .type = XTTYPE_UINT16, 60c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .flags = XTOPT_PUT, XTOPT_POINTER(s, to_offset)}, 61c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "algo", .id = O_ALGO, .type = XTTYPE_STRING, 62c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, algo)}, 63c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "string", .id = O_STRING, .type = XTTYPE_STRING, 64c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .flags = XTOPT_INVERT, .excl = F_HEX_STRING}, 65c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "hex-string", .id = O_HEX_STRING, .type = XTTYPE_STRING, 66c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .flags = XTOPT_INVERT, .excl = F_STRING}, 67c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt {.name = "icase", .id = O_ICASE, .type = XTTYPE_NONE}, 68c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt XTOPT_TABLEEND, 693071913784b69423fd25c3db2344e585872920ccEmmanuel Roger}; 70c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt#undef s 713071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 72181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_init(struct xt_entry_match *m) 73c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira{ 746ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI struct xt_string_info *i = (struct xt_string_info *) m->data; 75c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira 76e88a7c2c7175742b58b6aa03f2b5aba2d80330a1Jan Engelhardt i->to_offset = UINT16_MAX; 77c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira} 78c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira 79c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neirastatic void 806ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAIparse_string(const char *s, struct xt_string_info *info) 813071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 82409f2a8e3b2706c8c6c5e345a4bc77fca8ad7105Pablo Neira Ayuso /* xt_string does not need \0 at the end of the pattern */ 836ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI if (strlen(s) <= XT_STRING_MAX_PATTERN_SIZE) { 846ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI strncpy(info->pattern, s, XT_STRING_MAX_PATTERN_SIZE); 85409f2a8e3b2706c8c6c5e345a4bc77fca8ad7105Pablo Neira Ayuso info->patlen = strnlen(s, XT_STRING_MAX_PATTERN_SIZE); 86c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira return; 87c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira } 881829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "STRING too long \"%s\"", s); 8996d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash} 9096d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash 91c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neirastatic void 926ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAIparse_hex_string(const char *s, struct xt_string_info *info) 9396d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash{ 94f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash int i=0, slen, sindex=0, schar; 95f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash short hex_f = 0, literal_f = 0; 96f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash char hextmp[3]; 97f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 98f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash slen = strlen(s); 99f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 100f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (slen == 0) { 1011829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 102f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "STRING must contain at least one char"); 103f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 104f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 105f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash while (i < slen) { 106f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (s[i] == '\\' && !hex_f) { 107f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash literal_f = 1; 108f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (s[i] == '\\') { 1091829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 110f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Cannot include literals in hex data"); 111f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (s[i] == '|') { 112f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (hex_f) 113f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hex_f = 0; 114b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash else { 115f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hex_f = 1; 116b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* get past any initial whitespace just after the '|' */ 117b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash while (s[i+1] == ' ') 118b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash i++; 119b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 120f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) 121f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash break; 122f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash else 123f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i++; /* advance to the next character */ 124f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 125f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash 126f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (literal_f) { 127f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) { 1281829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 129f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Bad literal placement at end of string"); 130f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 131c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = s[i+1]; 132f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 2; /* skip over literal char */ 133f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash literal_f = 0; 134f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else if (hex_f) { 135f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+1 >= slen) { 1361829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 137f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Odd number of hex digits"); 138f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 139f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (i+2 >= slen) { 140f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash /* must end with a "|" */ 1411829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Invalid hex block"); 142f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 14396d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash if (! isxdigit(s[i])) /* check for valid hex char */ 1441829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Invalid hex char '%c'", s[i]); 14596d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash if (! isxdigit(s[i+1])) /* check for valid hex char */ 1461829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "Invalid hex char '%c'", s[i+1]); 147f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[0] = s[i]; 148f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[1] = s[i+1]; 149f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash hextmp[2] = '\0'; 150f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (! sscanf(hextmp, "%x", &schar)) 1511829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 152f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash "Invalid hex char `%c'", s[i]); 153c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = (char) schar; 154f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash if (s[i+2] == ' ') 155f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 3; /* spaces included in the hex block */ 156f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash else 157f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i += 2; 158f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } else { /* the char is not part of hex data, so just copy */ 159c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->pattern[sindex] = s[i]; 160f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash i++; 161f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 1626ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI if (sindex > XT_STRING_MAX_PATTERN_SIZE) 1631829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "STRING too long \"%s\"", s); 164f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash sindex++; 165f8ac329cc9a8822273aefc6686d58cae07e8a8f9Michael Rash } 166c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira info->patlen = sindex; 1673071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 1683071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 169c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardtstatic void string_parse(struct xt_option_call *cb) 1703071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 171c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt struct xt_string_info *stringinfo = cb->data; 172c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt const unsigned int revision = (*cb->match)->u.user.revision; 1733071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 174c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt xtables_option_parse(cb); 175c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt switch (cb->entry->id) { 176c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt case O_STRING: 177c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt parse_string(cb->arg, stringinfo); 178c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt if (cb->invert) { 17978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision == 0) 18078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v0.invert = 1; 18178d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park else 18278d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT; 18378d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park } 18496d8593fffe816b3ee1bcd27df33beff5c404058Michael Rash break; 185c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt case O_HEX_STRING: 186c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt parse_hex_string(cb->arg, stringinfo); /* sets length */ 187c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt if (cb->invert) { 18878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision == 0) 18978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v0.invert = 1; 19078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park else 19178d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT; 19278d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park } 1933071913784b69423fd25c3db2344e585872920ccEmmanuel Roger break; 194c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt case O_ICASE: 19578d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision == 0) 1961829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(VERSION_PROBLEM, 19778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park "Kernel doesn't support --icase"); 19878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park 19978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park stringinfo->u.v1.flags |= XT_STRING_FLAG_IGNORECASE; 20078d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park break; 2013071913784b69423fd25c3db2344e585872920ccEmmanuel Roger } 2023071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 2033071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 204c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardtstatic void string_check(struct xt_fcheck_call *cb) 2053071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 206c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt if (!(cb->xflags & F_OP_ANY)) 2071829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 208c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "STRING match: You must specify `--string' or " 209c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira "`--hex-string'"); 2103071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 2113071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 212b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash/* Test to see if the string contains non-printable chars or quotes */ 213b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic unsigned short int 214b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashis_hex_string(const char *str, const unsigned short int len) 215b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 216b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 217b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) 218b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash if (! isprint(str[i])) 219b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 1; /* string contains at least one non-printable char */ 220b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* use hex output if the last char is a "\" */ 221f4daf54e5c184680559de33eb08f2a0fb701dbe9Jan Engelhardt if (str[len-1] == '\\') 222b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 1; 223b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash return 0; 224b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 225b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash 226b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash/* Print string with "|" chars included as one would pass to --hex-string */ 227b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic void 228b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashprint_hex_string(const char *str, const unsigned short int len) 229b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 230b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 231b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* start hex block */ 2323716dfd7eac3afa7fb3098952550e510c8df0220Dwight Davis printf(" \"|"); 233131d4fb53b45be85b1315f72f958cadf7b24a63fJan Engelhardt for (i=0; i < len; i++) 234131d4fb53b45be85b1315f72f958cadf7b24a63fJan Engelhardt printf("%02x", (unsigned char)str[i]); 235b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash /* close hex block */ 2363716dfd7eac3afa7fb3098952550e510c8df0220Dwight Davis printf("|\""); 237b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 238b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash 239b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashstatic void 240b807fb348369d852d031056f1c911f5b2b4c2114Michael Rashprint_string(const char *str, const unsigned short int len) 241b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash{ 242b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash unsigned int i; 24373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" \""); 244b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash for (i=0; i < len; i++) { 245d51a97bc52ee81a962b761c7e58a5eb9f07a2c8aJan Engelhardt if (str[i] == '\"' || str[i] == '\\') 246f4daf54e5c184680559de33eb08f2a0fb701dbe9Jan Engelhardt putchar('\\'); 247b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash printf("%c", (unsigned char) str[i]); 248b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 24973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf("\""); /* closing quote */ 250b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash} 251451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 2523071913784b69423fd25c3db2344e585872920ccEmmanuel Rogerstatic void 253181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstring_print(const void *ip, const struct xt_entry_match *match, int numeric) 2543071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 2556ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI const struct xt_string_info *info = 2566ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI (const struct xt_string_info*) match->data; 25778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park const int revision = match->u.user.revision; 25878d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park int invert = (revision == 0 ? info->u.v0.invert : 25978d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park info->u.v1.flags & XT_STRING_FLAG_INVERT); 260451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 261c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (is_hex_string(info->pattern, info->patlen)) { 26273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" STRING match %s", invert ? "!" : ""); 263c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_hex_string(info->pattern, info->patlen); 264b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } else { 26573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" STRING match %s", invert ? "!" : ""); 266c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_string(info->pattern, info->patlen); 267b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 26873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" ALGO name %s", info->algo); 269c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->from_offset != 0) 27073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" FROM %u", info->from_offset); 271c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->to_offset != 0) 27273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" TO %u", info->to_offset); 27378d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision > 0 && info->u.v1.flags & XT_STRING_FLAG_IGNORECASE) 27473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" ICASE"); 2753071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 2763071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 277181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void string_save(const void *ip, const struct xt_entry_match *match) 2783071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 2796ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI const struct xt_string_info *info = 2806ac58e399ccb3c2fbadc373266f454ce301547daYasuyuki KOZAKAI (const struct xt_string_info*) match->data; 28178d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park const int revision = match->u.user.revision; 28278d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park int invert = (revision == 0 ? info->u.v0.invert : 28378d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park info->u.v1.flags & XT_STRING_FLAG_INVERT); 284451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 285c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (is_hex_string(info->pattern, info->patlen)) { 28673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf("%s --hex-string", (invert) ? " !" : ""); 287c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_hex_string(info->pattern, info->patlen); 288b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } else { 28973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf("%s --string", (invert) ? " !": ""); 290c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira print_string(info->pattern, info->patlen); 291b807fb348369d852d031056f1c911f5b2b4c2114Michael Rash } 29273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --algo %s", info->algo); 293c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->from_offset != 0) 29473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --from %u", info->from_offset); 295c6fbf41cdd15705559269d992da9938cbb1a1f4ePablo Neira if (info->to_offset != 0) 29673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --to %u", info->to_offset); 29778d2d14211466f1986882ba6bdf82e6429ce78dcJoonwoo Park if (revision > 0 && info->u.v1.flags & XT_STRING_FLAG_IGNORECASE) 29873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --icase"); 2993071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 3003071913784b69423fd25c3db2344e585872920ccEmmanuel Roger 301451f3eaad6712ba790aeba1a5af41ef9ee007d68Stephane Ouellette 302f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardtstatic struct xtables_match string_mt_reg[] = { 303f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt { 304f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .name = "string", 305f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .revision = 0, 306f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .family = NFPROTO_UNSPEC, 307f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .version = XTABLES_VERSION, 308f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .size = XT_ALIGN(sizeof(struct xt_string_info)), 309f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .userspacesize = offsetof(struct xt_string_info, config), 310f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .help = string_help, 311f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .init = string_init, 312f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .print = string_print, 313f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .save = string_save, 314c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_parse = string_parse, 315c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_fcheck = string_check, 316c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_options = string_opts, 317f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt }, 318f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt { 319f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .name = "string", 320f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .revision = 1, 321f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .family = NFPROTO_UNSPEC, 322f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .version = XTABLES_VERSION, 323f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .size = XT_ALIGN(sizeof(struct xt_string_info)), 324f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .userspacesize = offsetof(struct xt_string_info, config), 325f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .help = string_help, 326f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .init = string_init, 327f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .print = string_print, 328f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt .save = string_save, 329c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_parse = string_parse, 330c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_fcheck = string_check, 331c618a0b1d3696c30f7791a427da9ba60186dfe05Jan Engelhardt .x6_options = string_opts, 332f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt }, 3334ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI}; 3344ccb6f547b6c2c355a188a267afe6358b013a438Yasuyuki KOZAKAI 3353071913784b69423fd25c3db2344e585872920ccEmmanuel Rogervoid _init(void) 3363071913784b69423fd25c3db2344e585872920ccEmmanuel Roger{ 337f2a77520693f0a6dd1df1f87be4b81913961c1f5Jan Engelhardt xtables_register_matches(string_mt_reg, ARRAY_SIZE(string_mt_reg)); 3383071913784b69423fd25c3db2344e585872920ccEmmanuel Roger} 339