libclamav/binhex.c
e72de3f1
 /*
2023340a
  *  Copyright (C) 2007-2008 Sourcefire, Inc.
  *
  *  Authors: Nigel Horne
e72de3f1
  *
  *  This program is free software; you can redistribute it and/or modify
2023340a
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
e72de3f1
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
48b7b4a7
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  *  MA 02110-1301, USA.
e72de3f1
  *
  * Change History:
  * $Log: binhex.c,v $
95e11e5a
  * Revision 1.23  2007/02/12 20:46:08  njh
  * Various tidy
  *
f8ff8f45
  * Revision 1.22  2006/07/31 09:19:52  njh
  * Use MAP_PRIVATE
  *
2673dc74
  * Revision 1.21  2006/07/01 16:17:35  njh
  * Added destroy flag
  *
826864d6
  * Revision 1.20  2006/07/01 03:47:50  njh
  * Don't loop if binhex runs out of memory
  *
d4a7dd82
  * Revision 1.19  2006/05/19 11:02:12  njh
  * Just include mbox.h
  *
48b7b4a7
  * Revision 1.18  2006/04/09 19:59:27  kojm
  * update GPL headers with new address for FSF
  *
8370b950
  * Revision 1.17  2005/11/06 14:03:26  nigelhorne
  * Ensure NAME_MAX isn't redefined on BeOS
  *
9b1e1206
  * Revision 1.16  2005/05/14 16:13:25  nigelhorne
  * Ensure munmap is the right size
  *
1703bd9f
  * Revision 1.15  2005/05/13 19:30:34  nigelhorne
  * Clean cli_realloc call
  *
9c107190
  * Revision 1.14  2005/03/10 08:51:30  nigelhorne
  * Tidy
  *
86ef406e
  * Revision 1.13  2005/01/19 05:29:41  nigelhorne
  * tidy
  *
7e7a86af
  * Revision 1.12  2004/12/27 14:17:14  nigelhorne
  * Fix segfault if write to temporary file fails
  *
3e6a3afa
  * Revision 1.11  2004/12/17 12:03:38  nigelhorne
  * Tidy up for machines without MMAP
  *
e7aa5e3d
  * Revision 1.10  2004/12/16 15:29:51  nigelhorne
  * Tidy
  *
564b3e07
  * Revision 1.9  2004/11/28 22:06:39  nigelhorne
  * Tidy space only headers code
  *
9ed148a8
  * Revision 1.8  2004/11/28 21:05:50  nigelhorne
  * Handle headers with only spaces
  *
1509feea
  * Revision 1.7  2004/11/23 09:05:26  nigelhorne
  * Fix crash in base64 encoded binhex files
  *
0ab539cc
  * Revision 1.6  2004/11/22 15:16:53  nigelhorne
  * Use cli_realloc instead of many cli_mallocs
  *
fb97009a
  * Revision 1.5  2004/11/18 20:11:34  nigelhorne
  * Fix segfault
  *
667ab9c6
  * Revision 1.4  2004/11/18 19:30:29  kojm
  * add support for Mac's HQX file format
  *
359e9fae
  * Revision 1.3  2004/11/18 18:24:45  nigelhorne
  * Added binhex.h
  *
e72de3f1
  * Revision 1.2  2004/11/18 18:09:06  nigelhorne
  * First draft of binhex.c
  *
  */
95e11e5a
 static	char	const	rcsid[] = "$Id: binhex.c,v 1.23 2007/02/12 20:46:08 njh Exp $";
e72de3f1
 
 #include "clamav.h"
 
 #if HAVE_CONFIG_H
 #include "clamav-config.h"
 #endif
 
 #ifdef CL_THREAD_SAFE
 #ifndef	_REENTRANT
 #define	_REENTRANT	/* for Solaris 2.8 */
 #endif
 #endif
 
7f49ea4b
 #ifdef	HAVE_MMAP
