1 /*
2 ettercap -- string manipulation functions
3
4 Copyright (C) ALoR & NaGA
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 */
21
22 #include <ec.h>
23 #include <ec_sleep.h>
24
25 #include <ctype.h>
26
27 /* protos... */
28
29 #ifndef HAVE_CTYPE_H
30 int isprint(int c);
31 #endif
32 static int hextoint(int c);
33
34 /*******************************************/
35
36 /* implement the function if it is not available */
37 #ifndef HAVE_CTYPE_H
isprint(int c)38 int isprint(int c)
39 {
40 return ( (c > 31 && c < 127) ? 1 : 0 );
41 }
42 #endif
43
44 /* Pattern matching code from OpenSSH. */
45
match_pattern(const char * s,const char * pattern)46 int match_pattern(const char *s, const char *pattern)
47 {
48 for (;;) {
49 if (!*pattern) return (!*s);
50
51 if (*pattern == '*') {
52 pattern++;
53
54 if (!*pattern) return (1);
55
56 if (*pattern != '?' && *pattern != '*') {
57 for (; *s; s++) {
58 if (*s == *pattern && match_pattern(s + 1, pattern + 1))
59 return (1);
60 }
61 return (0);
62 }
63 for (; *s; s++) {
64 if (match_pattern(s, pattern))
65 return (1);
66 }
67 return (0);
68 }
69 if (!*s) return (0);
70
71 if (*pattern != '?' && *pattern != *s)
72 return (0);
73
74 s++;
75 pattern++;
76 }
77 /* NOTREACHED */
78 }
79
80 /* stolen from ap_base64.c (apache source code) */
81
82 static const unsigned char pr2six[256] =
83 {
84 /* ASCII table */
85 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
86 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
87 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
88 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
89 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
90 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
91 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
92 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
93 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
94 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
95 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
96 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
97 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
98 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
99 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
100 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
101 };
102
103
base64_decode(char * bufplain,const char * bufcoded)104 int base64_decode(char *bufplain, const char *bufcoded)
105 {
106 int nbytesdecoded;
107 register const unsigned char *bufin;
108 register unsigned char *bufout;
109 register int nprbytes;
110
111 bufin = (const unsigned char *) bufcoded;
112 while (pr2six[*(bufin++)] <= 63);
113 nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
114 nbytesdecoded = ((nprbytes + 3) / 4) * 3;
115
116 bufout = (unsigned char *) bufplain;
117 bufin = (const unsigned char *) bufcoded;
118
119 while (nprbytes > 4)
120 {
121 *(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
122 *(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
123 *(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
124 bufin += 4;
125 nprbytes -= 4;
126 }
127
128 /* Note: (nprbytes == 1) would be an error, so just ingore that case */
129 if (nprbytes > 1)
130 *(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
131
132 if (nprbytes > 2)
133 *(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
134
135 if (nprbytes > 3)
136 *(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
137
138 nbytesdecoded -= (4 - nprbytes) & 3;
139
140 bufplain[nbytesdecoded] = '\0';
141 return nbytesdecoded;
142 }
143
144
145 /* adapted from magic.c part of dsniff <dugsong@monkey.org> source code... */
146
147 /*
148 * convert an HEX rapresentation into int
149 */
hextoint(int c)150 static int hextoint(int c)
151 {
152 if (!isascii((int) c))
153 return (-1);
154
155 if (isdigit((int) c))
156 return (c - '0');
157
158 if ((c >= 'a') && (c <= 'f'))
159 return (c + 10 - 'a');
160
161 if ((c >= 'A') && (c <= 'F'))
162 return (c + 10 - 'A');
163
164 return (-1);
165 }
166
167 /*
168 * convert the escaped string into a binary one
169 */
strescape(char * dst,char * src,size_t len)170 int strescape(char *dst, char *src, size_t len)
171 {
172 char *olddst = dst;
173 char *oldsrc = src;
174 int c;
175 int val;
176
177 while ((c = *src++) != '\0' && (size_t)(src - oldsrc) <= len) {
178 if (c == '\\') {
179 switch ((c = *src++)) {
180 case '\0':
181 goto strend;
182 default:
183 *dst++ = (char) c;
184 break;
185 case 'n':
186 *dst++ = '\n';
187 break;
188 case 'r':
189 *dst++ = '\r';
190 break;
191 case 'b':
192 *dst++ = '\b';
193 break;
194 case 't':
195 *dst++ = '\t';
196 break;
197 case 'f':
198 *dst++ = '\f';
199 break;
200 case 'v':
201 *dst++ = '\v';
202 break;
203 /* \ and up to 3 octal digits */
204 case '0':
205 case '1':
206 case '2':
207 case '3':
208 case '4':
209 case '5':
210 case '6':
211 case '7':
212 val = c - '0';
213 c = *src++;
214 /* try for 2 */
215 if (c >= '0' && c <= '7') {
216 val = (val << 3) | (c - '0');
217 c = *src++;
218 /* try for 3 */
219 if (c >= '0' && c <= '7')
220 val = (val << 3) | (c - '0');
221 else
222 if (src > oldsrc) /* protect against buffer underflow */
223 --src;
224 } else
225 if (src > oldsrc) /* protect against buffer underflow */
226 --src;
227 *dst++ = (char) val;
228 break;
229
230 case 'x':
231 val = 'x'; /* Default if no digits */
232 c = hextoint(*src++); /* Get next char */
233 if (c >= 0) {
234 val = c;
235 c = hextoint(*src++);
236 if (c >= 0)
237 val = (val << 4) + c;
238 else if (src > oldsrc) /* protect against buffer underflow */
239 --src;
240 } else if (src > oldsrc) /* protect against buffer underflow */
241 --src;
242 *dst++ = (char) val;
243 break;
244 }
245 } else if (c == 8 || c == 263) { /* the backspace */
246 if (dst > oldsrc) /* protect against buffer underflow */
247 dst--;
248 }
249 else
250 *dst++ = (char) c;
251 }
252
253 strend:
254 *dst = '\0';
255
256 return (dst - olddst);
257 }
258
259
260 /*
261 * replace 's' with 'd' in the string 'text'
262 * text will be realloc'ed, so a pointer is needed
263 * and stack based array can't be used
264 */
str_replace(char ** text,const char * s,const char * d)265 int str_replace(char **text, const char *s, const char *d)
266 {
267 size_t slen = strlen(s);
268 size_t dlen = strlen(d);
269 int diff = dlen - slen;
270 char *p, *q = *text;
271 size_t size;
272
273 /* the search string does not exist */
274 if (strstr(*text, s) == NULL)
275 return -E_NOTFOUND;
276
277 /* search all the occurrence of 's' */
278 while ( (p = strstr(q, s)) != NULL ) {
279
280 /* the new size */
281 if (diff > 0)
282 size = strlen(q) + diff + 1;
283 else
284 size = strlen(q) + 1;
285
286 SAFE_REALLOC(*text, size);
287
288 q = *text;
289
290 /*
291 * make sure the pointer p is within the *text memory.
292 * realloc may have moved it...
293 */
294 p = strstr(q, s);
295
296 if (p==NULL)
297 continue;
298 /* do the actual replacement */
299 memmove(p + dlen, p + slen, strlen(p + slen) + 1);
300 memcpy(p, d, dlen);
301 /* avoid recursion on substituted string */
302 q = p + dlen;
303 }
304
305 return E_SUCCESS;
306 }
307
308
309 /*
310 * Calculate the correct length of characters in an UTF-8 encoded string.
311 */
strlen_utf8(const char * s)312 size_t strlen_utf8(const char *s)
313 {
314 u_char c;
315 size_t len = 0;
316
317 while ((c = *s++)) {
318 if ((c & 0xC0) != 0x80)
319 ++len;
320 }
321
322 return len;
323 }
324
325
326 /*
327 * a reentrant version of strtok
328 */
ec_strtok(char * s,const char * delim,char ** ptrptr)329 char * ec_strtok(char *s, const char *delim, char **ptrptr)
330 {
331 #ifdef HAVE_STRTOK_R
332 return strtok_r(s, delim, ptrptr);
333 #else
334 #warning unsafe strtok
335 /* to avoid the warning on this function (the wrapper macro) */
336 #undef strtok
337 return strtok(s, delim);
338 #endif
339 }
340
341 /*
342 * simulate the getchar() on a buffer instead of on the stdin.
343 * also simulate sleep with s(x) for x seconds.
344 */
getchar_buffer(char ** buf)345 char getchar_buffer(char **buf)
346 {
347 char ret;
348
349 DEBUG_MSG("getchar_buffer: %s", *buf);
350
351 /* the buffer is empty, do nothing */
352 if (**buf == 0)
353 return 0;
354
355 /* simulate the sleep if we find s(x) */
356 if (*(*buf + 0) == 's' && *(*buf + 1) == '(') {
357 char *p;
358 int time = 0;
359
360 p = strchr(*buf, ')');
361 if (p != NULL) {
362
363 *p = '\0';
364
365 /* get the number of seconds to wait */
366 time = atoi(*buf + 2);
367
368 DEBUG_MSG("getchar_buffer: sleeping %d secs", time);
369
370 /* move the buffer after the s(x) */
371 *buf = p + 1;
372
373 ec_usleep(SEC2MICRO(time));
374 }
375 }
376
377 /* get the first char of the buffer */
378 ret = *buf[0];
379
380 /* increment the buffer pointer */
381 *buf = *buf + 1;
382
383 DEBUG_MSG("getchar_buffer: returning %c", ret);
384
385 return ret;
386 }
387
388 /* convert a string of hex values into an array of bytes */
str_hex_to_bytes(char * string,u_char * bytes)389 int str_hex_to_bytes(char *string, u_char *bytes)
390 {
391 char value[3]; /* two for the hex and the NULL terminator */
392 unsigned int value_bin;
393 u_int i;
394 size_t slen;
395
396 slen = strlen(string);
397 for (i = 0; i < slen; i++) {
398 strncpy(value, string + i*2, 2);
399 if (sscanf(value, "%02X", &value_bin) != 1)
400 return -E_INVALID;
401 bytes[i] = value_bin & 0x000000FF;
402 }
403
404 return 0;
405 }
406
407
408 /* print a binary string in hex format */
str_tohex(u_char * bin,size_t len,char * dst,size_t dst_len)409 char * str_tohex(u_char *bin, size_t len, char *dst, size_t dst_len)
410 {
411 size_t i;
412
413 memset(dst, 0, dst_len);
414
415 for (i = 0; i < len; i++)
416 sprintf(dst + i*2, "%02X", bin[i]);
417
418 return dst;
419 }
420
421 /* split ip from port */
ec_strsplit_ipport(char * input,char * ip,u_int16 * port)422 int ec_strsplit_ipport(char *input, char *ip, u_int16 *port)
423 {
424 static char ip_tmp[MAX_ASCII_ADDR_LEN];
425
426 /* Format for IPv4: 1.2.3.4:80 */
427 if (sscanf(input, "%20[0-9.]:%hu", ip_tmp, port) == 2) {
428 strncpy(ip, ip_tmp, strlen(ip_tmp)+1);
429 return E_SUCCESS;
430 }
431
432 /* Format for IPv6: [2001:db8::1]:80 */
433 if (sscanf(input, "[%40[0-9a-fA-F:.]]:%hu", ip_tmp, port) == 2) {
434 strncpy(ip, ip_tmp, strlen(ip_tmp)+1);
435 return E_SUCCESS;
436 }
437
438 DEBUG_MSG("ec_strsplit_ipport(): error splitting ip:port: '%s'\n", input);
439 return -E_INVALID;
440 }
441
442 /* duplicate string in all letters lowercase */
ec_strlc(const char * input)443 const char *ec_strlc(const char *input)
444 {
445 char *output, *ptr;
446
447 ptr = output = strdup(input);
448 do {
449 *ptr = tolower(*ptr);
450 } while (*(ptr++) != 0);
451
452 return output;
453 }
454
455 /* duplicate string in all letters uppercase */
ec_struc(const char * input)456 const char *ec_struc(const char *input)
457 {
458 char *output, *ptr;
459
460 ptr = output = strdup(input);
461 do {
462 *ptr = toupper(*ptr);
463 } while (*(ptr++) != 0);
464
465 return output;
466 }
467
468 /* EOF */
469
470 // vim:ts=3:expandtab
471
472