Merge pull request #56 from wuruilong01/master
[prads.git] / src / output-plugins / log_file.c
blobbeb4cd2a76e5444f7d6ec91eb46789d3dc379a76
1 /*
2 ** This file is a part of PRADS.
3 **
4 ** Copyright (C) 2009, Redpill Linpro
5 ** Copyright (C) 2009, Edward Fjellskål <edward.fjellskaal@redpill-linpro.com>
6 ** Copyright (C) 2011, Kacper Wysocki <kacper.wysocki@redpill-linpro.com>
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 2 of the License, or
11 ** (at your option) any later version.
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; if not, write to the Free Software
20 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 /* ip,vlan,port,proto,(ASSET DETECTION),FP/MAC,distance,uptime,timstamp */
27 /* I N C L U D E S *********************************************************/
28 #include "../prads.h"
29 #include "../config.h"
30 #include "../sys_func.h"
31 #include "../sig.h"
33 #include <stdio.h>
35 #include "log.h"
36 #include "log_file.h"
38 output_plugin p_file = {
39 .init = &init_output_log_file,
40 .arp = &file_arp,
41 .os = &file_os,
42 .service = &file_service,
43 .denit = &end_output_log_file,
46 output_plugin *init_log_file ()
48 return &p_file;
51 /* ----------------------------------------------------------
52 * FUNCTION : init_output_log_file
53 * DESC : This function initialize the output file.
54 * : If the file already exists, it will read in the
55 * : file and add each asset to the asset data structure.
56 * INPUT : 0 - CSV filename
57 * RETURN : None!
58 * --------------------------------------------------------- */
59 int init_output_log_file (output_plugin *log, const char *file, int flags)
61 FILE *fp;
62 const char *mode = MODE_READ;
63 int retry = 0;
64 /* Make sure filename isn't NULL. */
65 if (!file)
66 return -1;
68 log->path = file;
69 log->flags = flags;
71 /* Check to see if *filename exists. */
72 reopen:
73 if ((fp = fopen(log->path, mode)) == NULL) {
74 int e = errno;
75 switch(e) {
76 case EISDIR:
77 case EFAULT:
78 case EACCES:
79 /* retry in current working directory */
80 if(retry){
81 if(flags & CONFIG_VERBOSE )
82 elog("%s denied opening asset log '%s'", strerror(e), log->path);
83 return e;
85 log->path = PRADS_ASSETLOG;
86 retry++;
87 goto reopen;
88 case ENOENT:
89 mode = MODE_WRITE;
90 goto reopen;
91 default:
92 if(flags & CONFIG_VERBOSE)
93 elog("Cannot open file %s: %s!", log->path, strerror(errno));
94 return e;
97 } else {
98 log->data = (void *) fp;
100 if (*mode == 'w'){
101 /* File did not exist, create new.. */
102 fprintf(fp, "asset,vlan,port,proto,service,[service-info],distance,discovered\n");
104 /* File does exist, read it into data structure. */
105 fclose(fp);
106 // read_report_file();
108 /* Open file and assign it to the global FILE pointer. */
109 if ((log->data = (void *) fopen(log->path, "a")) == NULL) {
110 int e = errno;
111 if(flags & CONFIG_VERBOSE)
112 printf("Cannot open log file %s for append!\n", log->path);
113 return e;
117 return 0;
120 /* ----------------------------------------------------------
121 * FUNCTION : read_report_file
122 * DESC : This function will read in a specified
123 * : report CSV file. It will then break a part
124 * : the line and add the assets to the
125 * : specified asset data structure.
126 * INPUT : None
127 * RETURN : None
128 * ---------------------------------------------------------- */
129 void
130 read_report_file (output_plugin *log)
132 FILE *fp;
133 bstring filedata;
134 struct bstrList *lines;
135 int i;
137 printf("[*] Processing Assets from persistent file %s\n", log->path);
139 /* Open Signature File */
140 if ((fp = fopen(log->path, "r")) == NULL) {
141 printf("Unable to open CSV file - %s", log->path);
144 /* Read file into 'filedata' and process it accordingly. */
145 filedata = bread ((bNread) fread, fp);
146 if ((lines = bsplit(filedata, '\n')) != NULL) {
147 for (i = 0; i < lines->qty; i++) {
148 parse_raw_report(lines->entry[i]);
152 /* Clean Up */
153 bdestroy(filedata);
154 bstrListDestroy(lines);
155 fclose(fp);
158 /* ----------------------------------------------------------
159 * FUNCTION : parse_raw_report
160 * DESC : This function will parse through a single
161 * : line of the CSV file.
162 * INPUT : 0 - Raw Line
163 * RETURN : 0 - Sucess
164 * :-1 - Error
165 * ---------------------------------------------------------- */
166 int parse_raw_report (bstring line)
168 struct bstrList *list;
169 int ret = 0;
171 /* Temporary Storage */
172 struct in_addr ip_addr;
173 //char mac_addr[MAC_ADDR_LEN];
174 int port;
175 int proto;
176 bstring service;
177 bstring application;
178 time_t discovered;
180 /* Check to see if this line has something to read. */
181 if (line->data[0] == '\0' || line->data[0] == '#')
182 return 0;
184 /* Break line apart. */
185 if ((list = bsplit(line, ',')) == NULL)
186 return -1;
188 /* Check to see if this line contains the header. */
189 if ((biseqcstr(list->entry[0], "asset")) == 1) {
190 if (list != NULL)
191 bstrListDestroy(list);
192 return -1;
195 /* Place data from 'list' into temporary data storage. */
196 if ((inet_aton(bdata(list->entry[0]), &ip_addr)) == -1)
197 ret = -1;
199 if ((port = htons(atoi(bdata(list->entry[1])))) == -1)
200 ret = -1;
202 if ((proto = atoi(bdata(list->entry[2]))) == -1)
203 ret = -1;
205 if ((service = bstrcpy(list->entry[3])) == NULL)
206 ret = -1;
208 if ((application = bstrcpy(list->entry[4])) == NULL)
209 ret = -1;
211 if ((discovered = atol(bdata(list->entry[5]))) == -1)
212 ret = -1;
214 /* Make sure that this line contains 'good' data. */
215 if (service->slen == 0 || application->slen == 0 || discovered <= 0)
216 ret = -1;
218 /* Add Asset to Data Structure */
219 if (proto == 0 && ret != -1) {
220 /* ARP */
221 //mac2hex(bdata(application), mac_addr, MAC_ADDR_LEN);
222 //add_arp_asset(ip_addr, mac_addr, discovered);
223 } else {
224 /* Everything Else */
225 //add_asset(ip_addr, port, proto, service, application, discovered);
228 // Clean Up
229 if (list != NULL)
230 bstrListDestroy(list);
231 if (service != NULL)
232 bdestroy(service);
233 if (application != NULL)
234 bdestroy(application);
236 return ret;
239 /* ----------------------------------------------------------
240 * FUNCTION : file_arp
241 * DESC : This function prints an ARP asset to the log file
242 * INPUT : 0 - Main asset
243 * RETURN : VOID
244 * ---------------------------------------------------------- */
245 void file_arp (output_plugin *log, asset *main)
247 /* ip,vlan,port,proto,ARP (mac-resolved),mac-address,timstamp*/
248 static char ip_addr_s[INET6_ADDRSTRLEN];
249 if ((FILE*)log->data == NULL) {
250 if(log->flags & CONFIG_VERBOSE )
251 elog("[!] ERROR: File handle not open!\n");
252 return;
254 u_ntop(main->ip_addr, main->af, ip_addr_s);
255 if (main->macentry != NULL) {
256 /* ip,0,0,ARP (mac-resolved),mac-address,timstamp */
257 /* XXX: vendor info breaks csv niceness */
258 fprintf((FILE*)log->data, "%s,%u,0,0,ARP,[%s,(%s)],0,%lu\n", ip_addr_s,
259 main->vlan ? ntohs(main->vlan) : 0, hex2mac(main->mac_addr),
260 main->macentry->vendor, main->last_seen);
261 } else {
262 /* ip,0,0,ARP,mac-address,timstamp */
263 fprintf((FILE*)log->data, "%s,%u,0,0,ARP,[%s],0,%lu\n", ip_addr_s,
264 main->vlan ? ntohs(main->vlan) : 0,hex2mac(main->mac_addr), main->last_seen);
266 fflush((FILE*)log->data);
269 /* ----------------------------------------------------------
270 * FUNCTION : file_service
271 * DESC : Prints a service asset to the log file.
272 * INPUT : 0 - Main asset
273 * : 1 - Serice asset
274 * ---------------------------------------------------------- */
275 void
276 file_service (output_plugin* log,asset *main, serv_asset *service, connection *cxt)
278 if ((FILE*)log->data != NULL) {
279 uint8_t tmp_ttl;
280 static char ip_addr_s[INET6_ADDRSTRLEN];
281 u_ntop(main->ip_addr, main->af, ip_addr_s);
282 /* ip,vlan,port,proto,SERVICE,application,timstamp*/
283 fprintf((FILE*)log->data, "%s,%u,%d,%d,",
284 ip_addr_s, main->vlan ? ntohs(main->vlan) : 0,
285 ntohs(service->port),service->proto);
286 if (service->role == SC_SERVER) {
287 fprintf((FILE*)log->data, "SERVER,[%s:%s]",
288 (char*)bdata(service->service),
289 (char *)bdata(service->application));
290 } else {
291 fprintf((FILE*)log->data, "CLIENT,[%s:%s]",
292 (char*)bdata(service->service),
293 (char*)bdata(service->application));
296 tmp_ttl = normalize_ttl(service->ttl);
297 fprintf((FILE*)log->data, ",%d,%lu\n",tmp_ttl - service->ttl,service->last_seen);
298 fflush((FILE*)log->data);
299 } else {
300 if(log->flags & CONFIG_VERBOSE )
301 elog("[!] ERROR: File handle not open!\n");
305 /* ----------------------------------------------------------
306 * FUNCTION : file_os
307 * DESC : Prints a os asset to the log file.
308 * INPUT : 0 - Main asset
309 * : 1 - OS asset
310 * RETURN : VOID
311 * ---------------------------------------------------------- */
312 void
313 file_os (output_plugin *log, asset *main, os_asset *os, connection *cxt)
315 static char ip_addr_s[INET6_ADDRSTRLEN];
316 uint8_t tmp_ttl;
318 if (!log) {
319 return; // nah..
321 if(log->data == NULL){
322 if(log->flags & CONFIG_VERBOSE)
323 elog("[!] ERROR: File handle not open: %s!\n", log->path);
324 return;
327 u_ntop(main->ip_addr, main->af, ip_addr_s);
329 /* ip,vlan,port,proto,OS-FP,FP,timstamp*/
330 fprintf((FILE*)log->data, "%s,%u,%d,", ip_addr_s,
331 main->vlan ? ntohs(main->vlan) : 0, os->port);
332 //ntohs(main->port),service->proto);
334 switch (os->detection) {
335 case CO_SYN:
336 fprintf((FILE*)log->data, "6,SYN");
337 break;
338 case CO_SYNACK:
339 fprintf((FILE*)log->data, "6,SYNACK");
340 break;
341 case CO_ACK:
342 fprintf((FILE*)log->data, "6,ACK");
343 break;
344 case CO_RST:
345 fprintf((FILE*)log->data, "6,RST");
346 break;
347 case CO_FIN:
348 fprintf((FILE*)log->data, "6,FIN");
349 break;
350 case CO_UDP:
351 fprintf((FILE*)log->data, "17,UDP");
352 break;
353 case CO_ICMP:
354 // 58 is ICMPv6
355 fprintf((FILE*)log->data, "1,ICMP");
356 break;
357 case CO_DHCP:
358 fprintf((FILE*)log->data, "17,DHCP");
360 default:
361 fprintf(stderr,
362 "[!] error in detection type %d (isn't implemented!)\n", os->detection);
365 if (os->raw_fp != NULL) {
366 fprintf((FILE*)log->data, ",[%s:", (char *)bdata(os->raw_fp));
367 } else {
368 //bstring b = gen_fp_tcp(&os->fp, os->fp.zero_stamp, 0);
369 bstring b = gen_fp_tcp(&os->fp, os->uptime, 0);
370 os->raw_fp = b;
371 fprintf((FILE*)log->data, ",[%s:", (char *)bdata(os->raw_fp));
373 if (os->fp.os != NULL) fprintf((FILE*)log->data,"%s", os->fp.os);
374 else fprintf((FILE*)log->data, "unknown");
375 if (os->fp.desc != NULL) fprintf((FILE*)log->data, ":%s", os->fp.desc);
376 else fprintf((FILE*)log->data, ":unknown");
378 if (os->fp.mss) fprintf((FILE*)log->data, ":link:%s",lookup_link(os->fp.mss,1));
379 if (os->uptime) fprintf((FILE*)log->data, ":uptime:%dhrs",os->uptime/360000);
381 tmp_ttl = normalize_ttl(os->ttl);
382 fprintf((FILE*)log->data, "],%d,%lu\n",tmp_ttl - os->ttl, os->last_seen);
383 fflush((FILE*)log->data);
386 /* ----------------------------------------------------------
387 * FUNCTION : end_output_log_file
388 * DESC : This function will free the memory declared
389 * : for the log_file output.
390 * INPUT : output plugin
391 * OUTPUT : None!
392 * ---------------------------------------------------------- */
393 int end_output_log_file (output_plugin* log)
395 dlog("[*] Closing asset log.\n");
397 if (log->data != NULL)
398 fclose((FILE*)log->data);
399 return 0;