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