integrate the DLP code from Marty Roesch

git-svn: trunk@3795
remotes/push_mirror/metadata
Tomasz Kojm 18 years ago
parent 440fcf67fa
commit a6e388001a
  1. 6
      ChangeLog
  2. 1
      clamscan/clamscan.c
  3. 1
      clamscan/clamscan_opt.h
  4. 9
      clamscan/manager.c
  5. 4
      libclamav/Makefile.am
  6. 9
      libclamav/Makefile.in
  7. 15
      libclamav/clamav.h
  8. 354
      libclamav/dlp.c
  9. 136
      libclamav/dlp.h
  10. 1
      libclamav/others.h
  11. 85
      libclamav/scanners.c

@ -1,3 +1,9 @@
Wed Apr 16 20:10:17 CEST 2008 (tk)
----------------------------------
* libclamav: integrate the DLP code from Marty Roesch
* clamscan: new switch --detect-structured
* TODO: clamd, docs, dconf, fine-tuning options
Wed Apr 16 19:32:12 CEST 2008 (acab)
------------------------------------
* configure: check for bzip2 CVE-2008-1372 - bb#903

@ -306,6 +306,7 @@ void help(void)
#endif
mprintf("\n");
mprintf(" --detect-pua Detect Possibly Unwanted Applications\n");
mprintf(" --detect-structured Detect structured data (SSN, Credit Card)\n");
mprintf(" --no-mail Disable mail file support\n");
mprintf(" --no-phishing-sigs Disable signature-based phishing detection\n");
mprintf(" --no-phishing-scan-urls Disable url-based phishing detection\n");

