Nmap Development mailing list archives

[PATCH] Logging (filename) extensions


From: Kris Katterjohn <katterjohn () gmail com>
Date: Mon, 17 Sep 2007 20:20:40 -0500

Hey everyone!

I've been using the logging options (-oA, -oX, etc.) a lot lately, and I tend to like dates and times in the filename.

I thought it'd be cool to implement an extension to the logging options by allowing some strftime()-like conversions for the passed filenames.

I think it would come in handy for people who do automated scans, and also like dates/times in the filename.


The following are the same as for strftime():

%H - Hour (0-23)
%M - Minute (0-59)
%S - Second (0-60)
%m - Month (1-12)
%d - Day (1-31)
%y - Year (e.g. 07)
%Y - Year (e.g. 2007)
%% - "%"
%T - Same as "%H:%M:%S"


These are different than strftime():

%D - In strftime it's like "%m/%d/%y", here it's like "%m%d%y"
%t - In strftime it's like a <TAB>, here it's like "%H%M%S"


And if it's not a conversion character, then it'll just be that character (e.g. %w is just w).


Examples:

-oN 'myscan-%T-%D.nmap'

gives:

myscan-19:33:13-091707.nmap

-----

-oN 'myscan-%t-%m%d.nmap'

gives:

myscan-193320-0917.nmap

-----

-oX 'myscan-%H:%M-%m%d%Y.xml'

gives:

myscan-19:34-09172007.xml

-----

-oG 'myscan-100%%.gnmap'

gives:

myscan-100%.gnmap


Please give it a try and let me know what you think!

Thanks,
Kris Katterjohn
Index: nmap.cc
===================================================================
--- nmap.cc     (revision 5849)
+++ nmap.cc     (working copy)
@@ -473,6 +473,8 @@
   int num_host_exp_groups;
   char *machinefilename = NULL, *kiddiefilename = NULL, 
     *normalfilename = NULL, *xmlfilename = NULL;
+  time_t now;
+  struct tm *tm;
   HostGroupState *hstate = NULL;
   char *endptr = NULL;
   struct scan_lists *ports = NULL;
@@ -649,6 +651,9 @@
   win_pre_init();
 #endif
 
