#include #include #include #include #include #include #include #include #include #include #include "inetdconf.h" #include "inetdconf.m" #include "inetdconfedit.h" #define FILE_PATH_HOSTS_ALLOW 1 #define FILE_PATH_HOSTS_DENY 2 class MYDATA { private: public: int filepath; CONFIG_FILE *f_config_file; // /etc/hosts.allow or /etc/hosts.deny long modified_time; bool config_file_modified; INETDCONFLIST *inetdconflist; public: MYDATA( int path, CONFIG_FILE *f ); ~MYDATA( void ); }; PUBLIC MYDATA::MYDATA( int path, CONFIG_FILE *f ) { filepath = path; f_config_file = f; inetdconflist = new INETDCONFLIST(); inetdconflist->read( ); modified_time = 0; config_file_modified = false; } PUBLIC MYDATA::~MYDATA( void ) { delete inetdconflist; inetdconflist = NULL; } class HOSTSALLOW: public ARRAY_OBJ { private: void init (void); int input_error( ); void modify_service( VIEWITEM *item ); public: SSTRING service; // SSTRING add_service; // SSTRING client; // SSTRING command; // SSTRING comment; // bool new_hostsallow; // int hostsallow_line; // Line number in file /etc/hosts.allow /*~PROTOBEG~ HOSTSALLOW */ public: HOSTSALLOW (const char *_service_name); HOSTSALLOW ( void ); int edit( MYDATA *mydata ); int write( int button, MYDATA *mydata ); public: /*~PROTOEND~ HOSTSALLOW */ }; class HOSTSALLOWLIST: public ARRAY { private: char *next_word( char *d, char *s, int size ); void add_service( int line, VIEWITEM *item ); public: /*~PROTOBEG~ HOSTSALLOWLIST */ public: HOSTSALLOWLIST( ); HOSTSALLOW *getitem (const char *id) const; HOSTSALLOW *getitem (int negative) const; void read ( MYDATA *mydata ); int edit ( MYDATA *mydata ); /*~PROTOEND~ HOSTSALLOWLIST */ }; static HELP_FILE help_hostsallow ("inetdconf","hostsallow"); static CONFIG_FILE f_config_file_allow( "/etc/hosts.allow" ,help_hostsallow ,CONFIGF_MANAGED ,"root" ,"root" ,0644 ,subsys_inetdconf); static CONFIG_FILE f_config_file_deny( "/etc/hosts.deny" ,help_hostsallow ,CONFIGF_MANAGED ,"root" ,"root" ,0644 ,subsys_inetdconf); /* * HOSTSALLOW */ #define K_FIELD_SERVICE 1 #define K_FIELD_CLIENT 2 #define K_FIELD_COMMAND 3 PRIVATE void HOSTSALLOW::init() { //fprintf(stderr,"HOSTSALLOW::init\n"); new_hostsallow = 1; } PUBLIC HOSTSALLOW::HOSTSALLOW(const char *_service) { //fprintf(stderr,"HOSTSALLOW::HOSTSALLOW _service=%s\n", _service); service.setfrom (_service); init(); } PUBLIC HOSTSALLOW::HOSTSALLOW( ) { //fprintf(stderr,"HOSTSALLOW::HOSTSALLOW\n"); init(); } PUBLIC int HOSTSALLOW::write( int button, MYDATA *mydata ) { //fprintf(stderr,"HOSTSALLOW::write\n"); int ret = -1; long this_modified_time = file_date( mydata->f_config_file->getpath() ); if ( this_modified_time > mydata->modified_time ) { xconf_error(MSG_R(E_FILE_MODIFIED), mydata->f_config_file->getpath() ); mydata->config_file_modified = true; return( ret ); } VIEWITEMS items; items.setcomcar( '\002' ); // Set comment to "impossible" char items.read( *mydata->f_config_file ); // Read current version of config file if ( new_hostsallow ) { VIEWITEM *item = new VIEWITEM(""); modify_service( item ); items.add( item ); new_hostsallow = false; } else { for ( int line=0; linef_config_file, (PRIVILEGE *)NULL ); /* * Last modified set when config file read or written. */ mydata->modified_time = file_date( mydata->f_config_file->getpath() ); return( ret ); } /** * Update line */ PRIVATE void HOSTSALLOW::modify_service( VIEWITEM *item ) { //fprintf(stderr,"HOSTSALLOW::modify_service: item=%s\n", item->line.get()); char line[2048]; if ( command.is_empty() ) { snprintf( line, sizeof(line), "%s:%s", service.get(), client.get()); } else { snprintf( line, sizeof(line), "%s:%s:%s", service.get(), client.get(), command.get()); } item->line.setfrom( line ); } /** * Edit hostsallow entry */ PUBLIC int HOSTSALLOW::edit( MYDATA *mydata ) { //fprintf(stderr,"HOSTSALLOW::edit\n"); DIALOG dia; { FIELD_COMBO *combo = dia.newf_combo(MSG_U(F_SERVER,"Server"),service); INETDCONF *inetdconf = NULL; SSTRINGS strings; for (int i=0; iinetdconflist->getnb(); i++ ) { inetdconf = mydata->inetdconflist->getitem( i ); if ( inetdconf->server_path.cmp( daemon_findpath( "tcpd" ) ) == 0 ) { SSTRING *service_name = new SSTRING(inetdconf->server_args.get()); strings.add( service_name ); } } strings.add( new SSTRING("ALL") ); strings.sort(); strings.remove_dups(); for (int i=0; iaddopt(strings.getitem(i)->get()); } } { FIELD_COMBO *combo = dia.newf_combo(MSG_U(F_HOSTSALLOWCLIENT,"Client systems"),client); SSTRINGS strings; strings.add( new SSTRING("ALL") ); strings.add( new SSTRING("LOCAL") ); strings.add( new SSTRING("UNKNOWN") ); strings.add( new SSTRING("KNOWN") ); strings.sort(); for (int i=0; iaddopt(strings.getitem(i)->get()); } } dia.newf_str( MSG_U(F_HOSTSALLOWCOMMAND,"Optional command"), command ); int buttons; if ( new_hostsallow ) { buttons = (MENUBUT_CANCEL|MENUBUT_ACCEPT); } else { buttons = (MENUBUT_DEL|MENUBUT_CANCEL|MENUBUT_ACCEPT); } const char *title = NULL; if ( mydata->filepath == FILE_PATH_HOSTS_ALLOW ) { title = MSG_U(T_HOSTSALLOW, "Allowed servers"); } else if ( mydata->filepath == FILE_PATH_HOSTS_DENY ) { title = MSG_U(T_ETCHOSTSDENY, "Denied servers"); } int ret = 0; int choice = 0; while (1){ MENU_STATUS code = dia.edit( title ,"" ,help_hostsallow ,choice ,buttons); if (code == MENU_CANCEL || code == MENU_ESCAPE){ ret = -1; break; }else if (code == MENU_DEL){ if ( xconf_delok() ) { write( MENU_DEL, mydata ); ret = 1; break; } }else if (code == MENU_ACCEPT ) { if ( input_error( ) ) continue; write ( MENU_ACCEPT, mydata ); ret = 0; break; } } return ret; } PRIVATE int HOSTSALLOW::input_error( ) { if ( service.is_empty() ) { xconf_error( MSG_U(E_ALLOWSERVICEMISSING, "Server name is missing") ); return( 1 ); } if ( client.is_empty() ) { xconf_error( MSG_U(E_ALLOWCLIENT, "Client name is missing") ); return( 1 ); } return( 0 ); } /** * HOSTSALLOWLIST */ PUBLIC HOSTSALLOW *HOSTSALLOWLIST::getitem (int no) const { return (HOSTSALLOW*)ARRAY::getitem (no); } PUBLIC HOSTSALLOW *HOSTSALLOWLIST::getitem (const char *_service) const { HOSTSALLOW *ret = NULL; int n = getnb(); for (int i=0; iservice.cmp(_service)==0){ ret = hostsallow; break; } } return ret; } PUBLIC HOSTSALLOWLIST::HOSTSALLOWLIST( ) { //fprintf(stderr,"HOSTSALLOWLIST::HOSTSALLOWLIST\n"); } PRIVATE char * HOSTSALLOWLIST::next_word( char *d, char *s, int size ) { while ( *s ) { switch ( *s ) { case ' ': case ':': case '\t': s++; continue; default: break; } break; } for ( size--; *s && size; size-- ) { switch ( *s ) { case ':': case '\n': *d = '\0'; return( s ); case '#': *d++ = *s++; *d = '\0'; return( s ); default: *d++ = *s++; break; } } *d = '\0'; return( s ); } PUBLIC void HOSTSALLOWLIST::add_service( int line_number, VIEWITEM *item ) { //fprintf(stderr,"hostsallow.cc: add_service: item->line.get()=%s\n", item->line.get()); char word[1024]; char *line = (char *)item->line.get(); char *p = line; if ( *p && *p == '#' ) { return; } if ( strlen( p ) < 3 ) return; HOSTSALLOW *hostsallow = new HOSTSALLOW(); int field = 1; int valid_keywords = 0; while ( 1 ) { p = next_word( word, p, sizeof( word )); if ( strlen( word ) == 0 ) { break; } //fprintf(stderr,"hostsallow.cc: add_service: field=%d word=\"%s\" length=%d\n", field, word, strlen(word)); switch ( field ) { case K_FIELD_SERVICE: hostsallow->service.setfrom( word ); valid_keywords++; field++; break; case K_FIELD_CLIENT: if ( hostsallow->client.is_empty( ) ) { hostsallow->client.setfrom( word ); } else { hostsallow->client.append( " " ); hostsallow->client.append( word ); } field++; valid_keywords++; break; case K_FIELD_COMMAND: if ( hostsallow->command.is_empty( ) ) { hostsallow->command.setfrom( word ); } else { hostsallow->command.append( " " ); hostsallow->command.append( word ); } break; } } if ( valid_keywords > 1 ) { hostsallow->hostsallow_line = line_number; hostsallow->new_hostsallow = false; add( hostsallow ); } else { delete( hostsallow ); } return; } /** * Read config file and parse /etc/hosts.allow or /etc/hosts.deny */ PUBLIC void HOSTSALLOWLIST::read( MYDATA *mydata ) { VIEWITEMS items; items.setcomcar( '\002' ); // Set comment to "impossible" char items.read( *mydata->f_config_file ); // Read config file //fprintf(stderr,"HOSTSALLOWLIST::read items.getnb()=%d\n", items.getnb()); for ( int i=0; imodified_time = file_date( mydata->f_config_file->getpath() ); } /** * Edit hostsallowlist */ PUBLIC int HOSTSALLOWLIST::edit( MYDATA *mydata ) { //fprintf(stderr,"HOSTSALLOWLIST::edit\n"); DIALOG_RECORDS dia; int choice = 0; int ret = -1; dia.newf_head ("",MSG_U(H_HOSTSALLOW,"Service\tClient")); dia.addwhat (MSG_U(I_ADDHOSTSALLOW,"Select [Add] to add a new server\n")); while ( 1 ) { //fprintf(stderr,"HOSTSALLOWLIST::edit: getnb()=%d dia.getnb()=%d\n", getnb(),dia.getnb()); for (int i=0; iservice.get(), hostsallow->client.get()); dia.set_menuitem( i, hostsallow->service.get(), hostsallow->client.get()); } const char *heading = NULL; const char *title = NULL; if ( mydata->filepath == FILE_PATH_HOSTS_ALLOW ) { title = MSG_U(T_HOSTSALLOWLIST,"Allowed servers"); heading = MSG_U(I_HOSTSALLOWLIST, "This is a list of all servers which\n" "presently are allowed in the system.\n" ); } else if ( mydata->filepath == FILE_PATH_HOSTS_DENY ) { title = MSG_U(T_ETCHOSTSDENYLIST,"Denied servers"); heading = MSG_U(I_ETCHOSTSDENYLIST, "This is a list of all servers which\n" "presently are denied in the system.\n" ); } MENU_STATUS code = dia.editmenu (title ,heading ,help_hostsallow ,choice,MENUBUT_ADD); if (code == MENU_QUIT || code == MENU_ESCAPE) { break; } if ( ! perm_rootaccess("modify server access" ) ) { continue; } if (code == MENU_ADD) { HOSTSALLOW *hostsallow = new HOSTSALLOW(); ret = hostsallow->edit( mydata ); if ( ret == 0 ) { add( hostsallow ); } else if ( ret == -1 ) { delete hostsallow; } } else if ( code == MENU_OK ) { HOSTSALLOW *hostsallow = getitem( choice ); ret = hostsallow->edit( mydata ); if ( ret == 1 ) { remove_del( choice ); dia.remove_del( choice ); } } /* * ret = 1: Delete * ret = 0: Accept * ret = -1: Cancel */ } return ret; } PUBLIC void hostsallow_edit( void ) { MYDATA mydata( FILE_PATH_HOSTS_ALLOW, &f_config_file_allow ); HOSTSALLOWLIST hostsallowlist; hostsallowlist.read( &mydata ); hostsallowlist.edit( &mydata ); } PUBLIC void hostsdeny_edit( void ) { MYDATA mydata( FILE_PATH_HOSTS_DENY, &f_config_file_deny ); HOSTSALLOWLIST hostsallowlist; hostsallowlist.read( &mydata ); hostsallowlist.edit( &mydata ); }