@ -59,6 +59,7 @@ static struct option clamscan_longopt[] = {
{"max-recursion", 1, 0, 0},
{"max-dir-recursion", 1, 0, 0},
{"detect-pua", 0, 0, 0},
{"detect-structured", 0, 0, 0},
{"disable-archive", 0, 0, 0},
{"no-archive", 0, 0, 0},
{"detect-broken", 0, 0, 0},

@ -308,6 +308,15 @@ int scanmanager(const struct optstruct *opt)
else
options |= CL_SCAN_ALGORITHMIC;
if(opt_check(opt, "detect-structured")) {
options |= CL_SCAN_STRUCTURED;
limits.min_cc_count = 1;
limits.min_ssn_count = 1;
limits.structured_flags = CL_STRUCTURED_CONF_SSN_BOTH;
} else
options &= ~CL_SCAN_STRUCTURED;
#ifdef C_LINUX
procdev = (dev_t) 0;
if(stat("/proc", &sb) != -1 && !sb.st_size)

@ -186,7 +186,9 @@ libclamav_la_SOURCES = \
explode.c \
explode.h \
textnorm.c \
textnorm.h
textnorm.h \
dlp.c \
dlp.h
libclamav_internal_utils_la_SOURCES=str.c \
str.h \

@ -55,7 +55,7 @@ target_triplet = @target@
@VERSIONSCRIPT_TRUE@am__append_1 = -Wl,@VERSIONSCRIPTFLAG@,@top_srcdir@/libclamav/libclamav.map
subdir = libclamav
DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
$(srcdir)/Makefile.in COPYING
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
$(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
@ -89,7 +89,7 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher.lo \
infblock.lo pdf.lo spin.lo yc.lo elf.lo sis.lo uuencode.lo \
phishcheck.lo phish_domaincheck_db.lo phish_whitelist.lo \
regex_list.lo mspack.lo cab.lo entconv.lo hashtab.lo dconf.lo \
lzma_iface.lo explode.lo textnorm.lo
lzma_iface.lo explode.lo textnorm.lo dlp.lo
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
libclamav_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@ -421,7 +421,9 @@ libclamav_la_SOURCES = \
explode.c \
explode.h \
textnorm.c \
textnorm.h
textnorm.h \
dlp.c \
dlp.h
libclamav_internal_utils_la_SOURCES = str.c \
str.h \
@ -522,6 +524,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chmunpack.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cvd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dconf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsig.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entconv.Plo@am__quote@

@ -92,6 +92,8 @@ extern "C"
#define CL_SCAN_PHISHING_BLOCKCLOAK 0x1000
#define CL_SCAN_ELF 0x2000
#define CL_SCAN_PDF 0x4000
#define CL_SCAN_STRUCTURED 0x8000
/* recommended scan settings */
#define CL_SCAN_STDOPT (CL_SCAN_ARCHIVE | CL_SCAN_MAIL | CL_SCAN_OLE2 | CL_SCAN_HTML | CL_SCAN_PE | CL_SCAN_ALGORITHMIC | CL_SCAN_ELF)
@ -143,6 +145,11 @@ struct cl_engine {
void *ignored;
};
/* Structured data flags */
#define CL_STRUCTURED_CONF_SSN_BOTH 0x00
#define CL_STRUCTURED_CONF_SSN_NORMAL 0x01
#define CL_STRUCTURED_CONF_SSN_STRIPPED 0x02
struct cl_limits {
unsigned long int maxscansize; /* during the scanning of archives this size
* will never be exceeded
@ -155,6 +162,14 @@ struct cl_limits {
* within a single archive
*/
unsigned short archivememlim; /* limit memory usage for some unpackers */
/* This is for structured data detection. You can set the minimum
* number of occurences of an CC# or SSN before the system will
* generate a notification.
*/
unsigned long min_cc_count;
unsigned long min_ssn_count;
unsigned long structured_flags;
};
struct cl_stat {

@ -0,0 +1,354 @@
/*
* Simple library to detect and validate SSN and Credit Card numbers.
*
* Copyright (C) 2007-2008 Sourcefire, Inc.
*
* Authors: Martin Roesch <roesch@sourcefire.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "dlp.h"
/* detection mode macros for the contains_* functions */
#define DETECT_MODE_DETECT 0
#define DETECT_MODE_COUNT 1
/* group number mapping is here */
/* http://www.socialsecurity.gov/employer/highgroup.txt */
/* here's a perl script to convert the raw data from the highgroup.txt
* file to the data set in ssn_max_group[]:
--
local $/;
my $i = <>;
my $count = 0;
while ($i =~ s/(\d{3}) (\d{2})//) {
print int($2) .", ";
if ($count == 18)
{
print "\n";
$count = 0;
}
else
{
$count++;
}
}
--
*
* run 'perl convert.pl < highgroup.txt' to generate the data
*
*/
/* MAX_AREA is the maximum assigned area number. This can be derived from
* the data in the highgroup.txt file by looking at the last area->group
* mapping from that file.
*/
#define MAX_AREA 772
/* array of max group numbers for a given area number */
static int ssn_max_group[MAX_AREA+1] = { 0,
6, 6, 4, 8, 8, 8, 6, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 88, 88, 88, 88, 72, 72, 72, 72,
70, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
96, 96, 96, 96, 96, 96, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
94, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 82, 82, 82, 82, 82, 82, 82, 82,
82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
82, 82, 79, 79, 79, 79, 79, 79, 79, 79, 77, 6, 4, 99, 99, 99, 99, 99, 99,
99, 99, 99, 53, 53, 53, 53, 53, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 33, 33,
31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4,
35, 35, 35, 35, 35, 35, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
33, 33, 33, 33, 33, 33, 29, 29, 29, 29, 29, 29, 29, 29, 27, 27, 27, 27, 27,
67, 67, 67, 67, 67, 67, 67, 67, 99, 99, 99, 99, 99, 99, 99, 99, 63, 61, 61,
61, 61, 61, 61, 61, 61, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 23, 23, 23, 23, 23, 23, 23, 21, 21, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 51, 51, 51, 51, 49, 49, 49, 49,
49, 49, 37, 37, 37, 37, 37, 37, 37, 37, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 23, 23, 23, 33, 33, 41, 39, 53, 51, 51, 51, 27, 27, 27, 27, 27,
27, 27, 45, 43, 79, 77, 55, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 63, 63,
63, 61, 61, 61, 61, 61, 61, 75, 73, 73, 73, 73, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 51, 99, 99, 45, 45, 43, 37, 99, 99, 99, 99, 99, 61, 99, 3, 99,
99, 99, 99, 99, 99, 99, 84, 84, 84, 84, 99, 99, 67, 67, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 96,
96, 44, 44, 46, 46, 46, 44, 28, 26, 26, 26, 26, 16, 16, 16, 14, 14, 14, 14,
36, 34, 34, 34, 34, 34, 34, 34, 34, 14, 14, 12, 12, 90, 14, 14, 14, 14, 12,
12, 12, 12, 12, 12, 9, 9, 7, 7, 7, 7, 7, 7, 7, 18, 18, 18, 18, 18,
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
28, 18, 18, 10, 14, 10, 10, 10, 10, 10, 9, 9, 3, 1, 5, 5, 5, 5, 5,
5, 3, 3, 82, 82, 66, 66, 64, 64, 64, 64, 64
};
int dlp_is_valid_cc(const unsigned char *buffer, int length)
{
int even = 0;
int sum = 0;
int i = 0;
int val = 0;
if(buffer == NULL || length < 13)
return 0;
/* if the first digit is greater than 6 it isn't one of the major
* credit cards
* reference => http://www.beachnet.com/~hstiles/cardtype.html
*/
if(buffer[0] > '6')
return 0;
if(length > 16)
length = 16;
for(i = length - 1; i > -1; i--)
{
if(isdigit(buffer[i]) == 0)
continue;
val = buffer[i] - '0';
if(even)
{
if((val *= 2) > 9) val = (val - 10) + 1;
}
even = !even;
sum += val;
}
return (sum % 10 == 0);
}
static int contains_cc(const unsigned char *buffer, int length, int detmode)
{
const unsigned char *idx;
const unsigned char *end;
int count = 0;
if(buffer == NULL || length < 13)
{
return 0;
}
end = buffer + length;
idx = buffer;
while(idx < end)
{
if(isdigit(*idx))
{
if(dlp_is_valid_cc(idx, length - (idx - buffer)) == 1)
{
if(detmode == DETECT_MODE_DETECT)
return 1;
else
{
count++;
/* if we got a valid match we should increment the idx ptr
* to gain a little performance
*/
idx += (length > 15?15:(length-1));
}
}
}
idx++;
}
return count;
}
int dlp_get_cc_count(const unsigned char *buffer, int length)
{
return contains_cc(buffer, length, DETECT_MODE_COUNT);
}
int dlp_has_cc(const unsigned char *buffer, int length)
{
return contains_cc(buffer, length, DETECT_MODE_DETECT);
}
int dlp_is_valid_ssn(const unsigned char *buffer, int length, int format)
{
int area_number;
int group_number;
int serial_number;
int minlength;
int retval = 1;
if(buffer == NULL)
return 0;
minlength = (format==SSN_FORMAT_HYPHENS?11:9);
if(length < minlength)
return 0;
/* sscanf parses and (basically) validates the string for us */
switch(format)
{
case SSN_FORMAT_HYPHENS:
if(sscanf((const char *) buffer,
"%3d-%2d-%4d",
&area_number,
&group_number,
&serial_number) != 3)
{
return 0;
}
break;
case SSN_FORMAT_STRIPPED:
if(sscanf((const char *) buffer,
"%3d%2d%4d",
&area_number,
&group_number,
&serial_number) != 3)
{
return 0;
}
break;
}
/* start validating */
/* validation data taken from
* http://en.wikipedia.org/wiki/Social_Security_number_%28United_States%29
*/
if(area_number > MAX_AREA ||
area_number == 666 ||
area_number <= 0 ||
group_number <= 0 ||
group_number > 99 ||
serial_number <= 0 ||
serial_number > 9999)
retval = 0;
if(area_number == 987 && group_number == 65)
{
if(serial_number >= 4320 && serial_number <= 4329)
retval = 0;
}
if(group_number > ssn_max_group[area_number])
retval = 0;
return retval;
}
static int contains_ssn(const unsigned char *buffer, int length, int format, int detmode)
{
const unsigned char *idx;
const unsigned char *end;
int count = 0;
if(buffer == NULL || length < 11)
return 0;
end = buffer + length;
idx = buffer;
while(idx < end)
{
if(isdigit(*idx))
{
/* check for area number and the first hyphen */
if(dlp_is_valid_ssn(idx, length - (idx - buffer), format) == 1)
{
if(detmode == DETECT_MODE_COUNT)
{
count++;
/* hop over the matched bytes if we found an SSN */
idx += ((format == SSN_FORMAT_HYPHENS)?11:9);
}
else
{
return 1;
}
}
}
idx++;
}
return count;
}
int dlp_get_stripped_ssn_count(const unsigned char *buffer, int length)
{
return contains_ssn(buffer,
length,
SSN_FORMAT_STRIPPED,
DETECT_MODE_COUNT);
}
int dlp_get_normal_ssn_count(const unsigned char *buffer, int length)
{
return contains_ssn(buffer,
length,
SSN_FORMAT_HYPHENS,
DETECT_MODE_COUNT);
}
int dlp_get_ssn_count(const unsigned char *buffer, int length)
{
/* this will suck for performance but will find SSNs in either
* format
*/
return (dlp_get_stripped_ssn_count(buffer, length) + dlp_get_normal_ssn_count(buffer, length));
}
int dlp_has_ssn(const unsigned char *buffer, int length)
{
return (contains_ssn(buffer,
length,
SSN_FORMAT_HYPHENS,
DETECT_MODE_DETECT)
| contains_ssn(buffer,
length,
SSN_FORMAT_STRIPPED,
DETECT_MODE_DETECT));
}
int dlp_has_stripped_ssn(const unsigned char *buffer, int length)
{
return contains_ssn(buffer,
length,
SSN_FORMAT_STRIPPED,
DETECT_MODE_DETECT);
}
int dlp_has_normal_ssn(const unsigned char *buffer, int length)
{
return contains_ssn(buffer,
length,
SSN_FORMAT_HYPHENS,
DETECT_MODE_DETECT);
}

@ -0,0 +1,136 @@
/*
* Simple library to detect and validate SSN and Credit Card numbers.
*
* Copyright (C) 2007-2008 Sourcefire, Inc.
*
* Authors: Martin Roesch <roesch@sourcefire.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#ifndef __DLP_H_
#define __DLP_H_
#include <stdio.h>
/* these macros define the SSN string format to search for */
#define SSN_FORMAT_HYPHENS 0 /* xxx-yy-zzzz */
#define SSN_FORMAT_STRIPPED 1 /* xxxyyzzzz */
/*
* will check if a valid credit card number exists within the
* first 16 bytes of the supplied buffer. Validation supplied
* via the Luhn algorithm.
* Params:
* buffer => data buffer to be validated.
* length => length of supplied buffer. Values greater than 16 are
* truncated to 16. Values less than 13 are rejected.
* Returns:
* 1 on a find, 0 on a miss
*/
int dlp_is_valid_cc(const unsigned char *buffer, int length);
/* Searches the supplied buffer for credit card numbers and returns
* the number of CC's found.
* Params:
* buffer => data buffer to be analyzed.
* length => length of buffer.
* Returns:
* Count of detected CC #'s.
*/
int dlp_get_cc_count(const unsigned char *buffer, int length);
/* Searches the supplied buffer for CC #'s. Bails out as soon as a
* validated number is detected.
* Params:
* buffer => data buffer to be analyzed.
* length => length of buffer.
* Returns:
* 1 on detect, 0 on fail
*/
int dlp_has_cc(const unsigned char *buffer, int length);
/* Checks the supplied buffer for a valid SSN number. Validation
* is supplied via area and group number validation. Valid numbers
* which are not in circulation (666 series, 000 series) are NOT
* detected, only numbers that can be valid in the real world. Searches
* only the first 11 or 9 bytes (based on the selected format)!
* Params:
* buffer => buffer to be validated
* length => length of buffer to validate
* Returns:
* 1 on detect, 0 on failure
*/
int dlp_is_valid_ssn(const unsigned char *buffer, int length, int format);
/* Searches the supplied buffer for valid SSNs. Note that this function
* is effectively searching the buffer TWICE looking for the hyphenated and
* stripped forms of the SSN. There will be a performance impact!
* Params:
* buffer => buffer to search
* length => length of the buffer
* Returns:
* Count of SSNs in the supplied buffer
*/
int dlp_get_ssn_count(const unsigned char *buffer, int length);
/* Searches the supplied buffer for valid SSNs formatted as xxxyyzzzz.
* Params:
* buffer => buffer to search
* length => length of the buffer
* Returns:
* Count of SSNs in the supplied buffer.
*/
int dlp_get_stripped_ssn_count(const unsigned char *buffer, int length);
/* Searches the supplied buffer for valid SSNs formatted as xxx-yy-zzzz.
* Params:
* buffer => buffer to search
* length => length of the buffer
* Returns:
* Count of SSNs in the supplied buffer.
*/
int dlp_get_normal_ssn_count(const unsigned char *buffer, int length);
/* Searches the supplied buffer for a SSN in any format. This searches the
* buffer twice for both the stripped and hyphenated versions of an SSN so
* there will be a performance impact!
* Params:
* buffer => buffer to search
* length => length of the buffer
* Returns:
* 1 on detect, 0 on fail
*/
int dlp_has_ssn(const unsigned char *buffer, int length);
/* Searches the supplied buffer for a SSN in the stripped xxxyyzzzz format.
* Params:
* buffer => buffer to search
* length => length of the buffer
* Returns:
* 1 on detect, 0 on fail
*/
int dlp_has_stripped_ssn(const unsigned char *buffer, int length);
/* Searches the supplied buffer for a SSN in the normal xxx-yy-zzzz format.
* Params:
* buffer => buffer to search
* length => length of the buffer
* Returns:
* 1 on detect, 0 on fail
*/
int dlp_has_normal_ssn(const unsigned char *buffer, int length);
#endif /* __DLP_H_ */

@ -101,6 +101,7 @@ typedef struct {
#define DETECT_ENCRYPTED (ctx->options & CL_SCAN_BLOCKENCRYPTED)
/* #define BLOCKMAX (ctx->options & CL_SCAN_BLOCKMAX) */
#define DETECT_BROKEN (ctx->options & CL_SCAN_BLOCKBROKEN)
#define SCAN_STRUCTURED (ctx->options & CL_SCAN_STRUCTURED)
/* based on macros from A. Melnikoff */
#define cbswap16(v) (((v & 0xff) << 8) | (((v) >> 8) & 0xff))

@ -89,6 +89,7 @@
#include "textnorm.h"
#include <zlib.h>
#include "unzip.h"
#include "dlp.h"
#ifdef HAVE_BZLIB_H
#include <bzlib.h>
@ -1491,6 +1492,76 @@ static int cli_scanmail(int desc, cli_ctx *ctx)
return ret;
}
static int cli_scan_structured(int desc, cli_ctx *ctx)
{
char buf[8192];
int result = 0;
unsigned int cc_count = 0;
unsigned int ssn_count = 0;
int done = 0;
const struct cl_limits *lim = NULL;
int (*ccfunc)(const unsigned char *buffer, int length);
int (*ssnfunc)(const unsigned char *buffer, int length);
if(ctx == NULL || ctx->limits == NULL)
return CL_ENULLARG;
lim = ctx->limits;
if(lim->min_cc_count == 1)
ccfunc = dlp_has_cc;
else
ccfunc = dlp_get_cc_count;
ssnfunc = dlp_get_ssn_count;;
switch(lim->structured_flags) {
case CL_STRUCTURED_CONF_SSN_BOTH:
if(lim->min_ssn_count == 1)
ssnfunc = dlp_has_ssn;
else
ssnfunc = dlp_get_ssn_count;
break;
case CL_STRUCTURED_CONF_SSN_NORMAL:
if(lim->min_ssn_count == 1)
ssnfunc = dlp_has_normal_ssn;
else
ssnfunc = dlp_get_normal_ssn_count;
break;
case CL_STRUCTURED_CONF_SSN_STRIPPED:
if(lim->min_ssn_count == 1)
ssnfunc = dlp_has_stripped_ssn;
else
ssnfunc = dlp_get_stripped_ssn_count;
break;
}
while(((result = cli_readn(desc, buf, 8191)) > 0) && !done) {
if((cc_count += ccfunc((const unsigned char *)buf, result)) >= lim->min_cc_count)
done = 1;
if((ssn_count += ssnfunc((const unsigned char *)buf, result)) >= lim->min_ssn_count)
done = 1;
}
if(cc_count != 0 && cc_count >= lim->min_cc_count) {
cli_dbgmsg("cli_scan_structured: %u credit card numbers detected\n", cc_count);
*ctx->virname = "Structured.CreditCardNumber";
return CL_VIRUS;
}
if(ssn_count != 0 && ssn_count > lim->min_ssn_count) {
cli_dbgmsg("cli_scan_structured: %u social security numbers detected\n", ssn_count);
*ctx->virname = "Structured.SSN";
return CL_VIRUS;
}
return CL_CLEAN;
}
static int cli_scanembpe(int desc, cli_ctx *ctx)
{
int fd, bytes, ret = CL_CLEAN;
@ -1918,12 +1989,22 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
ret = cli_check_mydoom_log(desc, ctx->virname);
break;
case CL_TYPE_TEXT_ASCII:
if(SCAN_STRUCTURED)
/* TODO: consider calling this from cli_scanscript() for
* a normalised text
*/
ret = cli_scan_structured(desc, ctx);
break;
default:
break;
}
ctx->recursion--;
if(ret == CL_VIRUS)
return CL_VIRUS;
if(type == CL_TYPE_ZIP && SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_ZIP)) {
if(sb.st_size > 1048576) {
cli_dbgmsg("cli_magic_scandesc: Not checking for embedded PEs (zip file > 1 MB)\n");
@ -1932,7 +2013,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
}
/* CL_TYPE_HTML: raw HTML files are not scanned, unless safety measure activated via DCONF */
if(type != CL_TYPE_IGNORED && (type != CL_TYPE_HTML || !(DCONF_DOC & DOC_CONF_HTML_SKIPRAW)) && ret != CL_VIRUS && !ctx->engine->sdb) {
if(type != CL_TYPE_IGNORED && (type != CL_TYPE_HTML || !(DCONF_DOC & DOC_CONF_HTML_SKIPRAW)) && !ctx->engine->sdb) {
if(cli_scanraw(desc, ctx, type, typercg, &dettype) == CL_VIRUS)
return CL_VIRUS;
}

Loading…
Cancel
Save