Imported Upstream version 2.7
[ossec-hids.git] / src / rootcheck / os_string.c
1 /* @(#) $Id: ./src/rootcheck/os_string.c, 2011/09/08 dcid Exp $
2  */
3
4 /* Included and modified strings.c from the OpenBSD project.
5  * Copyright bellow.
6  */
7
8 /*
9  * Copyright (c) 1980, 1987, 1993
10  *      The Regents of the University of California.  All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36
37
38 #ifndef WIN32
39 #include <sys/types.h>
40
41 #include <ctype.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <locale.h>
48 #include <unistd.h>
49
50 #include <netinet/in.h>
51
52
53 /* Again, making solaris happy... */
54 #ifdef SOLARIS
55 #include <sys/exechdr.h>
56
57 #elif defined Darwin || defined HPUX
58
59 /* For some reason darwin does not have that */
60 struct exec
61 {
62   unsigned long a_info;         /* Use macros N_MAGIC, etc for access */
63   unsigned char   a_machtype;     /* machine type */
64   unsigned short  a_magic;        /* magic number */
65   unsigned a_text;              /* length of text, in bytes */
66   unsigned a_data;              /* length of data, in bytes */
67   unsigned a_bss;               /* length of uninitialized data area for file, in bytes */
68   unsigned a_syms;              /* length of symbol table data in file, in bytes */
69   unsigned a_entry;             /* start address */
70   unsigned a_trsize;            /* length of relocation info for text, in bytes */
71   unsigned a_drsize;            /* length of relocation info for data, in bytes */
72 };
73 #define OMAGIC 0407             /* Object file or impure executable.  */
74 #define NMAGIC 0410             /* Code indicating pure executable.  */
75 #define ZMAGIC 0413             /* Code indicating demand-paged executable.  */
76 #define BMAGIC 0415             /* Used by a b.out object.  */
77 #define M_OLDSUN2       0
78
79 #else
80
81 #include <a.out.h>
82 #endif
83
84
85 #ifndef PAGSIZ
86 #define       PAGSIZ          0x02000
87 #endif
88
89 #ifndef OLD_PAGSIZ
90 #define       OLD_PAGSIZ      0x00800
91 #endif
92
93 #ifndef N_BADMAG
94
95 #ifdef AIX
96 #define       N_BADMAG(x) \
97     (((x).magic)!=U802TOCMAGIC && ((x).magic)!=U803TOCMAGIC && ((x).magic)!=U803XTOCMAGIC && ((x).magic)!=U64_TOCMAGIC)
98 #else /* non AIX */
99 #define       N_BADMAG(x) \
100     (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC)
101 #endif
102
103 #endif  /* N_BADMAG */
104
105 #ifndef N_PAGSIZ
106 #define       N_PAGSIZ(x) \
107         ((x).a_machtype == M_OLDSUN2? OLD_PAGSIZ : PAGSIZ)
108 #endif
109
110 #ifndef N_TXTOFF
111
112 #ifdef AIX
113 #define         N_TXTOFF(x) \
114         /* text segment */ \
115             ((x).magic==U64_TOCMAGIC ? 0 : sizeof (struct aouthdr))
116 #else /* non AIX */
117 #define       N_TXTOFF(x) \
118         /* text segment */ \
119     ((x).a_machtype == M_OLDSUN2 \
120            ? ((x).a_magic==ZMAGIC ? N_PAGSIZ(x) : sizeof (struct exec)) \
121            : ((x).a_magic==ZMAGIC ? 0 : sizeof (struct exec)) )
122 #endif
123
124 #endif /* N_TXTOFF */
125
126
127 #include "headers/defs.h"
128 #include "headers/debug_op.h"
129 #include "headers/regex_op.h"
130
131 #include "error_messages/error_messages.h"
132
133 #define STR_MINLEN  4       /* Minumum length for a string */
134
135 #define ISSTR(ch)       (isascii(ch) && (isprint(ch) || ch == '\t'))
136
137
138 #ifdef AIX
139 typedef struct aouthdr EXEC;
140 #else
141 typedef struct exec EXEC;
142 #endif
143
144 typedef struct _os_strings
145 {
146     int head_len;
147     int read_len;
148     int hcnt;
149     long foff;
150     unsigned char hbfr[sizeof(EXEC)];
151     FILE *fp;
152 }os_strings;
153
154
155 /* os_getch: Read each character from a binary file */
156 int os_getch(os_strings *oss);
157
158
159 /* os_strings: List the strings of a binary and
160  * check if the regex given is there.
161  */
162 int os_string(char *file, char *regex)
163 {
164     int ch, cnt;
165
166     unsigned char *C;
167     unsigned char *bfr;
168
169     char line[OS_SIZE_1024 +1];
170     char *buf;
171
172     EXEC *head;
173
174     os_strings oss;
175
176     /* Return didn't match */
177     if(!file || !regex)
178     {
179         return(0);
180     }
181
182
183     /* Allocating for the buffer */
184     bfr = calloc(STR_MINLEN + 2, sizeof(char *));
185     if (!bfr)
186     {
187         merror(MEM_ERROR, ARGV0);
188         return(0);
189     }
190
191     /* Opening the file */
192     oss.fp = fopen(file, "r");
193     if(!oss.fp)
194     {
195         free(bfr);
196         return(0);
197     }
198
199     /* cleaning the line */
200     memset(line, '\0', OS_SIZE_1024 +1);
201
202     /* starting .. (from old strings.c) */
203     oss.foff = 0;
204     oss.head_len = 0;
205
206     oss.read_len = -1;
207     head = (EXEC *)oss.hbfr;
208
209
210     if ((oss.head_len = read(fileno(oss.fp), head, sizeof(EXEC))) == -1)
211     {
212         oss.head_len = 0;
213         oss.read_len = -1;
214     }
215     else if (oss.head_len == sizeof(EXEC) && !N_BADMAG(*head))
216     {
217         oss.foff = N_TXTOFF(*head);
218         if (fseek(stdin, oss.foff, SEEK_SET) == -1)
219         {
220             oss.read_len = -1;
221         }
222         else
223         {
224             #ifdef AIX
225             oss.read_len = head->tsize + head->dsize;
226             #else
227             oss.read_len = head->a_text + head->a_data;
228             #endif
229         }
230
231         oss.head_len = 0;
232     }
233     else
234     {
235         oss.hcnt = 0;
236     }
237
238     /* Read the file and perform the regex comparison */
239     for (cnt = 0; (ch = os_getch(&oss)) != EOF;)
240     {
241         if (ISSTR(ch))
242         {
243             if (!cnt)
244                 C = bfr;
245             *C++ = ch;
246             if (++cnt < STR_MINLEN)
247                 continue;
248
249             strncpy(line, (char *)bfr, STR_MINLEN +1);
250             buf = line;
251             buf+=strlen(line);
252
253
254             while ((ch = os_getch(&oss)) != EOF && ISSTR(ch))
255             {
256                 if(cnt < OS_SIZE_1024)
257                 {
258                     *buf = (char)ch;
259                     buf++;
260                 }
261                 else
262                 {
263                     *buf = '\0';
264                     break;
265                 }
266                 cnt++;
267             }
268
269             *buf = '\0';
270
271             if(OS_PRegex(line, regex))
272             {
273                 if(oss.fp)
274                     fclose(oss.fp);
275                 free(bfr);
276                 return(1);
277             }
278         }
279
280         cnt = 0;
281     }
282
283     if(oss.fp)
284         fclose(oss.fp);
285     free(bfr);
286     return(0);
287 }
288
289
290 /*
291  * getch (os_getch, modified)--
292  *      get next character from wherever
293  */
294 int os_getch(os_strings *oss)
295 {
296         ++oss->foff;
297         if (oss->head_len)
298     {
299                 if (oss->hcnt < oss->head_len)
300                         return((int)oss->hbfr[oss->hcnt++]);
301                 oss->head_len = 0;
302         }
303         if (oss->read_len == -1 || oss->read_len-- > 0)
304     {
305                 return(fgetc(oss->fp));
306     }
307         return(EOF);
308 }
309
310 /* EOF */
311 #else
312 int os_string(char *file, char *regex)
313 {
314     return(0);
315 }
316 #endif