1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <errno.h>
6
7 #include "logger.h"
8 #include "pldstr.h"
9 #include "bytedecoders.h"
10 #include "olestream-unwrap.h"
11 #include "localization.h"
12 #include "sci_malloc.h"
13 #include "charEncoding.h"
14 #include "os_string.h"
15
16
17 #define DUW if (oleuw->debug)
18
19 struct OLE10_header
20 {
21 unsigned char data[6];
22 char *attach_name;
23 unsigned char data2[8];
24 char *fname_1;
25 char *fname_2;
26 size_t attach_size;
27 size_t attach_size_1;
28 size_t attach_start_offset;
29 };
30
31
32 /*-----------------------------------------------------------------\
33 Function Name : OLEUNWRAP_init
34 Returns Type : int
35 ----Parameter List
36 1. struct OLEUNWRAP_object *oleuw ,
37 ------------------
38 Exit Codes :
39 Side Effects :
40 --------------------------------------------------------------------
41 Comments:
42
43 --------------------------------------------------------------------
44 Changes:
45
46 \------------------------------------------------------------------*/
OLEUNWRAP_init(struct OLEUNWRAP_object * oleuw)47 int OLEUNWRAP_init( struct OLEUNWRAP_object *oleuw )
48 {
49 oleuw->debug = 0;
50 oleuw->verbose = 0;
51 oleuw->filename_report_fn = NULL;
52
53 return OLEUW_OK;
54 }
55
56 /*-----------------------------------------------------------------\
57 Function Name : OLEUNWRAP_set_debug
58 Returns Type : int
59 ----Parameter List
60 1. struct OLEUNWRAP_object *oleuw,
61 2. int level ,
62 ------------------
63 Exit Codes :
64 Side Effects :
65 --------------------------------------------------------------------
66 Comments:
67
68 --------------------------------------------------------------------
69 Changes:
70
71 \------------------------------------------------------------------*/
OLEUNWRAP_set_debug(struct OLEUNWRAP_object * oleuw,int level)72 int OLEUNWRAP_set_debug( struct OLEUNWRAP_object *oleuw, int level )
73 {
74 oleuw->debug = level;
75 return OLEUW_OK;
76 }
77
78 /*-----------------------------------------------------------------\
79 Function Name : OLEUNWRAP_set_verbose
80 Returns Type : int
81 ----Parameter List
82 1. struct OLEUNWRAP_object *oleuw,
83 2. int level ,
84 ------------------
85 Exit Codes :
86 Side Effects :
87 --------------------------------------------------------------------
88 Comments:
89
90 --------------------------------------------------------------------
91 Changes:
92
93 \------------------------------------------------------------------*/
OLEUNWRAP_set_verbose(struct OLEUNWRAP_object * oleuw,int level)94 int OLEUNWRAP_set_verbose( struct OLEUNWRAP_object *oleuw, int level )
95 {
96 oleuw->verbose = level;
97 return OLEUW_OK;
98 }
99
100 /*-----------------------------------------------------------------\
101 Function Name : OLEUNWRAP_set_save_unknown_streams
102 Returns Type : int
103 ----Parameter List
104 1. struct OLEUNWRAP_object *oleuw,
105 2. int level ,
106 ------------------
107 Exit Codes :
108 Side Effects :
109 --------------------------------------------------------------------
110 Comments:
111
112 --------------------------------------------------------------------
113 Changes:
114
115 \------------------------------------------------------------------*/
OLEUNWRAP_set_save_unknown_streams(struct OLEUNWRAP_object * oleuw,int level)116 int OLEUNWRAP_set_save_unknown_streams( struct OLEUNWRAP_object *oleuw, int level )
117 {
118 oleuw->save_unknown_streams = level;
119 return OLEUW_OK;
120 }
121
122
123 /*-----------------------------------------------------------------\
124 Function Name : OLEUNWRAP_save_stream
125 Returns Type : int
126 ----Parameter List
127 1. char *fname,
128 2. char *stream,
129 3. size_t bytes ,
130 ------------------
131 Exit Codes :
132 Side Effects :
133 --------------------------------------------------------------------
134 Comments:
135
136 --------------------------------------------------------------------
137 Changes:
138
139 \------------------------------------------------------------------*/
OLEUNWRAP_save_stream(struct OLEUNWRAP_object * oleuw,char * fname,char * decode_path,char * stream,size_t bytes)140 int OLEUNWRAP_save_stream( struct OLEUNWRAP_object *oleuw, char *fname, char *decode_path, char *stream, size_t bytes )
141 {
142 char *full_name;
143 FILE *f;
144 int result = 0;
145
146 DUW LOGGER_log("%s:%d:OLEUNWRAP_save_stream:DEBUG: fname=%s, decodepath=%s, size=%ld"
147 , FL
148 , fname
149 , decode_path
150 , bytes
151 );
152
153 full_name = PLD_dprintf("%s/%s", decode_path, fname );
154 if (full_name == NULL)
155 {
156 LOGGER_log(_("%s:%d:OLEUNWRAP_save_stream:ERROR: Unable to create filename string from '%s' and '%s'"), FL, fname, decode_path);
157 return -1;
158 }
159
160 wcfopen(f, full_name, "wb");
161 if (f != NULL)
162 {
163 size_t write_count;
164
165 write_count = fwrite( stream, 1, bytes, f );
166 if (write_count != bytes)
167 {
168 LOGGER_log(_("%s:%d:OLEUNWRAP_save_stream:WARNING: Only wrote %d of %d bytes to file %s\n"), FL, write_count, bytes, full_name );
169 }
170
171 fclose(f);
172
173
174 }
175 else
176 {
177 LOGGER_log(_("%s:%d:OLEUNWRAP_save_stream:ERROR: Unable to open %s for writing (%s)\n"), FL, full_name, strerror(errno));
178 result = -1;
179 }
180
181 if (full_name)
182 {
183 FREE(full_name);
184 }
185
186 DUW LOGGER_log("%s:%d:OLEUNWRAP_save_stream:DEBUG: Done saving '%s'", FL, fname);
187
188 return result;
189 }
190
191 /*-----------------------------------------------------------------\
192 Function Name : OLEUNWRAP_sanitize_filename
193 Returns Type : int
194 ----Parameter List
195 1. char *fname ,
196 ------------------
197 Exit Codes :
198 Side Effects :
199 --------------------------------------------------------------------
200 Comments:
201
202 --------------------------------------------------------------------
203 Changes:
204
205 \------------------------------------------------------------------*/
OLEUNWRAP_sanitize_filename(char * fname)206 int OLEUNWRAP_sanitize_filename( char *fname )
207 {
208 while (*fname)
209 {
210 if ( !isalnum((int)*fname) && (*fname != '.') )
211 {
212 *fname = '_';
213 }
214 if ( (*fname < ' ') || (*fname > '~') )
215 {
216 *fname = '_';
217 }
218 fname++;
219 }
220 return 0;
221 }
222
223 /*-----------------------------------------------------------------\
224 Function Name : OLEUNWRAP_decode_attachment
225 Returns Type : int
226 ----Parameter List
227 1. char *stream ,
228 ------------------
229 Exit Codes :
230 Side Effects :
231 --------------------------------------------------------------------
232 Comments:
233
234 --------------------------------------------------------------------
235 Changes:
236
237 \------------------------------------------------------------------*/
OLEUNWRAP_decode_attachment(struct OLEUNWRAP_object * oleuw,char * stream,size_t stream_size,char * decode_path)238 int OLEUNWRAP_decode_attachment( struct OLEUNWRAP_object *oleuw, char *stream, size_t stream_size, char *decode_path )
239 {
240 struct OLE10_header oh;
241 char *sp = stream;
242 char *data_start_point = stream;
243 int result = OLEUW_OK;
244
245 /* Get the data size*/
246 oh.attach_size_1 = (size_t)get_4byte_value( (unsigned char *) sp );
247 sp += 4;
248
249 DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: attachsize = %d, stream length = %d\n", FL, oh.attach_size_1, stream_size );
250
251 oh.attach_start_offset = (stream_size - oh.attach_size_1);
252 data_start_point = stream + oh.attach_start_offset;
253
254 /*if (oh.attach_start_offset == 4)*/
255 if (oh.attach_start_offset < 4)
256 {
257 /* If we only had the stream byte-length in our header*/
258 /* then we know we don't have a complex header.*/
259 oh.attach_name = PLD_dprintf("unknown-%ld", oh.attach_size_1);
260 oh.attach_size = oh.attach_size_1;
261 }
262 else
263 {
264
265 DUW LOGGER_log("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Decoding file information header", FL);
266 /* Unknown memory segment*/
267 memcpy( oh.data, sp, 2 );
268 sp += 2;
269
270 /* Full attachment string*/
271 oh.attach_name = os_strdup( sp );
272 sp = sp + strlen(oh.attach_name) + 1;
273
274 /* Attachment full path*/
275 oh.fname_1 = os_strdup( sp );
276 sp += strlen(oh.fname_1) + 1;
277
278 /* Unknown memory segment*/
279 memcpy( oh.data2, sp, 8 );
280 sp = sp + 8;
281
282 /* Attachment full path*/
283 oh.fname_2 = os_strdup( sp );
284 sp += strlen(oh.fname_2) + 1;
285
286 oh.attach_size = (size_t)get_4byte_value( (unsigned char*) sp );
287 sp += 4;
288
289 if (oh.attach_size > stream_size)
290 {
291 oh.attach_size = stream_size;
292 }
293
294 data_start_point = sp;
295 }
296
297 DUW LOGGER_log(_("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Attachment %s:%s:%s size = %d\n"), FL, oh.attach_name, oh.fname_1, oh.fname_2, oh.attach_size );
298
299
300 /** 20050119:2053:PLD - Added to sanitize 8-bit filenames **/
301 /** Sanitize the output filename **/
302 OLEUNWRAP_sanitize_filename(oh.attach_name);
303 OLEUNWRAP_sanitize_filename(oh.fname_1);
304 OLEUNWRAP_sanitize_filename(oh.fname_2);
305
306 result = OLEUNWRAP_save_stream( oleuw, oh.attach_name, decode_path, data_start_point, oh.attach_size );
307 if (result == OLEUW_OK)
308 {
309 if (oleuw->debug > 0)
310 {
311 LOGGER_log(_("%s:%d:OLEUNWRAP_decode_attachment:DEBUG: Calling reporter for the filename"), FL);
312 }
313 if ((oleuw->verbose > 0) && (oleuw->filename_report_fn != NULL))
314 {
315 oleuw->filename_report_fn(oh.attach_name);
316 }
317 /* Do call back to reporting function*/
318 }
319
320 /* Clean up our previously allocated data*/
321 if (oh.fname_1 != NULL)
322 {
323 FREE(oh.fname_1);
324 }
325 if (oh.attach_name != NULL)
326 {
327 FREE(oh.attach_name);
328 }
329 if (oh.fname_2 != NULL)
330 {
331 FREE(oh.fname_2);
332 }
333
334 return OLEUW_OK;
335 }
336
337 /*-----------------------------------------------------------------\
338 Function Name : OLEUNWRAP_decodestream
339 Returns Type : int
340 ----Parameter List
341 1. char *element_string,
342 2. char *stream ,
343 ------------------
344 Exit Codes :
345 Side Effects :
346 --------------------------------------------------------------------
347 Comments:
348
349 --------------------------------------------------------------------
350 Changes:
351
352 \------------------------------------------------------------------*/
OLEUNWRAP_decodestream(struct OLEUNWRAP_object * oleuw,char * element_string,char * stream,size_t stream_size,char * decode_path)353 int OLEUNWRAP_decodestream( struct OLEUNWRAP_object *oleuw, char *element_string, char *stream, size_t stream_size, char *decode_path )
354 {
355 int result = OLEUW_OK;
356
357 if (strstr(element_string, OLEUW_ELEMENT_10NATIVE_STRING) != NULL)
358 {
359 OLEUNWRAP_decode_attachment( oleuw, stream, stream_size, decode_path );
360
361 }
362 else
363 {
364 if (oleuw->debug)
365 {
366 LOGGER_log(_("Unable to decode stream with element string '%s'\n"), element_string);
367 }
368 result = OLEUW_STREAM_NOT_DECODED;
369 }
370
371 return result;
372 }
373
374
375 /*-----------------------------------------------------------------\
376 Function Name : OLEUNWRAP_set_filename_report_fn
377 Returns Type : int
378 ----Parameter List
379 1. struct OLEUNWRAP_object *oleuw,
380 2. int (*ptr_to_fn)(char *) ,
381 ------------------
382 Exit Codes :
383 Side Effects :
384 --------------------------------------------------------------------
385 Comments:
386
387 --------------------------------------------------------------------
388 Changes:
389
390 \------------------------------------------------------------------*/
OLEUNWRAP_set_filename_report_fn(struct OLEUNWRAP_object * oleuw,int (* ptr_to_fn)(char *))391 int OLEUNWRAP_set_filename_report_fn( struct OLEUNWRAP_object *oleuw, int (*ptr_to_fn)(char *) )
392 {
393
394 oleuw->filename_report_fn = ptr_to_fn;
395
396 return 0;
397 }
398
399