e72de3f1
 #if HAVE_SYS_MMAN_H
 #include <sys/mman.h>
 #else /* HAVE_SYS_MMAN_H */
 #undef HAVE_MMAP
 #endif
 #endif
 
 #include <stdio.h>
 #include <memory.h>
 #include <sys/stat.h>
8370b950
 #include "others.h"
d4a7dd82
 
e72de3f1
 #include "mbox.h"
359e9fae
 #include "binhex.h"
e72de3f1
 
 int
 cli_binhex(const char *dir, int desc)
 {
3e6a3afa
 #ifndef HAVE_MMAP
 	cli_warnmsg("File not decoded - binhex decoding needs mmap() (for now)\n");
 	return CL_CLEAN;
 #else
e72de3f1
 	struct stat statb;
0ab539cc
 	char *buf, *start, *line;
1509feea
 	size_t size;
e7aa5e3d
 	long bytesleft;
e72de3f1
 	message *m;
 	fileblob *fb;
 
 	if(fstat(desc, &statb) < 0)
 		return CL_EOPEN;
 
9c107190
 	size = (size_t)statb.st_size;
86ef406e
 
 	if(size == 0)
 		return CL_CLEAN;
 
e72de3f1
 	m = messageCreate();
 	if(m == NULL)
 		return CL_EMEM;
 
f8ff8f45
 	start = buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, desc, 0);
e7aa5e3d
 	if(buf == MAP_FAILED) {
 		messageDestroy(m);
871177cd
 		return CL_EMAP;
e7aa5e3d
 	}
e72de3f1
 
 	cli_dbgmsg("mmap'ed binhex file\n");
 
9b1e1206
 	bytesleft = (long)size;
0ab539cc
 	line = NULL;
e72de3f1
 
1509feea
 	while(bytesleft > 0) {
e72de3f1
 		int length = 0;
1703bd9f
 		char *ptr, *newline;
e72de3f1
 
1509feea
 		/*printf("%d: ", bytesleft);*/
fb97009a
 
e7aa5e3d
 		for(ptr = buf; bytesleft && (*ptr != '\n') && (*ptr != '\r'); ptr++) {
e72de3f1
 			length++;
 			--bytesleft;
 		}
 
1509feea
 		/*printf("%d: ", length);*/
e72de3f1
 
1703bd9f
 		newline = cli_realloc(line, (size_t)(length + 1));
 		if(newline == NULL)
 			break;
 
 		line = newline;
e72de3f1
 
 		memcpy(line, buf, length);
 		line[length] = '\0';
 
1509feea
 		/*puts(line);*/
e72de3f1
 
564b3e07
 		if(messageAddStr(m, line) < 0)
e72de3f1
 			break;
 
e7aa5e3d
 		if((bytesleft > 0) && (*ptr == '\r')) {
 			ptr++;
 			bytesleft--;
 		}
e72de3f1
 		buf = ++ptr;
fb97009a
 		bytesleft--;
e72de3f1
 	}
 	munmap(start, size);
 
0ab539cc
 	if(line)
 		free(line);
 
 	if(binhexBegin(m) == NULL) {
e72de3f1
 		messageDestroy(m);
f2d79ab3
 		cli_dbgmsg("No binhex line found\n");
e72de3f1
 		return CL_EFORMAT;
 	}
95e11e5a
 
826864d6
 	/* similar to binhexMessage */
e72de3f1
 	messageSetEncoding(m, "x-binhex");
 
2673dc74
 	fb = messageToFileblob(m, dir, 1);
e72de3f1
 	if(fb) {
 		cli_dbgmsg("Binhex file decoded to %s\n", fileblobGetFilename(fb));
 		fileblobDestroy(fb);
 	} else
7e7a86af
 		cli_errmsg("Couldn't decode binhex file to %s\n", dir);
e72de3f1
 	messageDestroy(m);
 
 	if(fb)
 		return CL_CLEAN;	/* a lie - but it gets things going */
871177cd
 	/* return CL_EIO; */	/* probably CL_EMEM, but we can't tell at this layer */
 	return CL_EMEM;
e72de3f1
 #endif
 }