5 #include "output-plugins/log.h"
9 extern globalconfig config
;
10 static asset
*passet
[BUCKET_SIZE
];
12 void update_asset(packetinfo
*pi
)
14 if (asset_lookup(pi
) == SUCCESS
) {
15 if (pi
->asset
!= NULL
) {
16 pi
->asset
->vlan
= pi
->vlan
;
17 pi
->asset
->last_seen
= pi
->pheader
->ts
.tv_sec
;
19 printf("\nBAD ERROR in update_asset\n");
27 void update_service_stats(int role
, uint16_t proto
)
29 if (role
==SC_SERVER
) {
30 if (proto
== 6) config
.pr_s
.tcp_services
++;
31 if (proto
==17) config
.pr_s
.udp_services
++;
33 if (proto
== 6) config
.pr_s
.tcp_clients
++;
34 if (proto
==17) config
.pr_s
.udp_clients
++;
38 void update_os_stats(uint8_t detection
)
47 config
.pr_s
.tcp_os_assets
++;
50 config
.pr_s
.udp_os_assets
++;
53 config
.pr_s
.icmp_os_assets
++;
56 config
.pr_s
.dhcp_os_assets
++;
63 void flip_connection(packetinfo
*pi
, asset
* masset
)
65 if (pi
->sc
== SC_CLIENT
) {
66 if (pi
->cxt
->reversed
== 0)
67 pi
->cxt
->c_asset
= masset
;
69 pi
->cxt
->s_asset
= masset
;
71 if (pi
->cxt
->reversed
== 0)
72 pi
->cxt
->s_asset
= masset
;
74 pi
->cxt
->c_asset
= masset
;
76 if (pi
->sc
== SC_CLIENT
) {
77 if (pi
->cxt
->reversed
== 0)
78 pi
->cxt
->c_asset
= masset
;
80 pi
->cxt
->s_asset
= masset
;
82 if (pi
->cxt
->reversed
== 0)
83 pi
->cxt
->s_asset
= masset
;
85 pi
->cxt
->c_asset
= masset
;
89 asset
* connection_lookup(packetinfo
*pi
)
95 if (pi
->sc
== SC_CLIENT
&& pi
->cxt
->reversed
== 0 && pi
->cxt
->c_asset
!= NULL
) {
96 return pi
->cxt
->c_asset
;
97 } else if (pi
->sc
== SC_CLIENT
&& pi
->cxt
->reversed
== 1 && pi
->cxt
->s_asset
!= NULL
) {
98 return pi
->cxt
->s_asset
;
99 } else if (pi
->sc
== SC_SERVER
&& pi
->cxt
->reversed
== 0 && pi
->cxt
->s_asset
!= NULL
) {
100 return pi
->cxt
->s_asset
;
101 } else if (pi
->sc
== SC_SERVER
&& pi
->cxt
->reversed
== 1 && pi
->cxt
->c_asset
!= NULL
) {
102 return pi
->cxt
->c_asset
;
106 /* asset *asset_lookup(struct in6_addr ip, int af)
107 * tries to match your packet to a sender we've seen before
109 * 1. already in connection database
110 * 2. ip4 lookup & ip6 lookup
113 * asset_lookup should return 0 on success, 1 on failure
115 uint8_t asset_lookup(packetinfo
*pi
)
118 asset
*masset
= NULL
;
120 if (pi
->asset
!= NULL
|| NULL
!= (pi
->asset
= connection_lookup(pi
))){
123 if (pi
->af
== AF_INET
) {
126 if(pi
->arph
) {// arp check
127 //memcpy(&ip, pi->arph->arp_spa, sizeof(uint8_t)*4);
128 ip
= *(uint32_t*) pi
->arph
->arp_spa
;
132 hash
= ASSET_HASH4(ip
);
133 masset
= passet
[hash
];
134 while (masset
!= NULL
) {
135 //if (memcmp(&ip_addr,&rec->ip_addr,16)) {
136 if (masset
->af
== AF_INET
137 && CMP_ADDR4( &masset
->ip_addr
, ip
))
140 if (pi
->cxt
!= NULL
) {
141 flip_connection(pi
,masset
);
145 masset
= masset
->next
;
148 } else if (pi
->af
== AF_INET6
) {
149 hash
= ASSET_HASH6(PI_IP6SRC(pi
));
150 masset
= passet
[hash
];
151 while (masset
!= NULL
) {
152 if (masset
->af
== AF_INET6
&&
153 CMP_ADDR6(&masset
->ip_addr
, &PI_IP6SRC(pi
))){
155 if (pi
->cxt
!= NULL
) {
156 flip_connection(pi
,masset
);
160 masset
= masset
->next
;
168 /* ----------------------------------------------------------
169 * FUNCTION : update_asset_os
170 * DESCRIPTION : This function will update the OS
171 * : fields of an asset.
172 * INPUT : 0 - IP Address
174 * : 2 - detection method
178 * RETURN : 0 - Success!
180 * ---------------------------------------------------------- */
182 short update_asset_shmem(packetinfo
*pi
)
184 // flip it upside down: caller packs it?
185 // now how would that eat the program from the inside?
186 // pass the struct around but store it in a shared mem buffer
188 // what is detection?
194 // what more do we need in the *pi?
197 // signatures identify HOSTS or SERVICES
198 // (or mac resources) .. eventually have graph method
199 return 1; // we did the computation straight on the *pi;
201 //update_asset_os_shmem(pi);
202 return 2; // whatever
204 return 1338; // not leet.
208 short update_asset_os (
216 os_asset
*tmp_oa
= NULL
;
217 os_asset
*head_oa
= NULL
;
219 if (asset_lookup(pi
) == SUCCESS
) {
220 if (pi
->asset
!= NULL
) {
223 elog("BAD ERROR in update_asset_os\n");
228 if (update_asset_os(pi
, detection
, raw_fp
, match
, uptime
) == SUCCESS
) return SUCCESS
;
233 tmp_oa
= pi
->asset
->os
;
234 head_oa
= pi
->asset
->os
;
235 pi
->asset
->last_seen
= pi
->pheader
->ts
.tv_sec
;
237 while (tmp_oa
!= NULL
) {
238 if (detection
== tmp_oa
->detection
) {
240 // old style save-the-fp-string OS detection
241 if (biseq(raw_fp
, tmp_oa
->raw_fp
) == 1) {
243 // FIXME: inefficient string copies
244 bdestroy(tmp_oa
->raw_fp
);
245 tmp_oa
->raw_fp
= bstrcpy(raw_fp
);
246 //tmp_sa->i_attempts++;
248 tmp_oa
->port
= PI_TCP_SP(pi
);
252 tmp_oa
->last_seen
= pi
->pheader
->ts
.tv_sec
;
253 if (uptime
) tmp_oa
->uptime
= uptime
;
257 // pointer equality - does this OS asset point
258 // to the same match?
259 if (match
->os
== tmp_oa
->fp
.os
&&
260 match
->desc
== tmp_oa
->fp
.desc
){
261 //if (match == tmp_oa->match) {
264 tmp_oa
->port
= PI_TCP_SP(pi
);
268 tmp_oa
->last_seen
= pi
->pheader
->ts
.tv_sec
;
270 tmp_oa
->uptime
= uptime
;
275 tmp_oa
= tmp_oa
->next
;
278 if (tmp_oa
== NULL
) {
279 update_os_stats(detection
);
280 os_asset
*new_oa
= NULL
;
282 // FIXME: allocate resource from shared storage pool
283 new_oa
= (os_asset
*) calloc(1, sizeof(os_asset
));
284 new_oa
->detection
= detection
;
287 // FIXME: don't copy fp, bincode it
288 new_oa
->raw_fp
= bstrcpy(raw_fp
);
292 //new_oa->fp = *match; //why copy it two times?
294 //new_oa->i_attempts = 1;
295 new_oa
->first_seen
= pi
->pheader
->ts
.tv_sec
;
296 new_oa
->last_seen
= pi
->pheader
->ts
.tv_sec
;
299 new_oa
->port
= PI_TCP_SP(pi
);
303 if (pi
->ip4
!= NULL
) new_oa
->ttl
= pi
->ip4
->ip_ttl
;
304 else if (pi
->ip6
!= NULL
) new_oa
->ttl
= pi
->ip6
->hop_lmt
;
305 if (uptime
) new_oa
->uptime
= uptime
;
306 new_oa
->next
= head_oa
;
308 head_oa
->prev
= new_oa
;
310 pi
->asset
->os
= new_oa
;
312 log_asset_os(pi
->asset
,new_oa
);
318 /* ----------------------------------------------------------
319 * FUNCTION : update_asset_service
320 * DESCRIPTION : This function will update the service and
321 * : application fields of an asset.
322 * INPUT : 0 - IP Address
327 * RETURN : 0 - Success!
329 * ---------------------------------------------------------- */
330 short update_asset_service(packetinfo
*pi
, bstring service
, bstring application
)
332 serv_asset
*tmp_sa
= NULL
;
333 serv_asset
*head_sa
= NULL
;
336 if (asset_lookup(pi
) == SUCCESS
) {
337 if (pi
->asset
!= NULL
) {
338 if (pi
->sc
== SC_CLIENT
) {
345 printf("\nBAD ERROR in update_asset_service\n");
351 return update_asset_service(pi
, service
, application
);
356 /* Find asset within linked list */
357 tmp_sa
= head_sa
= pi
->asset
->services
;
358 pi
->asset
->last_seen
= pi
->pheader
->ts
.tv_sec
;
360 while (tmp_sa
!= NULL
) {
361 if (port
== tmp_sa
->port
&& pi
->proto
== tmp_sa
->proto
) {
364 * If we have an id for the service which is != unknown AND the id now is unknown
365 * - just increment i_attempts untill MAX_PKT_CHECK before replacing with unknown
367 * NEW: No more unknown :)
368 * But now we have generic service for the port, example: @https
369 * So now we just check the first char of the string for '@'.
370 * if (application->data[0] != '@') (If the service matched dont starts with a '@')
371 * and the service registered in the service_asset starts with '@', discard it and
372 * register the new asset!
374 if ((application
->data
[0] != '@') && (tmp_sa
->application
->data
[0] == '@')) {
375 tmp_sa
->i_attempts
= 0;
376 bdestroy(tmp_sa
->service
);
377 bdestroy(tmp_sa
->application
);
378 tmp_sa
->service
= bstrcpy(service
);
379 tmp_sa
->application
= bstrcpy(application
);
380 tmp_sa
->last_seen
= pi
->pheader
->ts
.tv_sec
;
382 log_asset_service(pi
->asset
,tmp_sa
);
385 } else if (!(biseq(application
, tmp_sa
->application
) == 1)) {
386 if (tmp_sa
->i_attempts
> MAX_SERVICE_CHECK
) {
387 tmp_sa
->i_attempts
= 0;
388 bdestroy(tmp_sa
->service
);
389 bdestroy(tmp_sa
->application
);
390 tmp_sa
->service
= bstrcpy(service
);
391 tmp_sa
->application
= bstrcpy(application
);
392 tmp_sa
->last_seen
= pi
->pheader
->ts
.tv_sec
;
394 log_asset_service(pi
->asset
,tmp_sa
);
398 tmp_sa
->i_attempts
++;
399 tmp_sa
->last_seen
= pi
->pheader
->ts
.tv_sec
;
403 tmp_sa
->i_attempts
= 0;
404 tmp_sa
->last_seen
= pi
->pheader
->ts
.tv_sec
;
408 tmp_sa
= tmp_sa
->next
;
411 if (tmp_sa
== NULL
) {
412 update_service_stats(pi
->sc
, pi
->proto
);
413 serv_asset
*new_sa
= NULL
;
414 new_sa
= (serv_asset
*) calloc(1, sizeof(serv_asset
));
416 if (pi
->ip4
!= NULL
) new_sa
->ttl
= pi
->ip4
->ip_ttl
;
417 else if (pi
->ip6
!= NULL
) new_sa
->ttl
= pi
->ip6
->hop_lmt
;
418 new_sa
->proto
= pi
->proto
;
419 new_sa
->service
= bstrcpy(service
);
420 new_sa
->application
= bstrcpy(application
);
421 new_sa
->role
= pi
->sc
;
422 new_sa
->i_attempts
= 0;
423 new_sa
->first_seen
= pi
->pheader
->ts
.tv_sec
;
424 new_sa
->last_seen
= pi
->pheader
->ts
.tv_sec
;
425 new_sa
->next
= pi
->asset
->services
;
427 pi
->asset
->services
= new_sa
;
429 log_asset_service(pi
->asset
, new_sa
);
435 /* ----------------------------------------------------------
436 * FUNCTION : add_asset
437 * DESCRIPTION : This function will add an asset to the
438 * : specified asset data structure.
439 * INPUT : 0 - packetinfo (af, ip_src, vlan)
441 * ---------------------------------------------------------- */
442 void add_asset(packetinfo
*pi
)
445 asset
*masset
= NULL
;
447 config
.pr_s
.assets
++;
449 masset
= (asset
*) calloc(1, sizeof(asset
));
451 masset
->vlan
= pi
->vlan
;
452 masset
->i_attempts
= 0;
453 masset
->first_seen
= masset
->last_seen
= pi
->pheader
->ts
.tv_sec
;
455 if (pi
->af
== AF_INET
) {
456 if(pi
->arph
) // mongo arp check
457 //memcpy(&masset->ip_addr.__u6_addr.__u6_addr32[0], pi->arph->arp_spa, sizeof(uint32_t));
458 IP4ADDR(&masset
->ip_addr
) = *(uint32_t*) pi
->arph
->arp_spa
;
460 IP4ADDR(&masset
->ip_addr
) = PI_IP4SRC(pi
);
461 hash
= ASSET_HASH4(IP4ADDR(&masset
->ip_addr
));
462 } else if (pi
->af
== AF_INET6
) {
463 masset
->ip_addr
= PI_IP6SRC(pi
);
464 hash
= ASSET_HASH6(PI_IP6SRC(pi
));
467 masset
->next
= passet
[hash
];
469 if (passet
[hash
] != NULL
)
470 passet
[hash
]->prev
= masset
;
473 masset
->services
= NULL
;
474 masset
->macentry
= NULL
;
475 passet
[hash
] = masset
;
478 /* verbose info for sanity checking */
479 static char ip_addr_s
[INET6_ADDRSTRLEN
];
480 u_ntop(pi
->ip_src
, pi
->af
, ip_addr_s
);
481 dlog("[*] asset added: %s\n",ip_addr_s
);
487 short update_asset_arp(u_int8_t arp_sha
[MAC_ADDR_LEN
], packetinfo
*pi
)
489 if (asset_lookup(pi
) == SUCCESS
) {
490 if (pi
->asset
!= NULL
) {
493 printf("\nBAD ERROR in update_asset_arp\n");
501 if ( pi
->asset
== NULL
) {
502 elog("update_asset(pi) failed! Asset does not exist! Cant enter MAC!!! die();\n");
505 if (update_asset_arp(arp_sha
, pi
) == SUCCESS
) {
513 /* Check the ARP data structure for an existing entry */
514 if (memcmp(pi
->asset
->mac_addr
, arp_sha
, MAC_ADDR_LEN
) == 0) {
515 /* UPDATE TIME STAMP */
516 pi
->asset
->last_seen
= pi
->pheader
->ts
.tv_sec
;
519 /* UPDATE MAC AND TIME STAMP */
520 /* XXX: this handler suxx! */
521 if(memcmp(pi
->asset
->mac_addr
, "\0\0\0\0\0\0", 6)){
522 printf("ACHTUNG! MAC changed! : ");
523 print_mac(pi
->asset
->mac_addr
);
530 if(pi
->asset
->macentry
== NULL
) {
531 // vendor entry did not exist.
532 mac_entry
*match
= match_mac(config
.sig_mac
, arp_sha
, 48);
533 pi
->asset
->macentry
= match
;
535 memcpy(&pi
->asset
->mac_addr
, arp_sha
, MAC_ADDR_LEN
);
536 pi
->asset
->last_seen
= pi
->pheader
->ts
.tv_sec
;
537 log_asset_arp(pi
->asset
);
542 void del_os_asset(os_asset
** head_oa
, os_asset
* os
)
547 os_asset
*tmp_oa
= NULL
;
548 os_asset
*next_oa
= NULL
;
549 os_asset
*prev_oa
= NULL
;
552 //bdestroy(tmp_oa->vendor);
553 //bdestroy(tmp_oa->os);
554 bdestroy(tmp_oa
->raw_fp
);
555 //bdestroy(tmp_oa->matched_fp);
557 next_oa
= tmp_oa
->next
;
558 prev_oa
= tmp_oa
->prev
;
560 if (prev_oa
== NULL
) {
569 next_oa
->prev
= NULL
;
570 } else if (next_oa
== NULL
) {
574 prev_oa
->next
= NULL
;
579 prev_oa
->next
= next_oa
;
580 next_oa
->prev
= prev_oa
;
590 void del_serv_asset(serv_asset
** head_sa
, serv_asset
* service
)
595 serv_asset
*tmp_sa
= NULL
;
596 serv_asset
*next_sa
= NULL
;
597 serv_asset
*prev_sa
= NULL
;
600 bdestroy(tmp_sa
->service
);
601 bdestroy(tmp_sa
->application
);
603 next_sa
= tmp_sa
->next
;
604 prev_sa
= tmp_sa
->prev
;
606 if (prev_sa
== NULL
) {
615 next_sa
->prev
= NULL
;
616 } else if (next_sa
== NULL
) {
620 prev_sa
->next
= NULL
;
625 prev_sa
->next
= next_sa
;
626 next_sa
->prev
= prev_sa
;
635 void del_asset(asset
* passet
, asset
** bucket_ptr
)
638 * remove passet from bucket
640 asset
*prev
= passet
->prev
; /* OLDER connections */
641 asset
*next
= passet
->next
; /* NEWER connections */
642 serv_asset
*tmp_sa
= passet
->services
;
643 os_asset
*tmp_oa
= passet
->os
;
644 serv_asset
*stmp
= tmp_sa
;
645 os_asset
*otmp
= tmp_oa
;
648 * delete all service assets
650 while (tmp_sa
!= NULL
) {
652 tmp_sa
= tmp_sa
->next
;
653 del_serv_asset(&passet
->services
, stmp
);
656 * delete all os assets
658 while (tmp_oa
!= NULL
) {
660 tmp_oa
= tmp_oa
->next
;
661 del_os_asset(&passet
->os
, otmp
);
665 * now delete the asset
673 } else if (next
== NULL
) {
683 * Free and set to NULL
689 void clear_asset_list()
694 for (akey
= 0; akey
< BUCKET_SIZE
; akey
++) {
696 while (rec
!= NULL
) {
697 serv_asset
*tmp_sa
= NULL
;
698 os_asset
*tmp_oa
= NULL
;
699 tmp_sa
= rec
->services
;
702 while (tmp_sa
!= NULL
) {
703 /* Delete service asset */
704 serv_asset
*stmp
= tmp_sa
;
705 tmp_sa
= tmp_sa
->next
;
706 del_serv_asset(&rec
->services
, stmp
);
709 while (tmp_oa
!= NULL
) {
710 /* Delete os asset */
711 os_asset
*otmp
= tmp_oa
;
712 tmp_oa
= tmp_oa
->next
;
713 del_os_asset(&rec
->os
, otmp
);
716 /* Delete the main asset */
719 del_asset(tmp
, &passet
[akey
]);
722 olog("asset memory has been cleared\n");
725 /* update_asset_list()
726 ** iterates over all assets,
729 ** and expires old (service, os, asset) since CHECK_TIMEOUT
730 ** optionally printing assets updated since ASSET_TIMEOUT
732 void update_asset_list()
734 extern time_t tstamp
;
737 serv_asset
*tmp_sa
= NULL
;
738 os_asset
*tmp_oa
= NULL
;
740 for (akey
= 0; akey
< BUCKET_SIZE
; akey
++) {
742 while (rec
!= NULL
) {
743 /* Checks if something has been updated in the asset since last time */
744 if (tstamp
- rec
->last_seen
<= CHECK_TIMEOUT
) {
745 tmp_sa
= rec
->services
;
747 if (config
.print_updates
) log_asset_arp(rec
);
749 while (tmp_sa
!= NULL
) {
750 /* Just print out the asset if it is updated since lasttime */
751 if (config
.print_updates
&& tstamp
- tmp_sa
->last_seen
<= CHECK_TIMEOUT
) {
752 log_asset_service(rec
,tmp_sa
);
754 /* If the asset is getting too old - delete it */
755 if (config
.print_updates
&& tstamp
- tmp_sa
->last_seen
>= ASSET_TIMEOUT
) {
756 serv_asset
*stmp
= tmp_sa
;
757 tmp_sa
= tmp_sa
->next
;
758 del_serv_asset(&rec
->services
, stmp
);
760 tmp_sa
= tmp_sa
->next
;
764 while (tmp_oa
!= NULL
) {
765 /* Just print out the asset if it is updated since lasttime */
766 if (config
.print_updates
&& tstamp
- tmp_oa
->last_seen
<= CHECK_TIMEOUT
) {
767 log_asset_os(rec
, tmp_oa
);
769 /* If the asset is getting too old - delete it */
770 if (tstamp
- tmp_oa
->last_seen
>= ASSET_TIMEOUT
) {
771 os_asset
*otmp
= tmp_oa
;
772 tmp_oa
= tmp_oa
->next
;
773 del_os_asset(&rec
->os
, otmp
);
775 tmp_oa
= tmp_oa
->next
;
780 /* If nothing in the asset has been updated for some time - delete it! */
781 if (tstamp
- rec
->last_seen
>= ASSET_TIMEOUT
) {
784 del_asset(tmp
, &passet
[akey
]);