+  now = time(NULL);
+  tm = localtime(&now);
+
   /* OK, lets parse these args! */
   optind = 1; /* so it can be called multiple times */
   while((arg = getopt_long_only(argc,fakeargv,"6Ab:D:d::e:Ffg:hIi:M:m:nO::o:P:p:qRrS:s:T:Vv", long_options, 
&option_index)) != EOF) {
@@ -818,23 +823,23 @@
       } else if (strcmp(long_options[option_index].name, "webxml") == 0) {
        o.setXSLStyleSheet("http://www.insecure.org/nmap/data/nmap.xsl";);
       } else if (strcmp(long_options[option_index].name, "oN") == 0) {
-       normalfilename = optarg;
+       normalfilename = logfilename(optarg, tm);
       } else if (strcmp(long_options[option_index].name, "oG") == 0 ||
                 strcmp(long_options[option_index].name, "oM") == 0) {
-       machinefilename = optarg;
+       machinefilename = logfilename(optarg, tm);
       } else if (strcmp(long_options[option_index].name, "oS") == 0) {
-       kiddiefilename = optarg;
+       kiddiefilename = logfilename(optarg, tm);
       } else if (strcmp(long_options[option_index].name, "oH") == 0) {
        fatal("HTML output is not directly supported, though Nmap includes an XSL for transforming XML output into 
HTML.  See the man page.");
       } else if (strcmp(long_options[option_index].name, "oX") == 0) {
-       xmlfilename = optarg;
+       xmlfilename = logfilename(optarg, tm);
       } else if (strcmp(long_options[option_index].name, "oA") == 0) {
        char buf[MAXPATHLEN];
-       Snprintf(buf, sizeof(buf), "%s.nmap", optarg);
+       Snprintf(buf, sizeof(buf), "%s.nmap", logfilename(optarg, tm));
        normalfilename = strdup(buf);
-       Snprintf(buf, sizeof(buf), "%s.gnmap", optarg);
+       Snprintf(buf, sizeof(buf), "%s.gnmap", logfilename(optarg, tm));
        machinefilename = strdup(buf);
-       Snprintf(buf, sizeof(buf), "%s.xml", optarg);
+       Snprintf(buf, sizeof(buf), "%s.xml", logfilename(optarg, tm));
        xmlfilename = strdup(buf);
       } else if (strcmp(long_options[option_index].name, "thc") == 0) {
        printf("!!Greets to Van Hauser, Plasmoid, Skyper and the rest of THC!!\n");
@@ -1013,7 +1018,7 @@
       }
       break;
     case 'o':
-      normalfilename = optarg;
+      normalfilename = logfilename(optarg, tm);
       break;
     case 'P': 
       if (*optarg == '\0' || *optarg == 'I' || *optarg == 'E')
@@ -1242,10 +1247,6 @@
 
   if (!o.interactivemode) {
     char tbuf[128];
-    struct tm *tm;
-    time_t now = time(NULL);
-    if (!(tm = localtime(&now))) 
-      fatal("Unable to get current localtime()#!#");
     // ISO 8601 date/time -- http://www.cl.cam.ac.uk/~mgk25/iso-time.html 
     if (strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M %Z", tm) <= 0)
       fatal("Unable to properly format time");
Index: output.h
===================================================================
--- output.h    (revision 5849)
+++ output.h    (working copy)
@@ -138,6 +138,8 @@
    in a certain place to conform to DTD. */
 void printmacinfo(Target *currenths);
 
+char *logfilename(const char *str, struct tm *tm);
+
 /* Write some information (printf style args) to the given log stream(s).
    Remember to watch out for format string bugs. */
 void log_write(int logt, const char *fmt, ...)
Index: output.cc
===================================================================
--- output.cc   (revision 5849)
+++ output.cc   (working copy)
@@ -830,6 +830,83 @@
   return temp;
 }
 
+char *logfilename(const char *str, struct tm *tm)
+{
+       char *a, *ret, *end, *p;
+       char tbuf[10];
+       int retlen = strlen(str) * 8 + 1;
+
+       ret = (char *) safe_malloc(retlen);
+       end = ret + retlen;
+
+       for (p = ret; *str; str++) {
+               if (*str == '%') {
+                       if (!*(str + 1)) {
+                               break;
+                       }
+
+                       str++;
+
+                       switch (*str) {
+                       case 'H':
+                               strftime(tbuf, sizeof tbuf, "%H", tm);
+                               a = strdup(tbuf);
+                               break;
+                       case 'M':
+                               strftime(tbuf, sizeof tbuf, "%M", tm);
+                               a = strdup(tbuf);
+                               break;
+                       case 'S':
+                               strftime(tbuf, sizeof tbuf, "%S", tm);
+                               a = strdup(tbuf);
+                               break;
+                       case 'T':
+                               strftime(tbuf, sizeof tbuf, "%T", tm);
+                               a = strdup(tbuf);
+                               break;
+                       case 't':
+                               strftime(tbuf, sizeof tbuf, "%H%M%S", tm);
+                               a = strdup(tbuf);
+                               break;
+                       case 'm':
+                               strftime(tbuf, sizeof tbuf, "%m", tm);
+                               a = strdup(tbuf);
+                               break;
+                       case 'd': 
+                               strftime(tbuf, sizeof tbuf, "%d", tm);
+                               a = strdup(tbuf);
+                               break;
+                       case 'y': 
+                               strftime(tbuf, sizeof tbuf, "%y", tm);
+                               a = strdup(tbuf);
+                               break;
+                       case 'Y': 
+                               strftime(tbuf, sizeof tbuf, "%Y", tm);
+                               a = strdup(tbuf);
+                               break;
+                       case 'D': 
+                               strftime(tbuf, sizeof tbuf, "%m%d%y", tm);
+                               a = strdup(tbuf);
+                               break;
+                       default:
+                               *p++ = *str;
+                               continue;
+                       }
+
+                       assert(end - p > 1);
+                       Strncpy(p, a, end - p - 1);
+                       p += strlen(a);
+                       free(a);
+               } else {
+                       *p++ = *str;
+               }
+       }
+
+       *p = 0;
+
+       return (char *) safe_realloc(ret, strlen(ret) + 1);
+}
+
 /* This is the workhorse of the logging functions.  Usually it is
    called through log_write(), but it can be called directly if you
    are dealing with a vfprintf-style va_list.  Unlike log_write, YOU

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org

Current thread: