#pragma implementation #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "inetdconf.h" #include "inetdconf.m" #include "inetdconfedit.h" #include "etcservice.h" #include "etcprotocol.h" #include "../module_apis/package_api.h" static LINUXCONF_SUBSYS subb (subsys_inetdconf,P_MSG_U(T_INETD, "Internet super server" )); static char *xinetd_conf = "/etc/xinetd.conf"; static char *inetd_conf = "/etc/inetd.conf"; PUBLIC bool xinetd_conf_flag = false; char *which_config_file() { xinetd_conf_flag = false; struct stat statbuf; if ( stat( xinetd_conf, &statbuf ) == 0 ) { xinetd_conf_flag = true; return( xinetd_conf ); } return( inetd_conf ); } char *which_help_file() { static char *xinetd_conf_help = "xinetdconf"; static char *inetd_conf_help = "inetdconf"; struct stat statbuf; if ( stat( xinetd_conf, &statbuf ) == 0 ) { return( xinetd_conf_help ); } return( inetd_conf_help ); } static HELP_FILE help_inetdconf (which_help_file(),which_help_file()); static CONFIG_FILE f_config_file( which_config_file() ,help_inetdconf ,CONFIGF_MANAGED ,"root" ,"root" ,0644 ,subsys_inetdconf); static INETDCONFLIST *g_inetdconflist = 0; static ETCSERVICELIST *g_etcservicelist = 0; static ETCPROTOCOLLIST *g_etcprotocollist = 0; static long modified_time = 0; static bool config_file_modified = false; static const char * next_word(char *d, const char *s, int size) { while ( *s ) { switch ( *s ) { case ' ': case '\t': case '\n': s++; continue; default: break; } break; } for ( size--; *s && size; size-- ) { switch ( *s ) { case ' ': case '\t': case '\n': *d = '\0'; return( s ); default: *d++ = *s++; break; } } *d = '\0'; return( s ); } /* * One line of input: First word in a, second in o and the rest are * put in v. */ static void next_attribute(char *a, char *o, char *v, const char *s, int size_a, int size_o, int size_v) { char word[128]; *v = '\0'; *o = '\0'; const char *p = next_word( word, s, sizeof(word) ); strncpy(a,word,size_a); // Attribute if ( ! *p ) return; // Only one word in line p = next_word( word, p, sizeof(word) ); strncpy(o,word,size_o); // Operator if ( ! *p ) return; // Only two words in line for ( int i=0; *p && imy_xinetdefaults==0 ) return ret; if ( previous_enabled == enabled ) return ret; previous_enabled = enabled; FILE_CFG *fpr, *fpw; if ( (fpr=f_config_file.fopen("r"))==NULL) return ret; if ( (fpw=f_config_file.fopen("w"))==NULL) return ret; char buffer[1024]; int token = 1; //fprintf(stderr,"set_enabled_disabled: file=%s service_name=%s\n",f_config_file.getpath(),service_name.get()); while (fgets( buffer, sizeof(buffer), fpr) != NULL ) { const char *p = buffer; next_attribute( myAttribute, myOperator,myValue,p, sizeof(myAttribute),sizeof(myOperator),sizeof(myValue)); switch ( token ) { case 1: if ( strcmp(myAttribute,"defaults" ) == 0) token = 2; break; case 2: if ( strcmp(myAttribute,"{" ) == 0) token = 3; break; case 3: if ( strcmp(myAttribute,"disabled" ) == 0) { //fprintf(stderr,"set_enabled_disabled: disabled found: myValue=%s enabled=%d\n",myValue, (int)enabled); if ( word_present( myValue, service_name.get() )) { if (enabled) { word_remove( myValue,service_name.get() ); if (strlen(myValue)) { //fprintf(stderr," Disabled previously: Now enabled: myValue=%s\n",myValue); snprintf(buffer,sizeof(buffer),"\tdisabled\t\t= %s\n", myValue); } else { continue; } } } else { if (!enabled) { //fprintf(stderr," Enabled previously: Now disabled: myValue=%s\n",myValue); snprintf(buffer,sizeof(buffer),"\tdisabled\t\t= %s %s\n", myValue,service_name.get()); } } token = 4; } else if (strcmp(myAttribute,"}")==0 && !enabled ) { //fprintf(stderr," None enabled previously: Now disabled: service_name.get()=%s\n",service_name.get()); snprintf(buffer,sizeof(buffer),"\tdisabled\t\t= %s\n}\n",service_name.get()); token = 4; } break; case 4: break; } fprintf(fpw,"%s",buffer); } fclose( fpr ); fclose( fpw ); return ret; } PRIVATE int INETDCONF::write_xinetd_service(FILE_CFG *fpw) { char string[1024]; int ret = -1; fprintf(fpw,"service %s\n", service_name.get()); fprintf(fpw,"{\n"); if (multi) put_string( fpw, "wait", "yes" ); else put_string( fpw, "wait", "no" ); put_integer(fpw, "instances", max ); put_integer(fpw, "port", port ); put_integer(fpw, "nice", nice ); snprintf(string,sizeof(string),"%s%s%s", type_rpc?" RPC":"", type_internal?" INTERNAL":"", type_unlisted?" UNLISTED":""); put_string( fpw, "type", string); snprintf(string,sizeof(string),"%s%s%s%s", flags_reuse?" REUSE":"", flags_intercept?" INTERCEPT":"", flags_noretry?" NORETRY":"", flags_idonly?" IDONLY":""); put_string( fpw, "flags", string); put_string( fpw, "socket_type", socket_type.get() ); put_string( fpw, "protocol", protocol.get() ); put_string( fpw, "bind", interface.get() ); put_string( fpw, "only_from", only_from.get() ); put_string( fpw, "no_access", no_access.get() ); put_string( fpw, "access_times", access_times.get() ); put_string( fpw, "user", user.get() ); put_string( fpw, "group", group.get() ); put_string( fpw, "server", server_path.get() ); put_string( fpw, "server_args", server_args.get() ); put_string( fpw, "disable", enabled ? "no" : "yes"); switch (log_type_flag) { case 0: break; case 1: // SYSLOG snprintf(string,sizeof(string),"%s %s %s", "SYSLOG", log_facility.get(), log_level.get()); put_string( fpw, "log_type", string); break; case 2: // FILE snprintf(string,sizeof(string),"%s %s %d %d", "FILE", log_file.get(), log_softlimit, log_hardlimit); put_string( fpw, "log_type", string ); break; } if ( log_type_flag ) { snprintf(string,sizeof(string),"%s%s%s%s%s", log_on_success_pid?" PID":"", log_on_success_host?" HOST":"", log_on_success_userid?" USERID":"", log_on_success_exit?" EXIT":"", log_on_success_duration?" DURATION":""); put_string( fpw, "log_on_success", string ); snprintf(string,sizeof(string),"%s%s%s%s", log_on_failure_host?" HOST":"", log_on_failure_userid?" USERID":"", log_on_failure_attempt?" ATTEMPT":"", log_on_failure_record?" RECORD":""); put_string( fpw, "log_on_failure", string ); } put_string( fpw, "rpc_version", rpc_version.get() ); put_string( fpw, "rpc_number", rpc_number.get() ); put_string( fpw, "env", env.get() ); put_string( fpw, "passenv", passenv.get() ); fprintf(fpw,"}\n"); return ret; } PRIVATE void INETDCONF::put_string(FILE_CFG *fpw, const char *attribute, const char *value) { const char *p = value; while ( *p == ' ' ) p++; if ( strcmp(p,syslog_default)==0) { return; } if ( strlen(p)) if (strlen(attribute)>7) fprintf(fpw,"\t%s\t= %s\n", attribute, p); else fprintf(fpw,"\t%s\t\t= %s\n", attribute, p); } PRIVATE void INETDCONF::put_integer(FILE_CFG *fpw, const char *attribute, int value) { if ( value ) if (strlen(attribute)>7) fprintf(fpw,"\t%s =\t%d\n", attribute, value); else fprintf(fpw,"\t%s\t\t= %d\n", attribute, value); } PRIVATE int INETDCONF::write_inetd( int button ) { //fprintf(stderr,"INETDCONF::write_inetd\n"); int ret = -1; long this_modified_time = file_date( f_config_file.getpath() ); if ( this_modified_time > modified_time ) { xconf_error(MSG_U(E_FILE_MODIFIED, "Config file %s has been modified recently\n" "by someone else. The list of records in the\n" "module may be incorrect.\n" "\n" "This update can not be done.\n" ), f_config_file.getpath() ); config_file_modified = true; return( ret ); } VIEWITEMS items; items.setcomcar( '\002' ); // Set comment to "impossible" char items.read( f_config_file ); // Read current version of config file if ( new_inetdconf ) { VIEWITEM *item = new VIEWITEM(""); inetdconf_line = items.getnb(); inetd_modify_service( item ); items.add( item ); } else { for ( int line=0; lineline.get()); char line[2048]; char multiple[100]; char user_group[100]; if ( max ) { snprintf( multiple, sizeof(multiple),"%s.%d", multi?"wait":"nowait", max ); } else { snprintf( multiple, sizeof(multiple),"%s", multi?"wait":"nowait" ); } if ( group.is_empty() ) { snprintf( user_group, sizeof(user_group),"%s", user.get() ); } else { snprintf( user_group, sizeof(user_group),"%s.%s", user.get(), group.get() ); } snprintf( line, sizeof(line), "%s%s\t%s\t%s\t%s\t%s\t%s\t%s", enabled?"":"#", service_name.get(), socket_type.get(), protocol.get(), multiple, user_group, server_path.get(), server_args.get() ); item->line.setfrom( line ); } /** * Edit inetdconf entry */ PUBLIC int INETDCONF::edit( INETDCONFLIST *list ) { g_inetdconflist = list; return( edit( ) ); } PRIVATE void INETDCONF::set_attribute_type( ) { //fprintf(stderr,"set_attribute_type: %s\n", type.get()); char word[128]; const char *p = type.get(); while ( *p ) { p = next_word( word, p, sizeof( word )); if (strlen(word)) { if (strcmp(word,"RPC") == 0 ) type_rpc = 1; else if (strcmp(word,"INTERNAL") == 0 ) type_internal = 1; else if (strcmp(word,"UNLISTED") == 0 ) type_unlisted = 1; } } } PRIVATE void INETDCONF::set_attribute_flags( ) { //fprintf(stderr,"set_attribute_flags: %s\n", flags.get()); char word[128]; const char *p = flags.get(); while ( *p ) { p = next_word( word, p, sizeof( word )); if (strlen(word)) { if (strcmp(word,"REUSE") == 0 ) flags_reuse = 1; else if (strcmp(word,"INTERCEPT") == 0 ) flags_intercept = 1; else if (strcmp(word,"NORETRY") == 0 ) flags_noretry = 1; else if (strcmp(word,"IDONLY") == 0 ) flags_idonly = 1; } } } PRIVATE void INETDCONF::set_attribute_log_type( ) { //fprintf(stderr,"set_attribute_log_type: %s\n", log_type.get()); char word[128]; const char *p = log_type.get(); p = next_word( word, p, sizeof( word )); // log_type = "SYSLOG" | "FILE" if (strcmp(word,"SYSLOG") == 0 ) { log_type_flag = 1; // "SYSLOG" p = next_word( word, p, sizeof( word )); if (strlen(word)) { log_facility.setfrom(word); p = next_word( word, p, sizeof( word )); // level if (strlen(word)) { log_level.setfrom(word); } } } else if (strcmp(word,"FILE") == 0 ) { log_type_flag = 2; // "FILE" p = next_word( word, p, sizeof( word )); if (strlen(word)) { log_file.setfrom(word); // file name p = next_word( word, p, sizeof( word )); if (strlen(word)) { log_softlimit = atoi(word); // soft limit p = next_word( word, p, sizeof( word )); if (strlen(word)) { log_hardlimit = atoi(word); // hard limit } } } } } PRIVATE void INETDCONF::set_attribute_log_on_success( ) { //fprintf(stderr,"set_attribute_log_on_success: %s\n", log_on_success.get()); char word[128]; const char *p = log_on_success.get(); while ( *p ) { p = next_word( word, p, sizeof( word )); if (strlen(word)) { if (strcmp(word,"PID") == 0 ) log_on_success_pid = 1; else if (strcmp(word,"HOST") == 0 ) log_on_success_host = 1; else if (strcmp(word,"USERID") == 0 ) log_on_success_userid = 1; else if (strcmp(word,"EXIT") == 0 ) log_on_success_exit = 1; else if (strcmp(word,"DURATION") == 0 ) log_on_success_duration = 1; } } } PRIVATE void INETDCONF::set_attribute_log_on_failure( ) { //fprintf(stderr,"set_attribute_log_on_failure: %s\n", log_on_failure.get()); char word[128]; const char *p = log_on_failure.get(); while ( *p ) { p = next_word( word, p, sizeof( word )); if (strlen(word)) { if (strcmp(word,"HOST") == 0 ) log_on_failure_host = 1; else if (strcmp(word,"USERID") == 0 ) log_on_failure_userid = 1; else if (strcmp(word,"ATTEMPT") == 0 ) log_on_failure_attempt = 1; else if (strcmp(word,"RECORD") == 0 ) log_on_failure_record = 1; } } } PRIVATE void INETDCONF::add_xinetd_extensions( DIALOG *dia ) { set_attribute_type(); set_attribute_flags(); set_attribute_log_type(); set_attribute_log_on_success(); set_attribute_log_on_failure(); { dia->newf_title (MSG_U(T_SECURITY,"Security"),1, "",MSG_R(T_SECURITY)); dia->newf_str( MSG_U(F_INTERFACE,"Interface/bind"), interface ); dia->newf_str( MSG_U(F_ONLY_FROM,"Only accept from"), only_from ); dia->newf_str( MSG_U(F_NO_ACCESS,"No access from"), no_access ); dia->newf_str( MSG_U(F_ACCESS_TIMES,"Access time (hh:mm-hh:mm)"), access_times ); } { dia->newf_chk ("",flags_intercept, MSG_U(F_FLAGS_INTERCEPT, "Intercept packages")); dia->newf_chk ("",flags_idonly, MSG_U(F_FLAGS_IDONLY, "Require identification")); } dia->newf_title (MSG_U(T_LOG,"Log"),1,"",MSG_R(T_LOG)); { static const char *log_type_use[]={ MSG_U(F_LOG_TYPE_DEFAULT,"Default"), MSG_U(F_LOG_TYPE_SYSLOG,"To syslog"), MSG_U(F_LOG_TYPE_FILE,"To file"), NULL }; dia->newf_chkm (MSG_U(F_LOG_TYPE,"Log type"), log_type_flag,log_type_use); } { dia->newf_title (MSG_U(T_LOG_TYPE_SYSLOG,"Syslog"),2, "",MSG_R(T_LOG_TYPE_SYSLOG)); } { if (log_facility.is_empty()) { log_facility = syslog_default; } FIELD_LIST *combo = dia->newf_list(MSG_U(F_SYSLOG_FACILITY ,"Facility"),log_facility); combo->addopt(syslog_default,MSG_U(F_SYSLOG_DEFAULT,"Default")); combo->addopt("daemon",MSG_U(F_SYSLOG_DAEMON,"Daemon")); combo->addopt("auth",MSG_U(F_SYSLOG_AUTH,"Auth")); combo->addopt("user",MSG_U(F_SYSLOG_USER,"User")); combo->addopt("local0",MSG_U(F_SYSLOG_LOCAL0,"Local0")); combo->addopt("local1",MSG_U(F_SYSLOG_LOCAL1,"Local1")); combo->addopt("local2",MSG_U(F_SYSLOG_LOCAL2,"Local2")); combo->addopt("local3",MSG_U(F_SYSLOG_LOCAL3,"Local3")); combo->addopt("local4",MSG_U(F_SYSLOG_LOCAL4,"Local4")); combo->addopt("local5",MSG_U(F_SYSLOG_LOCAL5,"Local5")); combo->addopt("local6",MSG_U(F_SYSLOG_LOCAL6,"Local6")); combo->addopt("local7",MSG_U(F_SYSLOG_LOCAL7,"Local7")); } { if (log_level.is_empty()) { log_facility = syslog_default; } FIELD_LIST *combo = dia->newf_list(MSG_U(F_SYSLOG_LEVEL ,"Level"),log_level); combo->addopt(syslog_default,MSG_R(F_SYSLOG_DEFAULT)); combo->addopt("emerg",MSG_U(F_SYSLOG_EMERG,"Emergency")); combo->addopt("alert",MSG_U(F_SYSLOG_ALERT,"Alert")); combo->addopt("crit",MSG_U(F_SYSLOG_CRIT,"Critical")); combo->addopt("err",MSG_U(F_SYSLOG_ERR,"Error")); combo->addopt("warning",MSG_U(F_SYSLOG_WARNING,"Warning")); combo->addopt("notice",MSG_U(F_SYSLOG_NOTICE,"Notice")); combo->addopt("info",MSG_U(F_SYSLOG_INFO,"Info")); combo->addopt("debug",MSG_U(F_SYSLOG_DEBUG,"Debug")); } { dia->newf_title (MSG_U(T_LOG_TYPE_FILE,"File"),2, "",MSG_R(T_LOG_TYPE_FILE)); } dia->newf_str( MSG_U(F_SYSLOG_FILE,"File name"), log_file ); { static const char *tbmsg[]={ MSG_U(F_SOFTDEFAULT,"Default"),NULL}; static int tbv[]={0,0}; dia->newf_chkm_num( MSG_U(F_SOFTLIMIT, "Soft limit"),log_softlimit,tbv,tbmsg); } { static const char *tbmsg[]={ MSG_U(F_HARDDEFAULT,"Default"),NULL}; static int tbv[]={0,0}; dia->newf_chkm_num( MSG_U(F_HARDLIMIT, "Hard limit"),log_hardlimit,tbv,tbmsg); } { dia->newf_title (MSG_U(T_LOG_ON_SUCCESS,"On success"),2, "",MSG_R(T_LOG_ON_SUCCESS)); dia->newf_chk ("",log_on_success_pid, MSG_U(F_LOG_ON_SUCCESS_PID, "Process id")); dia->newf_chk ("",log_on_success_host, MSG_U(F_LOG_ON_SUCCESS_HOST, "Remote host address")); dia->newf_chk ("",log_on_success_userid, MSG_U(F_LOG_ON_SUCCESS_USERID, "Remote host user id")); dia->newf_chk ("",log_on_success_exit, MSG_U(F_LOG_ON_SUCCESS_EXIT, "Server exit status")); dia->newf_chk ("",log_on_success_duration, MSG_U(F_LOG_ON_SUCCESS_DURATION, "Session duration")); } { dia->newf_title (MSG_U(T_LOG_ON_FAILURE,"On failure"),2, "",MSG_R(T_LOG_ON_FAILURE)); dia->newf_chk ("",log_on_failure_host, MSG_R(F_LOG_ON_SUCCESS_HOST)); dia->newf_chk ("",log_on_failure_userid, MSG_R(F_LOG_ON_SUCCESS_USERID)); dia->newf_chk ("",log_on_failure_attempt, MSG_U(F_LOG_ON_FAILURE_ATTEMPT, "Failed attempts")); dia->newf_chk ("",log_on_failure_record, MSG_U(F_LOG_ON_FAILURE_RECORD, "Record information")); } dia->newf_title (MSG_U(T_ADVANCED,"Advanced"),1, "",MSG_R(T_ADVANCED)); { dia->newf_chk ("",type_rpc, MSG_U(F_TYPE_RPC, "RPC Service")); dia->newf_chk ("",type_internal, MSG_U(F_TYPE_INTERNAL, "Internal service")); dia->newf_chk ("",type_unlisted, MSG_U(F_TYPE_UNLISTED, "Unlisted service")); } { static const char *tbmsg[]={ MSG_U(F_NICEDEFAULT,"Default"),NULL}; static int tbv[]={0,0}; dia->newf_chkm_num( MSG_U(F_NICE, "Priority (-20 to +19)"),nice,tbv,tbmsg); } { dia->newf_chk ("",flags_reuse, MSG_U(F_FLAGS_REUSE, "Reuse socket address")); dia->newf_chk ("",flags_noretry, MSG_U(F_FLAGS_NORETRY, "Do not retry")); } } PUBLIC int INETDCONF::edit() { //fprintf(stderr,"INETDCONF::edit_inetd\n"); DIALOG dia; if ( xinetd_conf_flag ) { dia.newf_title (MSG_U(T_STANDARD,"Basics"),1,"",MSG_R(T_STANDARD)); } if ( new_inetdconf ) { FIELD_COMBO *combo = dia.newf_combo(MSG_U(F_SERVICES ,"Service name"),service_name); ETCSERVICE *etcservice = 0; SSTRINGS strings; for (int i=0; igetnb(); i++ ) { etcservice = g_etcservicelist->getitem( i ); SSTRING *service = new SSTRING(etcservice->service_name.get()); strings.add( service ); } strings.sort(); strings.remove_dups(); for (int i=0; iaddopt(strings.getitem(i)->get()); } } else { dia.newf_info( MSG_R(F_SERVICES), service_name.get() ); /* * The same service can occur on another port with * a different protocol. */ ETCSERVICE *etcservice = 0; SSTRINGS strings; for (int i=0; igetnb(); i++ ) { bool add_service = false; etcservice = g_etcservicelist->getitem( i ); if ( etcservice->service_name.cmp( service_name ) == 0 ) { add_service = true; } else { /* * Service alias may be used.. */ char word[100]; const char *p = etcservice->aliases.get( ); while ( *p ) { p = str_copyword( word, p, sizeof( word ) ); if (strcmp(word, service_name.get()) == 0 ) { add_service = true; } } } if ( add_service ) { char portnumber[10]; snprintf(portnumber,sizeof(portnumber), "%d", etcservice->port); SSTRING *pn = new SSTRING(portnumber); strings.add( pn ); } } strings.sort(); strings.remove_dups(); SSTRING valid_ports; for (int i=0; iget() ); } else { valid_ports.append( "," ); valid_ports.append( strings.getitem(i)->get() ); } } if ( ! valid_ports.is_empty() ) { dia.newf_info( MSG_U(F_ETCSERVICEPORT,"Port"), valid_ports.get() ); } } { static const char *enabled_use[]={ MSG_U(F_DISABLED,"Disabled"), MSG_U(F_ENABLED,"Enabled"), NULL }; dia.newf_chkm (MSG_U(F_STATE,"State"),enabled,enabled_use); } { FIELD_LIST *combo = dia.newf_list(MSG_U(F_PROTOCOLS ,"Protocol"),protocol); if ( new_inetdconf ) { /* * Show all protocols in /etc/protocols */ ETCPROTOCOL *etcprotocol = 0; SSTRINGS strings; for (int i=0; igetnb(); i++ ) { etcprotocol = g_etcprotocollist->getitem( i ); SSTRING *protocol_name = new SSTRING(etcprotocol->protocol_name.get()); strings.add( protocol_name ); } strings.sort(); for (int i=0; iaddopt(strings.getitem(i)->get()); } } else { /* * Find valid protocols for service in /etc/services */ SSTRINGS strings; ETCSERVICE *etcservice = 0; for (int i=0; igetnb(); i++ ) { bool add_service = false; etcservice = g_etcservicelist->getitem( i ); if ( etcservice->service_name.cmp( service_name ) == 0 ) { add_service = true; } else { /* * Service alias may be used.. */ char word[100]; const char *p = etcservice->aliases.get( ); while ( *p ) { p = str_copyword( word, p, sizeof( word ) ); if (strcmp(word, service_name.get()) == 0 ) { add_service = true; } } } if ( add_service ) { SSTRING *service = new SSTRING(etcservice->protocol.get()); strings.add( service ); } } strings.sort(); strings.remove_dups(); for (int i=0; iaddopt(strings.getitem(i)->get()); } } } { ETCPROTOCOL *etcprotocol = 0; etcprotocol = g_etcprotocollist->getitem( protocol.get() ); if ( etcprotocol == 0 ) { etcprotocol = g_etcprotocollist->getitem_alias( protocol.get() ); } if ( etcprotocol != 0 ) { dia.newf_info( MSG_U(F_ETCPROTOCOLCOMMENT,"Protocol description"), etcprotocol->comment.get() ); } } { FIELD_LIST *combo = dia.newf_list(MSG_U(F_SOCKET_TYPE ,"Socket type"),socket_type); combo->addopt ("dgram",MSG_U(F_DATAGRAM,"Datagram")); combo->addopt ("raw",MSG_U(F_RAW,"Raw")); if ( ! xinetd_conf_flag ) { combo->addopt ("rdm",MSG_U(F_RDM,"Reliable delivered message")); } combo->addopt ("seqpacket",MSG_U(F_SEQPACKET,"Sequenced packet socket")); combo->addopt ("stream",MSG_U(F_STREAM,"Stream")); } { static const char *multi_use[]={ MSG_U(F_NO_WAIT,"Yes (nowait)"), MSG_U(F_WAIT,"No (wait)"), NULL }; dia.newf_chkm (MSG_U(F_MULTIPROCESS,"Concurrent processes"),multi,multi_use); } { static const char *tbmsg[]={ MSG_U(F_MAXDEFAULT,"Default"),NULL}; static int tbv[]={0,0}; dia.newf_chkm_num( MSG_U(F_MAX, "Max processes per minute"),max,tbv,tbmsg ); } { USERS users; FIELD_COMBO *usrl = dia.newf_combo ( MSG_U(F_USER,"Run as user") ,user); SSTRINGS names; for (int i=0; igetname()); if ( name->is_empty() ) continue; names.add( name ); } names.sort(); for (int i=0; iaddopt (names.getitem(i)->get()); } } { GROUPS groups; FIELD_COMBO *grpl = dia.newf_combo ( MSG_U(F_GROUP,"Run in group (opt)") ,group); SSTRINGS names; for (int i=0; igetname()); if ( name->is_empty() ) continue; names.add( name ); } names.sort(); for (int i=0; iaddopt (names.getitem(i)->get()); } } { FIELD_COMBO *server_paths = dia.newf_combo ( MSG_U(F_PATH,"Server path"), server_path ); SSTRINGS names; SSTRING *name=new SSTRING("internal"); names.add( name ); name=new SSTRING(daemon_findpath( "tcpd" ) ); names.add( name ); names.sort(); for (int i=0; iaddopt (names.getitem(i)->get()); } } dia.newf_str( MSG_U(F_ARGUMENTS,"Arguments"), server_args ); PACKAGE_API *pkg_api = package_api_init("inetdconf/inetdconfedit.cc"); SSTRING pkg; PACKAGE_VERSION ver; bool pkgfound = false; if ( pkg_api != NULL ) { pkgfound = pkg_api->path2pkg( pkg_api, get_server_path( ), pkg,ver) != -1; } int buttons = 0; if ( pkgfound ) { dia.newf_info( MSG_U(F_PACKAGE,"Package name"), pkg.get( ) ); dia.newf_info( MSG_U(F_PKGVER, "Package version"), ver.str ); dia.setbutinfo(MENU_USR5, MSG_U(B_PKGINFO,"Pkginfo"),MSG_R(B_PKGINFO)); buttons |= MENUBUT_USR5; } else if ( pkg_api == NULL ) { dia.newf_info (MSG_R(F_PACKAGE) ,MSG_U(I_NOMANAGERPM,"(No package manager available)")); } if ( xinetd_conf_flag ) { add_xinetd_extensions( &dia ); } if ( new_inetdconf ) { buttons |= (MENUBUT_CANCEL|MENUBUT_ACCEPT); } else { buttons |= (MENUBUT_DEL|MENUBUT_CANCEL|MENUBUT_ACCEPT); } int ret = 0; int nof = 0; while (1){ MENU_STATUS code = dia.edit( MSG_U(T_INETDCONF, "Internet server") ,"" ,help_inetdconf ,nof ,buttons); if (code == MENU_CANCEL || code == MENU_ESCAPE){ ret = -1; break; } else if (code == MENU_USR5){ pkg_api->showinfo( pkg_api, pkg.get( ) ); } else if (code == MENU_DEL){ if ( xconf_delok() ) { write( MENU_DEL ); ret = 1; break; } } else if (code == MENU_ACCEPT ) { if ( input_error( ) ) continue; write ( MENU_ACCEPT ); ret = 0; break; } } return ret; } PRIVATE void INETDCONF::present( char *buf1, int size1, char *buf2, int size2) { snprintf (buf1,size1-1,"[%s]",enabled ? "X" : " "); snprintf (buf2,size2-1,"%s\t%s\t%d/%s\t%s\t%s" ,service_name.get() ,socket_type.get() ,port ,protocol.get() ,server_path.get() ,server_args.get()); } static const char *inetdconf_basename( const char *name ) { const char *p, *d; for (p=d=name; *p; p++ ) { if ( *p == '/' ) d = ++p; } return( d ); } /* * Find the real path name of the server. */ PRIVATE const char * INETDCONF::get_server_path( ) { static char myServerPath[256]; myServerPath[0] = '\0'; if ( xinetd_conf_flag ) { if (type.cmp("INTERNAL")==0) { return(myServerPath); // Empty } return( server_path.get()); } if ( server_path.cmp("internal") == 0 ) { return(myServerPath); // Empty } if ( strcmp( inetdconf_basename( server_path.get()), "tcpd" ) == 0 ) { //fprintf(stderr,"server_path_error: tcpd: server_path=%s server_args=%s\n", server_path.get(), server_args.get() ); if ( server_args.get()[0] == '/' ) { /* * An absolute path name is allowed as argument to tcpd */ snprintf( myServerPath, sizeof( myServerPath ), "%s", server_args.get() ); } else { snprintf( myServerPath, sizeof( myServerPath ), "%s/%s", configf_lookuppath( REAL_DAEMON_DIR ), server_args.get() ); } } else { snprintf( myServerPath, sizeof( myServerPath ), "%s", server_path.get() ); } for ( int i=0; myServerPath[i]; i++ ) { if ( myServerPath[i] == ' ' ) { myServerPath[i] = '\0'; break; } } return( myServerPath ); } /* * This function is supposed to check whether the path is valid * or not. The problem is that if tcpd is used the path to the server * program need not be specified, only its name. The path is compiled * in to tcpd. So how can this be solved? */ PUBLIC int INETDCONF::server_path_error( char *text, int size ) { text[0] = '\0'; const char *myServerPath = get_server_path( ); //fprintf(stderr,"server_path_error: myServerPath=%s\n", myServerPath ); struct stat statbuf; int value; if ( ( value = stat( myServerPath, &statbuf ) ) == 0 ) { if ( statbuf.st_mode & S_IFDIR ) { snprintf( text, size, MSG_U(E_SERVERPATHDIR, "%s is a directory" ), myServerPath ); return( 1 ); } return( 0 ); } snprintf( text, size, MSG_U(E_SERVERPATHERROR, "%s does not exist" ), myServerPath ); return( 1 ); } PRIVATE int INETDCONF::input_error( ) { if ( server_path.is_empty() ) { xconf_error(MSG_U(E_NOSERVERPATH, "Server path missing") ); return( 1 ); } if ( server_path.cmp( "internal" ) != 0 ) { if ( server_path.get()[0] != '/' ) { xconf_error(MSG_U(E_SERVERPATHINCORRECT, "Server path incorrect.\n" "First character must be a /\n" ) ); return( 1 ); } } ETCSERVICE *etcservice = 0; etcservice = g_etcservicelist->getitem( service_name.get() ); if ( etcservice == 0 ) { etcservice = g_etcservicelist->getitem_alias( service_name.get() ); } if ( etcservice == 0 ) { xconf_error(MSG_U(E_NOSERVICE, "Service %s\n" "does not exist."), service_name.get() ); return( 1 ); } /* * Port is set here as it is not present in the dialog. */ port = etcservice->port; if ( user.is_empty() ) { user.setfrom( "root" ); } ETCPROTOCOL *etcprotocol = 0; etcprotocol = g_etcprotocollist->getitem( protocol.get() ); if ( etcprotocol == 0 ) { etcprotocol = g_etcprotocollist->getitem_alias( protocol.get() ); } if ( etcprotocol == 0 ) { xconf_error(MSG_U(E_NOPROTOCOL, "This protocol is missing.\n" "The protocol %s\n" "does not exist."), protocol.get() ); return( 1 ); } if ( enabled ) { for ( int i=0; igetnb(); i++ ) { INETDCONF *inetdconf = g_inetdconflist->getitem(i); if ( inetdconf->enabled && ( inetdconf->port == port ) && ( inetdconf->inetdconf_line != inetdconf_line ) && ( inetdconf->protocol.cmp( protocol ) == 0 ) ) { xconf_error(MSG_U(E_DUPPORTPROTOCOL, "Port/protocol (%d/%s) is already.\n" "enabled in service (%s).\n" "(%s: lines %d and %d)\n" ), port, protocol.get(), inetdconf->service_name.get(), f_config_file.getpath(), inetdconf->inetdconf_line, inetdconf_line ); return( 1 ); } } char text[256]; if ( server_path_error( text, sizeof( text ) ) ) { xconf_error( text ); return( 1 ); } } return( 0 ); } /** * INETDCONFLIST */ static int cmp_by_name (const ARRAY_OBJ *o1, const ARRAY_OBJ *o2) { INETDCONF *s1 = (INETDCONF*)o1; INETDCONF *s2 = (INETDCONF*)o2; int ret = s1->service_name.cmp(s2->service_name); if (ret == 0){ ret = s1->protocol.cmp(s2->protocol); } if (ret == 0){ ret = s1->socket_type.cmp(s2->socket_type); } return ret; } PUBLIC void INETDCONFLIST::sort() { ARRAY::sort (cmp_by_name); } PUBLIC INETDCONF *INETDCONFLIST::getitem (int no) const { return (INETDCONF*)ARRAY::getitem (no); } PUBLIC INETDCONF *INETDCONFLIST::getitem (const char *_service_name) const { INETDCONF *ret = 0; int n = getnb(); for (int i=0; iservice_name.cmp(_service_name)==0){ ret = inetdconf; break; } } return ret; } PUBLIC INETDCONFLIST::INETDCONFLIST( ) { //fprintf(stderr,"INETDCONFLIST::INETDCONFLIST\n"); my_xinetdefaults = 0; } PRIVATE int INETDCONFLIST::valid_etcservice( char *word, INETDCONF *inetdconf ) { ETCSERVICE *etcservice = g_etcservicelist->getitem( word ); if ( etcservice == 0 ) { //fprintf( stderr, "inetdconfedit.cc: valid_etcservice: word=%s etcservice->service_name=0\n", word); etcservice = g_etcservicelist->getitem_alias( word ); if ( etcservice == 0 ) { //fprintf( stderr, "inetdconfedit.cc: valid_etcservice: word=%s etcservice->service_name: alias=0\n", word); return( 0 ); } } //fprintf( stderr, "inetdconfedit.cc: etcservice->service_name=%s\n", etcservice->service_name.get()); inetdconf->service_name.setfrom( word ); inetdconf->port = etcservice->port; return( 1 ); } PRIVATE int INETDCONFLIST::valid_socket_type( char *word, INETDCONF *inetdconf ) { if ( ( strcmp( word, "stream" ) == 0 ) || ( strcmp( word, "dgram" ) == 0 ) || ( strcmp( word, "raw" ) == 0 ) || ( strcmp( word, "rdm" ) == 0 ) || ( strcmp( word, "seqpacket" ) == 0 ) ) { inetdconf->socket_type.setfrom( word ); return( 1 ); } return( 0 ); } PRIVATE int INETDCONFLIST::valid_protocol( char *word, INETDCONF *inetdconf ) { ETCPROTOCOL *etcprotocol = g_etcprotocollist->getitem( word ); if ( etcprotocol == 0 ) { //fprintf( stderr, "inetdconfedit.cc: valid_etcprotocol: word=%s etcprotocol->service_name=0\n", word); etcprotocol = g_etcprotocollist->getitem_alias( word ); if ( etcprotocol == 0 ) { //fprintf( stderr, "inetdconfedit.cc: valid_etcprotocol: word=%s etcprotocol->service_name: alias=0\n", word); return( 0 ); } } inetdconf->protocol.setfrom( word ); return( 1 ); } PRIVATE int INETDCONFLIST::valid_multi_max( char *word, INETDCONF *inetdconf ) { char *p = word; char *s = word; for ( ; *p && *p != '.'; p++ ); if ( *p == '.' ) { *p++ = '\0'; inetdconf->max = atoi( p ); } if ( strncmp( s, "wait", 4 ) == 0 ) { inetdconf->multi = 1; return( 1 ); } else { if ( strncmp( s, "nowait", 6 ) == 0 ) { inetdconf->multi = 0; return( 1 ); } } return( 0 ); } PRIVATE int INETDCONFLIST::valid_user_group( char *word, INETDCONF *inetdconf ) { char *p = word; char *s = word; for ( ; *p && *p != '.'; p++ ); if ( *p == '.' ) { *p++ = '\0'; inetdconf->user.setfrom( s ); inetdconf->group.setfrom( p ); } else { inetdconf->user.setfrom( s ); } return( 1 ); } PRIVATE int INETDCONFLIST::valid_path( char *word, INETDCONF *inetdconf ) { if ( strcmp( word, "internal" ) == 0 ) { inetdconf->server_path.setfrom( word ); return( 1 ); } if ( word[0] == '/' ) { inetdconf->server_path.setfrom( word ); return( 1 ); } return( 0 ); } /** * Read config file and parse inetdconfs */ PUBLIC void INETDCONFLIST::read() { if ( g_etcservicelist == 0 ) { g_etcservicelist = new ETCSERVICELIST(); g_etcservicelist->read( ); } if ( g_etcprotocollist == 0 ) { g_etcprotocollist = new ETCPROTOCOLLIST(); g_etcprotocollist->read( ); } if ( xinetd_conf_flag ) read_xinetd(); else read_inetd(); } PRIVATE void INETDCONFLIST::read_xinetd() { //fprintf(stderr,"read_xinetd: %s\n", f_config_file.getpath()); scan_file( f_config_file.getpath() ); } PRIVATE void INETDCONFLIST::scan_directory( char *directory, const char *file) { //fprintf(stderr,"scan_directory: %s file=%s\n", directory, file); DIR *d; if ((d=opendir(directory)) == NULL ) { xconf_error(MSG_U(E_NO_DIRECTORY, "Can not open directory %s\n\ Name found in file %s\n"),file,directory); return; } struct stat statbuf; struct dirent *entry; char name[1024]; while ( (entry = readdir(d)) != NULL ) { snprintf(name,sizeof(name),"%s/%s", directory, entry->d_name); if ((stat( name, &statbuf ) == 0) && ((statbuf.st_mode & S_IFDIR) == 0) ) { scan_file( name ); } } closedir( d ); } /* * This function is supposed to handle both variants of /etc/xinetd.conf * One is where services are all included in the file and the other * where a directory is specified where the services are specified * one in each file. */ PRIVATE void INETDCONFLIST::scan_file( const char *file ) { //fprintf(stderr,"%s\n", line); char myAttribute[64]; char myOperator[64]; char myValue[128]; FILE *fp; if ( (fp=fopen(file,"r"))==NULL) return; char buffer[1024]; int token = K_XINETD_SERVICE; INETDCONF *inetdconf = NULL; while (fgets( buffer, sizeof(buffer), fp) != NULL ) { const char *p = buffer; if ( *p && *p == '#' ) continue; if ( strlen( p ) == 1 ) continue; next_attribute( myAttribute, myOperator,myValue,p, sizeof(myAttribute),sizeof(myOperator),sizeof(myValue)); //fprintf(stderr,"scan_file: token=%d myAttribute=%s myOperator=\"%s\" myValue=%s\n", token, myAttribute,myOperator,myValue); switch ( token ) { case K_XINETD_SERVICE: if ( strcmp(myAttribute,"includedir" ) == 0) { scan_directory( myOperator, file ); } if ( strcmp(myAttribute,"include" ) == 0) { scan_file( myOperator ); } if ( strcmp(myAttribute,"service" ) == 0) { inetdconf = new INETDCONF(this); if ( valid_etcservice( myOperator, inetdconf ) ) { token = K_XINETD_SERVICE_START; } else { delete inetdconf; inetdconf = 0; } } if ( strcmp(myAttribute,"defaults" ) == 0) { token = K_XINETD_DEFAULTS_START; } break; case K_XINETD_SERVICE_START: if ( strcmp(myAttribute,"{") == 0 ) { token = K_XINETD_SERVICE_ATTRIBUTE; } else { token = K_XINETD_SERVICE; } break; case K_XINETD_SERVICE_ATTRIBUTE: if ( strcmp(myAttribute,"}") == 0 ) { //fprintf(stderr,"INETDCONFLIST::add_service_xinetd: %s file=%s\n", inetdconf->service_name.get(),file); inetdconf->my_config_file.setfrom( file ); inetdconf->inetdconf_line = 0; add( inetdconf ); //set_enabled(inetdconf); inetdconf->previous_enabled = inetdconf->enabled; token = K_XINETD_SERVICE_OK; break; } if ( strcmp(myAttribute,"type") == 0 ) { // type add_attribute( &inetdconf->type, myOperator, myValue ); } else if ( strcmp(myAttribute,"flags") == 0 ) { // flags add_attribute( &inetdconf->flags, myOperator, myValue ); } else if ( strcmp(myAttribute,"socket_type") == 0 ) { // socket_type add_attribute( &inetdconf->socket_type, myOperator, myValue ); } else if ( strcmp(myAttribute,"protocol") == 0 ) { // protocol (void)valid_protocol( myValue, inetdconf ); } else if ( strcmp(myAttribute,"interface") == 0 // interface || strcmp(myAttribute,"bind") == 0 ) { add_attribute( &inetdconf->interface, myOperator, myValue ); } else if ( strcmp(myAttribute,"wait") == 0 ) { // wait if (strcmp(myValue,"yes")==0) inetdconf->multi=1; else inetdconf->multi=0; } else if ( strcmp(myAttribute,"user") == 0 ) { // user add_attribute( &inetdconf->user, myOperator, myValue ); } else if ( strcmp(myAttribute,"group") == 0 ) { // group add_attribute( &inetdconf->group, myOperator, myValue ); } else if ( strcmp(myAttribute,"instances") == 0 ) { // instances inetdconf->max = atoi(myValue); } else if ( strcmp(myAttribute,"nice") == 0 ) { // nice inetdconf->nice = atoi(myValue); } else if ( strcmp(myAttribute,"server") == 0 ) { // server add_attribute( &inetdconf->server_path, myOperator, myValue ); } else if ( strcmp(myAttribute,"server_args") == 0 ) { // server_args add_attribute( &inetdconf->server_args, myOperator, myValue ); } else if ( strcmp(myAttribute,"only_from") == 0 ) { // only_from add_attribute( &inetdconf->only_from, myOperator, myValue ); } else if ( strcmp(myAttribute,"no_access") == 0 ) { // no_access add_attribute( &inetdconf->no_access, myOperator, myValue ); } else if ( strcmp(myAttribute,"access_times") == 0 ) { // access_times add_attribute( &inetdconf->access_times, myOperator, myValue ); } else if ( strcmp(myAttribute,"log_type") == 0 ) { // log_type add_attribute( &inetdconf->log_type, myOperator, myValue ); } else if ( strcmp(myAttribute,"log_on_success")==0) { // log_on_success add_attribute( &inetdconf->log_on_success, myOperator, myValue ); } else if ( strcmp(myAttribute,"log_on_failure")==0) { // log_on_failure add_attribute( &inetdconf->log_on_failure, myOperator, myValue ); } else if ( strcmp(myAttribute,"rpc_version")==0) { // rpc_version add_attribute( &inetdconf->rpc_version, myOperator, myValue ); } else if ( strcmp(myAttribute,"rpc_number")==0) { // rpc_number add_attribute( &inetdconf->rpc_number, myOperator, myValue ); } else if ( strcmp(myAttribute,"env")==0) { // env add_attribute( &inetdconf->env, myOperator, myValue ); } else if ( strcmp(myAttribute,"passenv")==0) { // passenv add_attribute( &inetdconf->passenv, myOperator, myValue ); } else if ( strcmp(myAttribute,"disable")==0) { inetdconf->enabled = strcasecmp(myValue,"no")==0; } else if ( strcmp(myAttribute,"port")==0) { // port inetdconf->port = atoi(myValue); } break; case K_XINETD_SERVICE_OK: break; case K_XINETD_DEFAULTS_START: if ( strcmp(myAttribute,"{") == 0 ) { my_xinetdefaults = new XINETDEFAULTS(); token = K_XINETD_DEFAULTS_ATTRIBUTE; } else { token = K_XINETD_SERVICE; } break; case K_XINETD_DEFAULTS_ATTRIBUTE: if ( strcmp(myAttribute,"}") == 0 ) { //fprintf(stderr,"INETDCONFLIST::add_defaults_xinetd: disabled=%s\n", my_xinetdefaults->disabled.get()); token = K_XINETD_SERVICE; break; } if ( strcmp(myAttribute,"disabled") == 0 ) { // disabled cat_attribute( &my_xinetdefaults->disabled, myValue ); } break; } } fclose( fp ); return; } PRIVATE void INETDCONFLIST::set_enabled( INETDCONF *inetdconf ) { if ( my_xinetdefaults == 0 ) { inetdconf->enabled = 1; return; } char word[1024]; const char *p = my_xinetdefaults->disabled.get(); //fprintf(stderr,"INETDCONF::set_enabled: service_name=%s disabled=%s\n", inetdconf->service_name.get(),my_xinetdefaults->disabled.get()); while ( *p ) { p = next_word( word, p, sizeof( word )); if (strcmp(inetdconf->service_name.get(),word)==0) { inetdconf->enabled = 0; return; } } inetdconf->enabled = 1; } PRIVATE void INETDCONFLIST::add_attribute( SSTRING *string, char *myOperator, char *myValue ) { if ( strcmp(myOperator,"=" ) == 0 ) string->setfrom( myValue ); else if ( strcmp(myOperator,"+=" ) == 0 ) { if ( string->is_empty( ) ) { string->setfrom( myValue ); } else { string->append( " " ); string->append( myValue ); } } } PRIVATE void INETDCONFLIST::cat_attribute( SSTRING *string, char *myValue ) { if ( string->is_empty( ) ) { string->setfrom( myValue ); } else { string->append( " " ); string->append( myValue ); } } PRIVATE void INETDCONFLIST::read_inetd() { VIEWITEMS items; items.setcomcar( '\002' ); // Set comment to "impossible" char items.read( f_config_file ); // Read config file //fprintf(stderr,"INETDCONFLIST::read items.getnb()=%d\n", items.getnb()); for ( int line=0; lineline.get()); bool enabled = true; INETDCONF *inetdconf = 0; char word[1024]; char *line = (char *)item->line.get(); const char *p = line; while ( *p && *p == '#' ) { p++; enabled = false; } if ( strlen( p ) < 3 ) return; int token = 0; int valid_keywords = 0; while ( *p ) { p = next_word( word, p, sizeof( word )); //fprintf(stderr,"%s\n", word); token++; switch ( token ) { case K_FIELD_INETDCONF_NAME: inetdconf = new INETDCONF(this); if ( valid_etcservice( word, inetdconf ) ) { valid_keywords++; } if ( ! enabled ) { inetdconf->enabled = 0; } break; case K_FIELD_SOCKET_TYPE: if ( valid_socket_type( word, inetdconf ) ) { valid_keywords++; } break; case K_FIELD_PROTOCOL: if ( valid_protocol( word, inetdconf ) ) { valid_keywords++; } break; case K_FIELD_WAIT_MAX: if ( valid_multi_max( word, inetdconf ) ) { valid_keywords++; } break; case K_FIELD_USER_GROUP: if ( valid_user_group( word, inetdconf ) ) { valid_keywords++; } break; case K_FIELD_PATH: if ( valid_path( word, inetdconf ) ) { valid_keywords++; } break; default: // Arguments if ( inetdconf->server_args.is_empty( ) ) { inetdconf->server_args.setfrom( word ); } else { inetdconf->server_args.append(" " ); inetdconf->server_args.append( word ); } break; } } if ( valid_keywords == 6 ) { inetdconf->inetdconf_line = line_number; //fprintf(stderr,"INETDCONFLIST::add_service_inetd: %s line=%d\n", inetdconf->service_name.get(), inetdconf->inetdconf_line); add( inetdconf ); } else { delete inetdconf; } return; } /** * Edit inetdconflist */ PUBLIC int INETDCONFLIST::edit() { //fprintf(stderr,"INETDCONFLIST::edit\n"); DIALOG_LISTE *dia = 0; int nof = 0; while (1) { if (dia == 0) { sort(); dia = new DIALOG_LISTE; dia->newf_head ("",MSG_U(H_INETD,"Enabled\tService\tType\tProtocol\tServer\tArguments")); for (int i=0; ipresent(buf1,sizeof(buf1),buf2,sizeof(buf2)); dia->new_menuitem( buf1, buf2 ); } dia->addwhat (MSG_U(I_ADDINETDCONF,"Select [Add] to add a new server.\n")); } MENU_STATUS code = dia->editmenu (MSG_U(T_INETDCONFLIST,"Internet servers") ,MSG_U(I_INETDCONFLIST, "This is the list of all services which are presently\n" "available in the system. These services can be enabled\n" "or disabled.\n" ) ,help_inetdconf ,nof,0); bool mustdelete=false; if (code == MENU_QUIT || code == MENU_ESCAPE) { break; } else if (code == MENU_ADD) { INETDCONF *inetdconf = new INETDCONF(this); inetdconf->new_inetdconf = true; if ( editone(inetdconf) != -1 ) mustdelete = true; } else { INETDCONF *inetdconf = getitem( nof ); inetdconf->new_inetdconf = false; //fprintf(stderr,"INETDCONFLIST::edit: %s line=%d\n", inetdconf->service_name.get(), inetdconf->inetdconf_line); switch ( editone(nof) ) { case -1: mustdelete = false; break; case 1: mustdelete = true; break; case 0: mustdelete = true; break; } } if (mustdelete){ delete dia; dia = 0; if ( config_file_modified ) { g_inetdconflist->remove_all(); g_inetdconflist->read(); config_file_modified = false; } } } delete dia; return 0; } PUBLIC void inetdconf_edit( void ) { //fprintf(stderr,"inetdconf_edit\n"); g_inetdconflist = new INETDCONFLIST(); g_inetdconflist->read(); g_inetdconflist->edit(); delete g_inetdconflist; g_inetdconflist = 0; delete g_etcservicelist; g_etcservicelist = 0; delete g_etcprotocollist; g_etcprotocollist = 0; } PUBLIC void inetdconf_enable_service( int argc, char *service[], int status ) { g_inetdconflist = new INETDCONFLIST(); g_inetdconflist->read(); while ( argc-- ) { //fprintf(stderr,"inetdconf_enable_service: argc=%d %s\n", argc, service[argc]); INETDCONF *inetdconf = g_inetdconflist->getitem( service[argc] ); if ( inetdconf != 0 ) { //fprintf(stderr,"inetdconf_enable_service: %s\n", inetdconf->service_name.get()); inetdconf->enabled = status; inetdconf->write( MENU_ACCEPT ); } } delete g_inetdconflist; g_inetdconflist = 0; delete g_etcservicelist; g_etcservicelist = 0; delete g_etcprotocollist; g_etcprotocollist = 0; } /* * Check /etc/inetd.conf and optionally disable service when an error * is spotted. * - Checks: * Invalid server path */ PUBLIC void inetdconf_server_path( int update ) { //fprintf(stderr,"inetdconf_server_path: update=%d\n", update); g_inetdconflist = new INETDCONFLIST(); g_inetdconflist->read(); net_prtlog( NETLOG_TITLE, MSG_U(I_SERVER_PATH, "Checking %s server paths\n"), f_config_file.getpath() ); for ( int i=0; igetnb(); i++ ) { INETDCONF *inetdconf = g_inetdconflist->getitem(i); if ( ! inetdconf->enabled ) continue; char text[256]; if ( inetdconf->server_path_error( text, sizeof( text ) ) ) { //fprintf(stderr,"inetdconf_server_path: server_path_error: %s: %s %s\ntext=%s\n", inetdconf->service_name.get(), inetdconf->server_path.get(), inetdconf->server_args.get(), text); if ( update ) { inetdconf->enabled = 0; inetdconf->write( MENU_ACCEPT ); net_prtlog( NETLOG_ERR, MSG_U(E_SERVER_PATH, "Service %s at line %d disabled: " "%s\n" ), inetdconf->service_name.get(), inetdconf->inetdconf_line+1, text ); } else { net_prtlog( NETLOG_ERR, MSG_U(W_SERVER_PATH, "Service %s at line %d should be disabled: " "%s\n" ), inetdconf->service_name.get(), inetdconf->inetdconf_line+1, text ); } } } delete g_inetdconflist; g_inetdconflist = 0; delete g_etcservicelist; g_etcservicelist = 0; delete g_etcprotocollist; g_etcprotocollist = 0; } static void inetd_list() { const char *directory = "/etc/xinetd.d"; DIR *d = opendir(directory); if (d != NULL ) { struct dirent *entry; while ( (entry = readdir(d)) != NULL ) { char name[1024]; snprintf(name,sizeof(name),"%s/%s", directory, entry->d_name); new CONFIG_FILE (name,help_inetdconf,CONFIGF_MANAGED|CONFIGF_NOOLD ,"root","root",0644,subsys_inetdconf); } closedir( d ); } } static CONFIG_FILE_LISTER cfglist (inetd_list);