#pragma implementation #include #include #include #include #include #include #include #include #include #include #include #include #include "inetdconf.h" #include "inetdconf.m" #include "etcservice.h" #include "fwport.h" #include "../../paths.h" #include "firewalld/netdevice.h" #include "fwedit.h" static const char K_ACTIVE[] = "active"; static const char K_ACTIVE_NO = 0; static const char K_ACTIVE_YES = 1; static const char K_LOG_DENIED[] = "log_denied"; static const char K_LOG_DENIED_NO = 0; static const char K_LOG_DENIED_YES = 1; static const char ETC_HEIMDALL[] = "/etc/heimdall"; #define FIREWALL_DAEMON "firewalld" #define PROC_SYS_NET_IPV4_IPLOCAL_PORT_RANGE "/proc/sys/net/ipv4/ip_local_port_range" static CONFIG_FILE f_proc_route (PROC_NET_ROUTE,help_nil,CONFIGF_PROBED); /* * class DAEMON_DIALD * class DAEMON_FIREWALL */ #include #include #include static int previous_active = -1; static HELP_FILE help_firewall ("inetdconf","firewall"); static CONFIG_FILE f_config_file( FIREWALL_CONFIG ,help_firewall ,CONFIGF_OPTIONAL|CONFIGF_MANAGED|CONFIGF_GENERATED|CONFIGF_PROBED ,"root" ,"root" ,0700 ,subsys_inetdconf); static CONFIG_FILE f_script_file( FIREWALL_SCRIPT ,help_firewall ,CONFIGF_OPTIONAL|CONFIGF_MANAGED|CONFIGF_GENERATED|CONFIGF_PROBED ,"root" ,"root" ,0700 ,subsys_inetdconf); /* * DAEMON_DIALD */ class PROC; class DAEMON_DIALD { private: public: PROC *myProcess; public: DAEMON_DIALD(); PROC *getdaemonprocess( void ); }; PUBLIC DAEMON_DIALD::DAEMON_DIALD() { myProcess = getdaemonprocess(); } PUBLIC PROC *DAEMON_DIALD::getdaemonprocess() { PROC *myProcess = NULL; char pidpath[PATH_MAX]; sprintf (pidpath,"%s.pid","/var/run/diald"); CONFIG_FILE f_pid ( pidpath, help_nil ,CONFIGF_OPTIONAL|CONFIGF_MANAGED ,"root","root",0600); if ( f_pid.exist ()){ myProcess = process_find ("diald", &f_pid); } return( myProcess ); } PUBLIC FW::FW( ) { linuxconf_setcursys( subsys_inetdconf ); etcservicelist = new ETCSERVICELIST(); etcservicelist->read(); fwportlist = new FWPORTLIST(); fwportlist->read(); fwportlist->sort(); fwportlist->update_from_db(); internet = NULL; netdevice = netdevice_read(); // NETDEVICE ifn; // for (ifn=netdevice[0]; ifn; ifn=ifn->next) { //fprintf(stderr,"firewall_edit: device=%s %s\n", ifn->name, ifn->status_if==STATUS_IF_UP?"UP":"DOWN" ); // } FILE *fp = NULL; #if 0 // Windows uses ports above 60000... FILE *fp = fopen( PROC_SYS_NET_IPV4_IPLOCAL_PORT_RANGE, "r" ); if ( fp != NULL ) { fscanf( fp, "%d %d", &port_low, &port_high ); fclose( fp ); } else { port_low = 1024; port_high = 65535; } #endif port_low = 1024; port_high = 65535; local_interfaces = 0; fp = fopen( PROC_SYS_NET_IPV4_DYNADDR, "r" ); if ( fp != NULL ) { fscanf( fp, "%d", &ip_dynaddr ); fclose( fp ); } else { ip_dynaddr = 0; } fp = fopen( PROC_SYS_IP_FORWARD, "r" ); if ( fp != NULL ) { fscanf( fp, "%d", &ip_forward ); fclose( fp ); } else { ip_forward = 0; } //fprintf(stderr, "FW::FW: port_low=%d port_high=%d ip_forward=%d ip_dynaddr=%d\n", port_low, port_high, ip_forward, ip_dynaddr ); active = (char)linuxconf_getvalnum( K_FIREWALL, K_ACTIVE, 0 ); if ( previous_active == -1 ) previous_active = active; frequency=(char)linuxconf_getvalnum(K_FIREWALL, K_FREQUENCY, K_FREQUENCY_1); details=(char)linuxconf_getvalnum(K_FIREWALL, K_DETAILS, K_DETAILS_NORMAL); log_denied=(char)linuxconf_getvalnum(K_FIREWALL, K_LOG_DENIED, K_LOG_DENIED_YES); } PUBLIC FW::~FW( void ) { delete fwportlist; delete etcservicelist; } PUBLIC int FW::firewall_setup( ) { //fprintf(stderr,"firewall_edit:\n"); if ( ! kernel_newer( 2,2,0 ) ) { xconf_error( MSG_U( E_OLD_KERNEL, "Sorry, your kernel is too old for this function.\n" "Version at least 2.2.0 required\n" ) ); return( 0 ); } //fprintf(stderr,"firewall_edit: enter internet_route\n"); if ( internet_route() == 0 ) { DAEMON_DIALD myDiald; if ( myDiald.myProcess != NULL ) { xconf_error( MSG_U( E_NOT_UP, "Route to the internet is not valid.\n" "Diald is running but the link is not active.\n" "Can not determine the route to the internet!\n" ) ); } else { xconf_error( MSG_U( E_NODEFAULT_ROUTE, "Can not determine the route to the internet!\n" "The search is based on internet being the default\n" "route.\n") ); } return( 0 ); } //fprintf(stderr,"firewall_edit: internet_ip=%s internet->name=%s\n", internet->ip_alfa, internet->name); if ( fwportlist->getnb() == 0 ) { xconf_error( MSG_U( E_NOPORTLIST, "No active services could be located in this system.\n" "If this is correct there is no need for a firewall.\n" ) ); return( 0 ); } internet->deny_icmp_echo_request=(char)linuxconf_getvalnum(K_FIREWALL, K_DENY_ICMP_ECHO_REQUEST, 1); internet->deny_icmp_time_exceeded=(char)linuxconf_getvalnum(K_FIREWALL, K_DENY_ICMP_TIME_EXCEEDED, 1); return( 1 ); } /* * Find route and device to the internet. */ PUBLIC int FW::internet_route( void ) { //fprintf(stderr,"internet_route\n" ); FILE_CFG *fp = f_proc_route.fopen ("r"); if (fp == NULL) { return( 0 ); } int found = 0; char buf[300]; char interface[30]; // Skip the first line (title line) fgets(buf,sizeof( buf)-1, fp ); while ( fgets( buf, sizeof( buf )-1, fp) !=NULL ) { unsigned long ip_dst, ip_gate, gen_mask, flags; char junk[20],iface[20]; if (sscanf (buf,"%s %lx %lx %lx %s %s %s %lx",iface,&ip_dst,&ip_gate ,&flags,junk,junk,junk,&gen_mask) != 8 ) { xconf_error (MSG_U(E_IVLOUTPUT ,"Invalid content in /proc/net/route\n%s\n") ,buf); return( 0 ); } else if (flags & 1) { // Only collect routes which are UP ip_dst = ntohl(ip_dst); if ( ip_dst == 0 ) { // Default route found = 1; strncpy( interface, iface, sizeof( interface )); break; } } } fclose( fp ); if ( ! found ) { return( 0 ); } found = 0; for ( NETDEVICE ifn=netdevice[0]; ifn; ifn=ifn->next) { if ( ifn->status_if == STATUS_IF_DOWN ) continue; //fprintf(stderr,"internet_route: device=%s\n", ifn->name ); if ( ( strcmp( ifn->name, interface ) ) == 0 ) { //fprintf(stderr,"internet_route: found interface=%s\n", interface ); internet = ifn; found = 1; break; } } if ( ! found ) { return( found ); } /* * Count real interfaces (excluding internet interface) for * forwarding logic */ for ( NETDEVICE ifn=netdevice[0]; ifn; ifn=ifn->next) { if ( ifn->status_if == STATUS_IF_DOWN ) continue; if ( ifn == internet ) continue; if ( strncmp( ifn->name, "lo", 2 ) == 0 ) continue; local_interfaces++; } //fprintf(stderr,"internet_route: internet=%s, local_interfaces=%d\n", internet->name, local_interfaces ); return( found ); } /* * Config file is written only for use by the firewall daemon. */ PUBLIC void FW::daemon_config_file( void ) { VIEWITEMS items; VIEWITEM *item; char line[128]; item = new VIEWITEM( MSG_U(I_CONFIG_FILE, "#\n" "# Generated by Linuxconf (module inetdconf)\n" "# http://www.solucorp.qc.ca/linuxconf/\n" "#\n" "# for:\n" "#\n" "# Heimdall firewall daemon (distributed as part of Linuxconf)\n" "# http://heimdall.sourceforge.net\n" "#\n" ) ); items.add( item ); snprintf( line, sizeof(line), "%s %s", K_SCRIPT_FILE, f_script_file.getpath()); item = new VIEWITEM(line); items.add( item ); char *strfrequency = NULL; switch ( frequency ) { case K_FREQUENCY_1: strfrequency = "1"; break; case K_FREQUENCY_10: strfrequency = "10"; break; case K_FREQUENCY_100: strfrequency = "100"; break; } snprintf( line, sizeof(line), "%s %s", K_FREQUENCY, strfrequency ); item = new VIEWITEM(line); items.add( item ); snprintf( line, sizeof(line), "%s %d", K_VERBOSE, details ); item = new VIEWITEM(line); items.add( item ); items.write( f_config_file, (PRIVILEGE *)NULL ); } PRIVATE void FW::write_start_firewall_forward( FILE_CFG *fout, const char *ipchains ) { fprintf( fout, " \n\ # \n\ # Forward: \n\ # - Flush rules \n\ # - Allow local interfaces with MASQ. \n\ # - Masquerade for RFC1918 networks (10.0.0.0/8, \n\ # 192.168.0.0/16 and 172.16.0.0/12) \n\ # - The rest: DENY (and log ?) \n\ # \n\ "); fprintf( fout, "\t%s -F forward;\n", ipchains ); for ( NETDEVICE ifn=netdevice[0]; ifn; ifn=ifn->next) { if ( ifn->status_if == STATUS_IF_DOWN ) continue; if ( ifn == internet ) continue; if ( strncmp( ifn->name, "lo", 2 ) == 0 ) continue; /* * Does NOT work if interface specified here! */ fprintf( fout, "\t%s -A forward -s %s/%s %s -b;\n", ipchains, ifn->ip_alfa, ifn->netmask_alfa, ifn->RFC1918 ? "-j MASQ" : "" ); } fprintf( fout, "\t%s -A forward -j DENY%s;\n", ipchains, log_denied ? " -l" : "" ); } PUBLIC int FW::write( void ) { if ( ! perm_rootaccess( MSG_U(P_EDITFIREWALL, "change internet firewall") ) ) { return( -1 ); } if ( file_mkdirp( ETC_HEIMDALL,"root","root",0700 ) == -1 ) { xconf_error (MSG_U(E_CREATEDIR ,"Can't create directory %s\n" "(%s)") ,ETC_HEIMDALL, strerror(errno)); return( -1 ); } /* * Update linuxconf database */ linuxconf_setcursys( subsys_inetdconf ); linuxconf_replace( K_FIREWALL, K_ACTIVE, active ); linuxconf_replace( K_FIREWALL, K_FREQUENCY, frequency ); linuxconf_replace( K_FIREWALL, K_DETAILS, details ); linuxconf_replace( K_FIREWALL, K_LOG_DENIED, log_denied ); if ( internet->deny_icmp_echo_request ) { linuxconf_replace( K_FIREWALL, K_DENY_ICMP_ECHO_REQUEST, 1); } else { linuxconf_removeall( K_FIREWALL, K_DENY_ICMP_ECHO_REQUEST); } if ( internet->deny_icmp_time_exceeded ) { linuxconf_replace( K_FIREWALL, K_DENY_ICMP_TIME_EXCEEDED, 1); } else { linuxconf_removeall( K_FIREWALL, K_DENY_ICMP_TIME_EXCEEDED); } for (int i=0; igetnb(); i++ ) { FWPORT *fwport = fwportlist->getitem( i ); char service[100]; snprintf( service, sizeof(service), "%s/%d", fwport->protocol.get(), fwport->port); if ( fwport->accept ) { linuxconf_replace( K_FIREWALL, service, fwport->accept); } else { linuxconf_removeall( K_FIREWALL, service ); } } linuxconf_save( (PRIVILEGE *)NULL ); /* * Update daemon config file */ if ( active ) { daemon_config_file( ); } const char *ipchains = daemon_findpath( "ipchains" ); FILE_CFG *fout = f_script_file.fopen( (PRIVILEGE *)NULL, "w" ); fprintf( fout, "\ #!/bin/sh\n\ #\n\ # Heimdall Interface monitor and firewall activator\n\ #\n\ # chkconfig: 345 51 49\n\ #\n\ # description: Heimdall firewalld is an interface monitor which starts a script\n\ # at interface state or ip address change for firewall activation.\n\ #\n\ # processname: firewalld\n\ # config: /etc/heimdall/firewall.conf\n\ # pidfile: /var/run/firewalld.pid\n\ #\n\ # Created by Linuxconf (module: inetdconf)\n\ #\n\ # This file can not be used as a sys V init script file directly as\n\ # it needs interface and ip address as parameters.\n\ #\n\ command=$1;\n\ network_device=$2;\n\ ip=$3;\n\ \n\ \n\ start_firewall() {\n\ "); if ( ip_forward && local_interfaces ) { write_start_firewall_forward( fout, ipchains ); } fprintf( fout, "\n\ #\n\ # Input:\n\ # - Flush input rules\n\ # - No policy set\n\ # - Fragments: ACCEPT\n\ #\n\ "); fprintf( fout, "\t%s -F input;\n", // Flush input rules ipchains ); fprintf( fout, "\t%s -A input -f -j ACCEPT;\n", ipchains ); fprintf( fout, "\n\ #\n\ # Input:\n\ # Local interfaces: ACCEPT\n\ #\n\ "); for ( NETDEVICE ifn=netdevice[0]; ifn; ifn=ifn->next) { if ( ifn->status_if == STATUS_IF_DOWN ) continue; if ( ifn == internet ) continue; fprintf( fout, "\t%s -A input -i %s -j ACCEPT;\n", ipchains, ifn->name ); } fprintf( fout, "\n\ #\n\ # Input: Internet interface chain (definition)\n\ # - Create internet interface chain (succeeds if missing)\n\ # - Flush rules in internet interface chain\n\ # - Create reference to new chain from input chain\n\ #\n\ "); // New internet chain fprintf( fout, "\t%s -N i_%s 2>/dev/null;\n", ipchains, internet->name ); fprintf( fout, "\t%s -F i_%s;\n", // Flush internet chain ipchains, internet->name ); // Internet chain reference fprintf( fout, "\t%s -A input -i %s -j i_%s;\n", ipchains, internet->name, internet->name ); fprintf( fout, "\n\ #\n\ # Input:\n\ # - icmp to all other interfaces: ACCEPT\n\ # - Everything else will be subject to input policy which is not\n\ # set in this script. In particular any soft interfaces which\n\ # where not up at script creation time, will be subject to policy.\n\ # This could be the case for incoming or outgoing ppp connections.\n\ #\n\ "); fprintf( fout, "\t%s -A input -p icmp -j ACCEPT;\n", ipchains ); fprintf( fout, "\n\ #\n\ # Input: Internet interface chain\n\ # - Source address equals our own network (spoofed!): DENY\n\ #\n\ "); fprintf( fout, "\t%s -A i_%s -s $ip/%s -j DENY%s;\n", ipchains, internet->name, internet->netmask_alfa, log_denied ? " -l" : "" ); if ( internet->deny_icmp_echo_request ) { fprintf( fout, "\n\ #\n\ # Input: Internet interface chain (continued)\n\ # - Ping from the internet: DENY\n\ #\n\ "); fprintf( fout, "\t%s -A i_%s -p icmp --icmp-type echo-request -d $ip/32 -j DENY%s;\n", ipchains, internet->name, log_denied ? " -l" : "" ); } fprintf( fout, "\n\ #\n\ # Input: Internet interface chain (continued)\n\ # - icmp with proper destination: ACCEPT\n\ # - icmp (the rest, including broadcasts): DENY\n\ #\n\ "); fprintf( fout, "\t%s -A i_%s -p icmp -d $ip/32 -j ACCEPT;\n", ipchains, internet->name ); fprintf( fout, "\t%s -A i_%s -p icmp -j DENY%s;\n", ipchains, internet->name, log_denied ? " -l" : "" ); fprintf( fout, "\n\ #\n\ # Input: Internet interface chain (continued)\n\ # - Services accepted in dialog: ACCEPT\n\ #\n\ "); for (int i=0; igetnb(); i++ ) { FWPORT *fwport = fwportlist->getitem( i ); if ( ! fwport->accept ) continue; ETCSERVICE *etcservice = etcservicelist->getitem( fwport->protocol.get(), fwport->port); char port[100]; const char *service = ""; if ( etcservice!=NULL) { service = etcservice->service_name.get(); } if ( strcmp( service, "ftp") == 0 ) { /* * Accept ftp-data (ftp port - 1) */ ETCSERVICE *ftp_data = etcservicelist->getitem( fwport->protocol.get(), fwport->port-1 ); if ( ftp_data != NULL ) { const char *ftp_data_name = ftp_data->service_name.get(); snprintf( port, sizeof(port), "%s:%s", ftp_data_name, service ); } else { snprintf( port, sizeof(port), "%d:%d", fwport->port-1, fwport->port ); } } else { if ( etcservice!=NULL) { snprintf( port, sizeof(port), "%s", service ); } else { snprintf( port, sizeof(port), "%d", fwport->port ); } } fprintf( fout, "\t%s -A i_%s -p %s -d $ip/32 %s -j ACCEPT;\n", ipchains, internet->name, fwport->protocol.get(), port ); } fprintf( fout, "\n\ #\n\ # Input: Internet interface chain (continued)\n\ # - Port %d <= not accepted ports <= port %d: DENY\n\ # (unless program is named and protocol is udp which is never\n\ # denied: In case of dynamic IP numbers named will listen to\n\ # different IP numbers)\n\ #\n\ ", port_low, port_high ); for (int i=0; igetnb(); i++ ) { FWPORT *fwport = fwportlist->getitem( i ); if ( fwport->port <= port_low || fwport->port >= port_high) continue; if ( fwport->accept ) continue; if (( strcmp( fwport->program.get(), "named" ) == 0 ) && ( strcmp( fwport->protocol.get(), "udp" ) == 0 ) ) continue; ETCSERVICE *etcservice = etcservicelist->getitem( fwport->protocol.get(), fwport->port); char port[10]; snprintf( port, sizeof(port), "%d", fwport->port ); const char *service = ""; if ( etcservice!=NULL) service = etcservice->service_name.get(); else service = port; fprintf( fout, "\t%s -A i_%s -p %s -d $ip/32 %s -j DENY%s;\n", ipchains, internet->name, fwport->protocol.get(), service, log_denied ? " -l" : "" ); } fprintf( fout, "\n\ #\n\ # Input: Internet interface chain (continued)\n\ # - Port %d <= any ports <= port %d (tcp and udp): ACCEPT\n\ #\n\ ", port_low, port_high ); fprintf( fout, "\t%s -A i_%s -p %s -d $ip/32 %d:%d -j ACCEPT;\n", ipchains, internet->name, "tcp", port_low, port_high ); fprintf( fout, "\t%s -A i_%s -p %s -d $ip/32 %d:%d -j ACCEPT;\n", ipchains, internet->name, "udp", port_low, port_high ); fprintf( fout, "\n\ #\n\ # Input: Internet interface chain (continued)\n\ # - Everything else: DENY\n\ # - Log ?\n\ #\n\ "); fprintf( fout, "\t%s -A i_%s -j DENY%s;\n", ipchains, internet->name, log_denied ? " -l": "" ); fprintf( fout, "\n\ #\n\ # Output:\n\ # - Flush rules\n\ #\n\ "); fprintf( fout, "\t%s -F output;\n", ipchains ); fprintf( fout, "\n\ #\n\ # Output: Internet interface chain (definition)\n\ # - Create internet interface chain (succeeds if missing)\n\ # - Flush rules in internet interface chain\n\ # - Create reference to new chain from output chain\n\ # - Other interfaces: ACCEPT\n\ #\n\ "); // New internet chain fprintf( fout, "\t%s -N o_%s 2>/dev/null;\n", ipchains, internet->name ); fprintf( fout, "\t%s -F o_%s;\n", // Flush internet chain ipchains, internet->name ); // Internet chain reference fprintf( fout, "\t%s -A output -i %s -j o_%s;\n", ipchains, internet->name, internet->name ); fprintf( fout, "\t%s -A output -j ACCEPT;\n", ipchains ); if ( internet->deny_icmp_time_exceeded ) { fprintf( fout, "\n\ #\n\ # Output: Internet interface chain\n\ # - Traceroute (or the response to them): DENY\n\ #\n\ "); fprintf( fout, "\t%s -A o_%s -s $ip/32 -p icmp --icmp-type time-exceeded -j DENY%s;\n", ipchains, internet->name, log_denied ? " -l": "" ); } fprintf( fout, "\n\ #\n\ # Output: Internet interface chain\n\ # - Source equal interface ip address: ACCEPT\n\ # - Everything else (spoofed!): DENY\n\ # - Log ?\n\ #\n\ "); fprintf( fout, "\t%s -A o_%s -s $ip/32 -j ACCEPT;\n", ipchains, internet->name ); fprintf( fout, "\t%s -A o_%s -j DENY%s;\n", ipchains, internet->name, log_denied ? " -l": "" ); fprintf( fout, "}\n" ); fprintf( fout, "\n" ); fprintf( fout, "\n" ); fprintf( fout, "stop_firewall() {\n" ); fprintf( fout, "\n\ #\n\ # Stop firewall\n\ # This function is supposed to remove all rules inserted\n\ # by this firewall script.\n\ #\n\ "); fprintf( fout, "\n\ #\n\ # Input:\n\ # - flush all rules\n\ #\n\ "); fprintf( fout, "\t%s -F input;\n", ipchains ); fprintf( fout, "\n\ #\n\ # Input:\n\ # - internet interface chain removed\n\ #\n\ "); fprintf( fout, "\t%s -F i_%s;\n", // Flush input internet chain ipchains, internet->name ); fprintf( fout, "\t%s -X i_%s;\n", // Delete input internet chain ipchains, internet->name ); fprintf( fout, "\n\ #\n\ # Output:\n\ # - flush all rules\n\ #\n\ "); fprintf( fout, "\t%s -F output;\n", ipchains ); fprintf( fout, "\n\ #\n\ # Output:\n\ # - internet interface chain removed\n\ #\n\ "); fprintf( fout, "\t%s -F o_%s;\n", // Flush output internet chain ipchains, internet->name ); fprintf( fout, "\t%s -X o_%s;\n", // Delete output internet chain ipchains, internet->name ); fprintf( fout, "}\n" ); fprintf( fout, "\n" ); fprintf( fout, "\n" ); fprintf( fout, "case $command in\n" ); fprintf( fout, "\tstart)\n" ); fprintf( fout, "\t\tcase $network_device in\n" ); fprintf( fout, "\t\t\t%s)\n", internet->name ); fprintf( fout, "\t\t\t\tstart_firewall;\n" ); fprintf( fout, "\t\t\t\t;;\n" ); fprintf( fout, "\t\tesac\n" ); fprintf( fout, "\t\t;;\n" ); fprintf( fout, "\tstatus)\n" ); fprintf( fout, "\t\t%s -L -v;\n", ipchains ); fprintf( fout, "\t\t;;\n" ); fprintf( fout, "\tstop)\n" ); fprintf( fout, "\t\tcase $network_device in\n" ); fprintf( fout, "\t\t\t%s)\n", internet->name ); fprintf( fout, "\t\t\t\tstop_firewall;\n" ); fprintf( fout, "\t\t\t\t;;\n" ); fprintf( fout, "\t\tesac\n" ); fprintf( fout, "\t\t;;\n" ); fprintf( fout, "\t*)\n" ); fprintf( fout, "\t\techo \"Usage: $0 {start %s ip|stop %s|status}\"\n", internet->name, internet->name ); fprintf( fout, "\t\texit 1\n" ); fprintf( fout, "\t;;\n" ); fprintf( fout, "esac\n" ); fprintf( fout, "exit 0\n" ); return( fclose( fout ) ); } PRIVATE void FW::check_status( ) { if ( active == 0 ) { xconf_notice( MSG_U(I_SCRIPT_CREATED, "Executable script (%s) has been created.\n" "This script should be executed when the internet interface %s is brought up.\n" "\n" "For a dynamic ip address start it by (in %s):\n" "%s start $1 $4\n" "\n" "or for a static ip address in a rc-script:\n" "%s start %s %s\n" ), f_script_file.getpath(), internet->name, ETC_PPP_IPUP, f_script_file.getpath(), f_script_file.getpath(), internet->name, internet->ip_alfa ); } } PRIVATE void FW::append_to_dialog( DIALOG *dia, FWPORT *fwport ) { ETCSERVICE *etcservice = etcservicelist->getitem( fwport->protocol.get(), fwport->port); const char *service = ""; if ( etcservice != NULL ) { service = etcservice->service_name.get(); } char port[10]; if ( strcmp( service, "ftp") == 0 ) { sprintf( port, "%d-%d", fwport->port-1, fwport->port ); } else { sprintf( port, "%d", fwport->port); } char text[100]; snprintf( text, sizeof( text ), "%s/%s %s %s:%d %s %s", port, service, MSG_U(T_IN,"in"), fwport->program.get(), fwport->pid, MSG_U(T_BY,"by"), fwport->user.get() ); dia->newf_chk( "", fwport->accept, text); } PUBLIC int FW::edit( void ) { //fprintf(stderr,"FW::edit: inferface=%s ip=%s fwportlist->getnb()=%d\n",internet->name, internet->ip_alfa, fwportlist->getnb()); DIALOG dia; dia.newf_title (MSG_U(T_BASICFWINFO,"Basic information") ,1,"",MSG_R(T_BASICFWINFO)); dia.newf_chk( MSG_U(F_ENABLE_FIREWALL,"Firewall daemon"), active, MSG_U(F_ACTIVE,"Active" ) ); { static const char *frequency_use[]={ MSG_U(F_POLL_1,"Once"), MSG_U(F_POLL_10,"Ten times"), MSG_U(F_POLL_100,"One hundred"), NULL }; dia.newf_chkm (MSG_U(F_CHECKACTION,"Polls per second"), frequency, frequency_use); } { static const char *details_use[]={ MSG_U(F_DETAILS_NONE,"None"), MSG_U(F_DETAILS_NORMAL,"Normal"), MSG_U(F_DETAILS_MANY,"Detailed"), NULL }; dia.newf_chkm (MSG_U(F_DAEMON_DETAILS,"System log"), details, details_use); } dia.newf_info( MSG_U(F_IP_FORWARD, "Kernel ip forward"), ip_forward?MSG_U(F_YES,"Yes"):MSG_U(F_NO,"No") ); dia.newf_info( MSG_U(F_IP_DYNADDR, "Kernel dynamic ip"), ip_forward?MSG_R(F_YES):MSG_R(F_NO) ); dia.newf_title (MSG_U(T_INTERNET,"Internet") ,1,"",MSG_R(T_INTERNET)); dia.newf_title ("",MSG_U(T_ALLOWED_SERVICES, "Allowed services from the internet")); dia.newf_title( MSG_U(T_INTERNET_INFO,"Basic information") ,2,"",MSG_R(T_INTERNET_INFO)); dia.newf_chk( MSG_U(F_LOG_DENIED,"Log denied packets"), log_denied, "" ); dia.newf_info( MSG_U(F_INTERNET_INTERFACE, "Interface"), internet->name ); dia.newf_info( MSG_U(F_INTERNET_IP, "IP address"), internet->ip_alfa ); dia.newf_info( MSG_U(F_NETWORK_MASK, "Network mask"),internet->netmask_alfa); dia.newf_title( MSG_U(T_ACTIVE_SERVICES_TCP,"TCP Services") ,2,"",MSG_R(T_ACTIVE_SERVICES_TCP)); for (int i=0; igetnb(); i++ ) { FWPORT *fwport = fwportlist->getitem( i ); if ( fwport->protocol.cmp( "tcp" ) == 0 ) { append_to_dialog( &dia, fwport ); } } dia.newf_title( MSG_U(T_ACTIVE_SERVICES_UDP,"UDP Services") ,2,"",MSG_R(T_ACTIVE_SERVICES_UDP)); for (int i=0; igetnb(); i++ ) { FWPORT *fwport = fwportlist->getitem( i ); if ( fwport->protocol.cmp( "udp" ) == 0 ) { append_to_dialog( &dia, fwport ); } } dia.newf_title( MSG_U(T_INTERNET_ADVANCED,"Advanced") ,2,"",MSG_R(T_INTERNET_ADVANCED)); dia.newf_chk( "", internet->deny_icmp_echo_request, MSG_U(F_PING_DENY,"Deny ping requests")); dia.newf_chk( "", internet->deny_icmp_time_exceeded, MSG_U(F_TRACEROUTE_DENY,"Deny traceroute response")); for ( NETDEVICE ifn=netdevice[0]; ifn; ifn=ifn->next) { if ( ifn->status_if == STATUS_IF_DOWN ) continue; if ( ifn == internet ) continue; dia.newf_title ( ifn->name,1,"",ifn->name); dia.newf_info( MSG_U(I_INTERFACE, "Full access to interface"), ifn->name ); dia.newf_info( MSG_U(F_NETWORK_ADDRESS, "Interface address"), ifn->ip_alfa); dia.newf_info( MSG_R(F_NETWORK_MASK), ifn->netmask_alfa); dia.newf_info( MSG_U(F_MASQERADED_NETWORK, "Masqueraded network"), (ifn->RFC1918 && ip_forward) ? MSG_R(F_YES) : MSG_R(F_NO) ); } //fprintf(stderr,"FW::edit: OK\n"); int ret = 0; int choice = 0; while (1) { MENU_STATUS code = dia.edit( MSG_U(T_FIREWALL, "Internet firewall") ,MSG_U(I_FIREWALL, "This firewall for internet interface blocks every connection unless it is\n" "allowed in this dialog." ) ,help_firewall ,choice ,(MENUBUT_CANCEL|MENUBUT_ACCEPT) ); if (code == MENU_CANCEL || code == MENU_ESCAPE){ ret = -1; break; }else if (code == MENU_ACCEPT ) { if ( input_error( ) ) { continue; } ret = write( ); if ( ret == 0 ) check_status(); break; } } return ret; } PUBLIC int FW::input_error( void ) { if ( local_interfaces && ip_forward == 0 ) { xconf_notice( MSG_U(E_IP_FORWARD, "Forwarding of ip traffic is not active in\n" "the kernel. This is not needed for the\n" "firewall but you may not reach the internet\n" "from a local network.\n") ); } return( 0 ); } PUBLIC void firewall_edit( ) { FW fw; if ( fw.firewall_setup( ) != 0 ) { fw.edit( ); } } /* * Command line: Enable firewall */ PUBLIC void firewall_enable( int argc, char *service[] ) { FW *fw = new FW( ); if ( fw->firewall_setup( ) == 0 ) { delete fw; return; } fw->active = K_ACTIVE_YES; fw->frequency = K_FREQUENCY_10; fw->details = K_DETAILS_NORMAL; fw->log_denied = K_LOG_DENIED_YES; while ( argc-- ) { } fw->write( ); delete fw; } /* * Command line: Disable firewall */ PUBLIC void firewall_disable( ) { FW *fw = new FW( ); if ( fw->firewall_setup( ) != 0 ) { fw->active = K_ACTIVE_NO; fw->write( ); } delete fw; } /* * DAEMON_FIREWALL */ class PROC; class DAEMON_FIREWALL { PROC *myProcess; private: public: DAEMON_FIREWALL(); PROC *getdaemonprocess( void ); int killdaemon( void ); int startdaemon( void ); }; PUBLIC int firewall_probe(int level, int target, int simulation ) { //fprintf(stderr,"firewall_probe\n"); char active = 0; DAEMON_FIREWALL myFirewall; active = (char)linuxconf_getvalnum( K_FIREWALL, K_ACTIVE, K_ACTIVE_NO ); if ( active == 0 && previous_active == 0 ) { return( 0 ); } //fprintf(stderr,"firewall_probe active=%d\n", (int)active ); switch ( active ) { case 0: myFirewall.killdaemon(); break; case 1: myFirewall.startdaemon( ); break; } if ( ! simulation ) previous_active = (int)active; return( 0 ); } /* * class DAEMON_FIREWALL */ PUBLIC DAEMON_FIREWALL::DAEMON_FIREWALL() { //fprintf(stderr,"DAEMON_FIREWALL::DAEMON_FIREWALL()\n"); myProcess = getdaemonprocess(); } PUBLIC PROC *DAEMON_FIREWALL::getdaemonprocess() { //fprintf(stderr,"DAEMON_FIREWALL::getdaemonprocess(): "); PROC *myProcess = NULL; char pidpath[PATH_MAX]; sprintf (pidpath,"%s/%s.pid", "/var/run", FIREWALL_DAEMON ); CONFIG_FILE f_pid ( pidpath, help_nil ,CONFIGF_OPTIONAL|CONFIGF_MANAGED ,"root","root",0600); if ( f_pid.exist ()){ myProcess = process_find( FIREWALL_DAEMON, &f_pid); //fprintf(stderr,"found"); } //fprintf(stderr,"\n"); return( myProcess ); } PUBLIC int DAEMON_FIREWALL::killdaemon() { //fprintf(stderr,"DAEMON_FIREWALL::killdaemon(): "); int ret = 0; if (myProcess != NULL){ net_prtlog (NETLOG_CMD,MSG_U(X_KILLFIREWALL ,"Killing firewall deamon\n") ); ret = myProcess->kill( SIGQUIT ); //fprintf(stderr,"killed"); } //fprintf(stderr,"\n"); return( ret ); } PUBLIC int DAEMON_FIREWALL::startdaemon( ) { //fprintf(stderr,"DAEMON_FIREWALL::startdaemon()\n"); int ret = 0; if (myProcess != NULL){ return( ret ); } /* * Not running: Start firewall */ DAEMON_INTERNAL *myDaemon = daemon_find(FIREWALL_DAEMON); if ( ! myDaemon->is_managed() ) { return( ret ); } char cmd[500]; sprintf(cmd,"%s -d -c %s", myDaemon->getpath(), f_config_file.getpath() ); //fprintf(stderr,"DAEMON_FIREWALL::startdaemon() cmd=%s\n", cmd); netconf_system(5 ,cmd); return ret; } #include static REGISTER_VARIABLE_LOOKUP_MSG fwedit_var_list[]={ {"firewall",NULL,P_MSG_R(F_ENABLE_FIREWALL),firewall_edit,NULL}, { NULL, NULL, NULL, NULL } }; static REGISTER_VARIABLES fwedit_registry("inetdconf",fwedit_var_list);