bump version
[prads.git] / src / output-plugins / log_file.c
blobac1dcc961ddbb937ab876c7cccba6292c280a4b6
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 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 /* ip,vlan,port,proto,(ASSET DETECTION),FP/MAC,distance,uptime,timstamp */
25 #include "log_file.h"
27 log_file_conf output_log_file_conf;
29 /* ----------------------------------------------------------
30 * FUNCTION : init_output_log_file
31 * DESC : This function initialize the output file.
32 * : If the file already exists, it will read in the
33 * : file and add each asset to the asset data structure.
34 * INPUT : 0 - CSV filename
35 * RETURN : None!
36 * --------------------------------------------------------- */
37 int init_output_log_file (bstring filename)
39 FILE *fp;
40 char *mode = "r";
41 int retry = 0;
43 /* Make sure filename isn't NULL. */
44 if (filename != NULL)
45 output_log_file_conf.filename = bstrcpy(filename);
46 else
47 output_log_file_conf.filename = bfromcstr(PRADS_ASSETLOG);
49 /* Check to see if *filename exists. */
50 reopen:
51 if ((fp = fopen(bdata(output_log_file_conf.filename), mode)) == NULL) {
52 int e = errno;
53 switch(e) {
54 case EISDIR:
55 case EFAULT:
56 case EACCES:
57 /* retry in current working directory */
58 if(retry){
59 elog("%s denied opening access log '%s'", strerror(e), bdata(output_log_file_conf.filename));
60 return e;
62 bdestroy(output_log_file_conf.filename);
63 output_log_file_conf.filename = bfromcstr(PRADS_ASSETLOG);
64 retry++;
65 goto reopen;
66 case ENOENT:
67 mode = MODE_WRITE;
68 goto reopen;
69 default:
70 elog("Cannot open file %s: %s!", bdata(output_log_file_conf.filename), strerror(errno));
71 return e;
74 } else {
75 fp = output_log_file_conf.file = fp;
77 if (mode == MODE_WRITE){
78 /* File did not exist, create new.. */
79 fprintf(output_log_file_conf.file, "asset,vlan,port,proto,service,[service-info],distance,discovered\n");
81 /* File does exist, read it into data structure. */
82 fclose(fp);
83 // read_report_file();
85 /* Open file and assign it to the global FILE pointer. */
86 if ((output_log_file_conf.file = fopen(bdata(output_log_file_conf.filename), "a")) == NULL) {
87 printf("Cannot open log file %s for append!\n", bdata(output_log_file_conf.filename));
91 return 0;
94 /* ----------------------------------------------------------
95 * FUNCTION : read_report_file
96 * DESC : This function will read in a specified
97 * : report CSV file. It will then break a part
98 * : the line and add the assets to the
99 * : specified asset data structure.
100 * INPUT : None
101 * RETURN : None
102 * ---------------------------------------------------------- */
103 void
104 read_report_file (void)
106 FILE *fp;
107 bstring filedata;
108 struct bstrList *lines;
109 int i;
111 printf("[*] Processing Assets from persistent file %s\n", bdata(output_log_file_conf.filename));
113 /* Open Signature File */
114 if ((fp = fopen(bdata(output_log_file_conf.filename), "r")) == NULL) {
115 printf("Unable to open CSV file - %s", bdata(output_log_file_conf.filename));
118 /* Read file into 'filedata' and process it accordingly. */
119 filedata = bread ((bNread) fread, fp);
120 if ((lines = bsplit(filedata, '\n')) != NULL) {
121 for (i = 0; i < lines->qty; i++) {
122 parse_raw_report(lines->entry[i]);
126 /* Clean Up */
127 bdestroy(filedata);
128 bstrListDestroy(lines);
129 fclose(fp);
132 /* ----------------------------------------------------------
133 * FUNCTION : parse_raw_report
134 * DESC : This function will parse through a single
135 * : line of the CSV file.
136 * INPUT : 0 - Raw Line
137 * RETURN : 0 - Sucess
138 * :-1 - Error
139 * ---------------------------------------------------------- */
140 int parse_raw_report (bstring line)
142 struct bstrList *list;
143 int ret = 0;
145 /* Temporary Storage */
146 struct in_addr ip_addr;
147 //char mac_addr[MAC_ADDR_LEN];
148 int port;
149 int proto;
150 bstring service;
151 bstring application;
152 time_t discovered;
154 /* Check to see if this line has something to read. */
155 if (line->data[0] == '\0' || line->data[0] == '#')
156 return 0;
158 /* Break line apart. */
159 if ((list = bsplit(line, ',')) == NULL)
160 return -1;
162 /* Check to see if this line contains the header. */
163 if ((biseqcstr(list->entry[0], "asset")) == 1) {
164 if (list != NULL)
165 bstrListDestroy(list);
166 return -1;
169 /* Place data from 'list' into temporary data storage. */
170 if ((inet_aton(bdata(list->entry[0]), &ip_addr)) == -1)
171 ret = -1;
173 if ((port = htons(atoi(bdata(list->entry[1])))) == -1)
174 ret = -1;
176 if ((proto = atoi(bdata(list->entry[2]))) == -1)
177 ret = -1;
179 if ((service = bstrcpy(list->entry[3])) == NULL)
180 ret = -1;
182 if ((application = bstrcpy(list->entry[4])) == NULL)
183 ret = -1;
185 if ((discovered = atol(bdata(list->entry[5]))) == -1)
186 ret = -1;
188 /* Make sure that this line contains 'good' data. */
189 if (service->slen == 0 || application->slen == 0 || discovered <= 0)
190 ret = -1;
192 /* Add Asset to Data Structure */
193 if (proto == 0 && ret != -1) {
194 /* ARP */
195 //mac2hex(bdata(application), mac_addr, MAC_ADDR_LEN);
196 //add_arp_asset(ip_addr, mac_addr, discovered);
197 } else {
198 /* Everything Else */
199 //add_asset(ip_addr, port, proto, service, application, discovered);
202 // Clean Up
203 if (list != NULL)
204 bstrListDestroy(list);
205 if (service != NULL)
206 bdestroy(service);
207 if (application != NULL)
208 bdestroy(application);
210 return ret;
213 /* ----------------------------------------------------------
214 * FUNCTION : file_arp
215 * DESC : This function prints an ARP asset to the log file
216 * INPUT : 0 - Main asset
217 * RETURN : VOID
218 * ---------------------------------------------------------- */
219 void file_arp (asset *main)
221 /* ip,vlan,port,proto,ARP (mac-resolved),mac-address,timstamp*/
222 static char ip_addr_s[INET6_ADDRSTRLEN];
223 if (output_log_file_conf.file == NULL) {
224 elog("[!] ERROR: File handle not open!\n");
225 return;
227 u_ntop(main->ip_addr, main->af, ip_addr_s);
228 if (main->mac_resolved != NULL) {
229 /* ip,0,0,ARP (mac-resolved),mac-address,timstamp */
230 fprintf(output_log_file_conf.file, "%s,%u,0,0,ARP (%s),%s,0,%lu\n", ip_addr_s,
231 main->vlan ? ntohs(main->vlan) : 0,bdata(main->mac_resolved),
232 hex2mac((const char *)main->mac_addr), main->last_seen);
233 } else {
234 /* ip,0,0,ARP,mac-address,timstamp */
235 fprintf(output_log_file_conf.file, "%s,%u,0,0,ARP,[%s],0,%lu\n", ip_addr_s,
236 main->vlan ? ntohs(main->vlan) : 0,hex2mac((const char *)main->mac_addr), main->last_seen);
238 fflush(output_log_file_conf.file);
241 /* ----------------------------------------------------------
242 * FUNCTION : file_service
243 * DESC : Prints a service asset to the log file.
244 * INPUT : 0 - Main asset
245 * : 1 - Serice asset
246 * ---------------------------------------------------------- */
247 void
248 file_service (asset *main, serv_asset *service)
250 if (output_log_file_conf.file != NULL) {
251 uint8_t tmp_ttl;
252 static char ip_addr_s[INET6_ADDRSTRLEN];
253 u_ntop(main->ip_addr, main->af, ip_addr_s);
254 /* ip,vlan,port,proto,SERVICE,application,timstamp*/
255 fprintf(output_log_file_conf.file, "%s,%u,%d,%d,",
256 ip_addr_s, main->vlan ? ntohs(main->vlan) : 0,
257 ntohs(service->port),service->proto);
258 if (service->role == 1) {
259 fprintf(output_log_file_conf.file, "SERVER,[%s:%s]",
260 (char*)bdata(service->service),
261 (char *)bdata(service->application));
262 } else {
263 fprintf(output_log_file_conf.file, "CLIENT,[%s:%s]",
264 (char*)bdata(service->service),
265 (char*)bdata(service->application));
268 tmp_ttl = normalize_ttl(service->ttl);
269 fprintf(output_log_file_conf.file, ",%d,%lu\n",tmp_ttl - service->ttl,service->last_seen);
270 fflush(output_log_file_conf.file);
271 } else {
272 elog("[!] ERROR: File handle not open!\n");
276 /* ----------------------------------------------------------
277 * FUNCTION : file_os
278 * DESC : Prints a os asset to the log file.
279 * INPUT : 0 - Main asset
280 * : 1 - OS asset
281 * RETURN : VOID
282 * ---------------------------------------------------------- */
283 void
284 file_os (asset *main, os_asset *os)
286 static char ip_addr_s[INET6_ADDRSTRLEN];
287 uint8_t tmp_ttl;
289 if (output_log_file_conf.file == NULL) {
290 elog("[!] ERROR: File handle not open!\n");
292 return;
295 u_ntop(main->ip_addr, main->af, ip_addr_s);
297 /* ip,vlan,port,proto,OS-FP,FP,timstamp*/
298 fprintf(output_log_file_conf.file, "%s,%u,%d,", ip_addr_s,
299 main->vlan ? ntohs(main->vlan) : 0, os->port);
300 //ntohs(main->port),service->proto);
302 switch (os->detection) {
303 case CO_SYN:
304 fprintf(output_log_file_conf.file, "6,SYN");
305 break;
306 case CO_SYNACK:
307 fprintf(output_log_file_conf.file, "6,SYNACK");
308 break;
309 case CO_ACK:
310 fprintf(output_log_file_conf.file, "6,ACK");
311 break;
312 case CO_RST:
313 fprintf(output_log_file_conf.file, "6,RST");
314 break;
315 case CO_FIN:
316 fprintf(output_log_file_conf.file, "6,FIN");
317 break;
318 case CO_UDP:
319 fprintf(output_log_file_conf.file, "17,UDP");
320 break;
321 case CO_ICMP:
322 // 58 is ICMPv6
323 fprintf(output_log_file_conf.file, "1,ICMP");
324 break;
326 default:
327 fprintf(stderr,
328 "[!] error in detection type %d (isn't implemented!)\n", os->detection);
331 if (os->raw_fp != NULL) {
332 fprintf(output_log_file_conf.file, ",[%s:", (char *)bdata(os->raw_fp));
333 } else {
334 //bstring b = gen_fp_tcp(&os->fp, os->fp.zero_stamp, 0);
335 bstring b = gen_fp_tcp(&os->fp, os->uptime, 0);
336 os->raw_fp = b;
337 fprintf(output_log_file_conf.file, ",[%s:", (char *)bdata(os->raw_fp));
339 if (os->fp.os != NULL) fprintf(output_log_file_conf.file,"%s", os->fp.os);
340 else fprintf(output_log_file_conf.file, "unknown");
341 if (os->fp.desc != NULL) fprintf(output_log_file_conf.file, ":%s", os->fp.desc);
342 else fprintf(output_log_file_conf.file, ":unknown");
344 if (os->fp.mss) fprintf(output_log_file_conf.file, ":link:%s",lookup_link(os->fp.mss,1));
345 if (os->uptime) fprintf(output_log_file_conf.file, ":uptime:%dhrs",os->uptime/360000);
347 tmp_ttl = normalize_ttl(os->ttl);
348 fprintf(output_log_file_conf.file, "],%d,%lu\n",tmp_ttl - os->ttl, os->last_seen);
349 fflush(output_log_file_conf.file);
352 /* ----------------------------------------------------------
353 * FUNCTION : end_output_log_file
354 * DESC : This function will free the memory declared
355 * : for the log_file output.
356 * INPUT : None!
357 * OUTPUT : None!
358 * ---------------------------------------------------------- */
359 int end_output_log_file ()
361 printf("\n[*] Closing log file.");
363 if (output_log_file_conf.file != NULL)
364 fclose(output_log_file_conf.file);
366 if (output_log_file_conf.filename != NULL)
367 bdestroy(output_log_file_conf.filename);
369 return 0;