Ejemplo n.º 1
0
status_e setup_environ( struct service_config *scp, struct service_config *def )
{
   struct environment   *ep = SC_ENV( scp ) ;

   if ( ! SC_SPECIFIED( scp, A_PASSENV ) )
   {
      if ( ! SC_SPECIFIED( def, A_PASSENV ) )
      {
         if ( ! SC_SPECIFIED( scp, A_ENV ) )
         {
            ep->env_type = STD_ENV ;
            ep->env_handle = std_env ;
            return( OK ) ;
         }
         else
            return( 
               make_env_with_strings( ep, std_env, SC_ENV_VAR_DEFS(scp) ) ) ;
      }
      else   /* SC_SPECIFIED( def, A_PASSENV ) */
      {
         struct environment *dep = SC_ENV( def ) ;

         if ( dep->env_type == NO_ENV &&
                  make_env_from_vars( dep, std_env,
                                 SC_PASS_ENV_VARS(def) ) == FAILED )
            return( FAILED ) ;

         if ( ! SC_SPECIFIED( scp, A_ENV ) )
         {
            ep->env_type = DEF_ENV ;
            ep->env_handle = dep->env_handle ;
            return( OK ) ;
         }
         else
            return( make_env_with_strings( ep, 
                           dep->env_handle, SC_ENV_VAR_DEFS(scp) ) ) ;
      }
   }
   else   /* SC_SPECIFIED( scp, A_PASSENV ) */
   {
      if ( make_env_from_vars( ep, std_env, SC_PASS_ENV_VARS(scp) ) == FAILED )
         return( FAILED ) ;

      if ( ! SC_SPECIFIED( scp, A_ENV ) )
         return( OK ) ;
      else
      {
         if ( update_env_with_strings( 
                     ep->env_handle, SC_ENV_VAR_DEFS(scp) ) == FAILED )
         {
            env_destroy( ep->env_handle ) ;
            return( FAILED ) ;
         }
         return( OK ) ;
      }
   }
}
Ejemplo n.º 2
0
/*
 * Identify the attribute in <attr_name>.
 *
 * Check if
 *      1) the attribute has been defined already
 *      2) the value count is correct
 *      3) the assign op is appropriate
 *
 * Invoke appropriate parser.
 *
 * This function will return FAILED only if its in the default section
 * and an attribute cannot be ID'd. Otherwise, it returns OK.
 */
static status_e identify_attribute( entry_e entry_type,
                                    struct service_config *scp,
                                    const char *attr_name,
                                    enum assign_op op,
                                    pset_h attr_values )
{
    const struct attribute   *ap ;
    const char         *func = "identify_attribute" ;

    if ( entry_type == SERVICE_ENTRY )
        ap = attr_lookup( service_attributes, attr_name ) ;
    else
        ap = attr_lookup( default_attributes, attr_name ) ;

    if ( ap == NULL )
        return OK;   /* We simply ignore keywords not on the list */

    if ( ! MODIFIABLE( ap ) )
    {
        if ( SC_SPECIFIED( scp, ap->a_id ) )
        {
            parsemsg( LOG_WARNING, func, "Service %s: attribute already set: %s",
                      SC_NAME(scp), attr_name ) ;
            return OK;
        }

        if ( op != SET_EQ )
        {
            parsemsg( LOG_WARNING, func,
                      "Service %s: operator '%s' cannot be used for attribute '%s'",
                      SC_NAME(scp), ( op == PLUS_EQ ) ? "+=" : "-=", attr_name ) ;
            return OK;
        }
    }
    else      /* modifiable attribute */
    {
        /*
         * For the defaults entry, '=' and '+=' have the same meaning
         */
        if ( entry_type == DEFAULTS_ENTRY && op == SET_EQ )
            op = PLUS_EQ ;
    }

    if ( FIXED_VALUES( ap ) &&
            (unsigned)ap->a_nvalues != pset_count( attr_values ) )
    {
        parsemsg( LOG_WARNING, func,
                  "attribute %s expects %d values and %d values were specified",
                  attr_name, ap->a_nvalues, pset_count( attr_values ) ) ;
        return OK;
    }

    if ( (*ap->a_parser)( attr_values, scp, op ) == OK )
    {   /* This is the normal path. */
        SC_SPECIFY( scp, ap->a_id ) ;
    }
    else if ( entry_type == SERVICE_ENTRY )
    {
        parsemsg( LOG_ERR, func,
                  "Error parsing attribute %s - DISABLING SERVICE", attr_name ) ;
        SC_DISABLE( scp );
    }
    /*
     * We are in the default section and an error was detected. At
     * this point, we should terminate since whatever attribute
     * was trying to be specified cannot be propagated.
     */
    else if ( !debug.on )
        return FAILED;

    return OK;
}
Ejemplo n.º 3
0
/*
 * Get a service entry. Steps:
 *
 *      1. Parse entry attributes
 *      2. Determine service id
 *      3. Insert entry in table
 */
static void get_service_entry( int fd,
                               pset_h sconfs,
                               const char *name,
                               struct service_config *defaults )
{
    struct service_config   *scp ;
    const char              *func = "get_service_entry" ;

    scp = sc_alloc( name ) ;
    if ( scp == NULL )
    {
        skip_entry( fd ) ;
        return ;
    }

    /* Now fill in default attributes if given. */
    if ( SC_SPECIFIED( defaults, A_LOG_ON_SUCCESS ) &&
            ! SC_IS_PRESENT( scp, A_LOG_ON_SUCCESS) )
        fill_attribute( A_LOG_ON_SUCCESS, scp, defaults ) ;
    if ( SC_SPECIFIED( defaults, A_LOG_ON_FAILURE ) &&
            ! SC_IS_PRESENT( scp, A_LOG_ON_FAILURE ) )
        fill_attribute( A_LOG_ON_FAILURE, scp, defaults ) ;
    if ( SC_SPECIFIED( defaults, A_ONLY_FROM ) &&
            ! SC_IS_PRESENT( scp, A_ONLY_FROM ) )
        fill_attribute( A_ONLY_FROM, scp, defaults ) ;
    if ( SC_SPECIFIED( defaults, A_NO_ACCESS ) &&
            ! SC_IS_PRESENT( scp, A_NO_ACCESS ) )
        fill_attribute( A_NO_ACCESS, scp, defaults ) ;
    if ( SC_SPECIFIED( defaults, A_PASSENV ) &&
            ! SC_IS_PRESENT( scp, A_PASSENV ) )
        fill_attribute( A_PASSENV, scp, defaults ) ;
    if ( SC_SPECIFIED( defaults, A_ACCESS_TIMES ) &&
            ! SC_IS_PRESENT( scp, A_ACCESS_TIMES ) )
        fill_attribute( A_ACCESS_TIMES, scp, defaults ) ;
    if ( SC_SPECIFIED( defaults, A_BANNER ) &&
            ! SC_IS_PRESENT( scp, A_BANNER ) )
        fill_attribute( A_BANNER, scp, defaults ) ;
    if ( SC_SPECIFIED( defaults, A_BANNER_SUCCESS ) &&
            ! SC_IS_PRESENT( scp, A_BANNER_SUCCESS ) )
        fill_attribute( A_BANNER_SUCCESS, scp, defaults ) ;
    if ( SC_SPECIFIED( defaults, A_BANNER_FAIL ) &&
            ! SC_IS_PRESENT( scp, A_BANNER_FAIL ) )
        fill_attribute( A_BANNER_FAIL, scp, defaults ) ;

    if ( parse_entry( SERVICE_ENTRY, fd, scp ) == FAILED )
    {
        sc_free( scp ) ;
        skip_entry( fd ) ;
        return ;
    }

    /*
     * If no service id was specified, set it equal to the service name
     */
    if ( ! SC_SPECIFIED( scp, A_ID ) ) {
        if ( (SC_ID(scp) = new_string( SC_NAME(scp) )) )
            SC_PRESENT( scp, A_ID ) ;
        else
        {
            out_of_memory( func ) ;
            sc_free( scp ) ;
            return ;
        }
    }

    if ( ! (pset_add( sconfs, scp )) )
    {
        out_of_memory( func ) ;
        sc_free( scp ) ;
        return ;
    }

}
Ejemplo n.º 4
0
/*
 * Read the configuration file (descriptor fd) and place all
 * services found there in the configuration.
 */
void parse_conf_file( int fd, struct configuration *confp, const char *filename)
{
    pset_h                   sconfs       = CNF_SERVICE_CONFS( confp ) ;
    struct service_config   *default_config   = CNF_DEFAULTS( confp ) ;
    boolean_e                found_defaults   = NO ;
    struct service_config    default_default_config ;
    const char              *func      = "parse_conf_file" ;
    int                      incfd;

    line_count = 0 ;
    current_file = filename;
    CLEAR( default_default_config ) ;

    for ( ;; )
    {
        entry_e   entry_type ;
        char      *service_name  = NULL;

        /*
         * if find_next_entry is successful, service_name
         * will point to malloc'ed memory
         */
        entry_type = find_next_entry( fd, &service_name ) ;
        switch ( entry_type )
        {
        case INCLUDE_ENTRY:
        {
            int saved_line_count = line_count;
            incfd = open(service_name, O_RDONLY);
            if( incfd < 0 ) {
                parsemsg( LOG_ERR, func,
                          "Unable to open included configuration file: %s",
                          service_name);
                break;
            }
            parsemsg( LOG_DEBUG,func,
                      "Reading included configuration file: %s",service_name);
            parse_conf_file(incfd, confp, service_name);
            /*
             * parse_conf_file eventually calls Srdline, try Sclosing it
             * to unmmap memory.
             */
            Sclose(incfd);
            /* Restore since we've returned from included file */
            current_file = filename;
            line_count = saved_line_count;
        }
        break;
        case INCLUDEDIR_ENTRY:
        {
            int saved_line_count = line_count;
            handle_includedir(service_name, confp);
            current_file = filename;
            line_count = saved_line_count;
        }
        break;
        case SERVICE_ENTRY:
            get_service_entry( fd, sconfs, service_name, default_config ) ;
            break ;
        case DEFAULTS_ENTRY:
            if ( found_defaults == YES )
            {
                parsemsg( LOG_ERR, func,
                          "only 1 defaults entry is allowed. This entry will be ignored" ) ;
                skip_entry( fd ) ;
            }
            else if ( parse_entry( DEFAULTS_ENTRY, fd,
                                   default_config ) == OK ) {
                found_defaults = YES ;
                /*
                 * We must check bind_address to see if it was deferred.
                 */
                if (SC_SPECIFIED( default_config, A_BIND) &&
                        SC_BIND_ADDR(default_config) == NULL)
                    M_CLEAR( default_config->sc_specified_attributes, A_BIND ) ;
            }
            break ;

        case BAD_ENTRY:
            skip_entry( fd ) ;
            break ;

        case NO_ENTRY:
            return ;
        }
        if (service_name)
            free(service_name);
    }
}
Ejemplo n.º 5
0
/*
 * Print info about service scp to file descriptor fd
 */
void sc_dump( struct service_config *scp, 
              int fd, 
              int tab_level, 
              bool_int is_defaults )
{
   const struct name_value    *nvp ;
   unsigned             u ;
   char                 **pp ;

   if ( is_defaults )
      tabprint( fd, tab_level, "Service defaults\n" ) ;
   else
      tabprint( fd, tab_level, "Service configuration: %s\n", SC_NAME(scp) ) ;

   if ( ! is_defaults )
   {
      tabprint( fd, tab_level+1, "id = %s\n", SC_ID(scp) ) ;

      if ( ! M_ARE_ALL_CLEAR( SC_XFLAGS(scp) ) )
      {
         tabprint( fd, tab_level+1, "flags =" ) ;
         for ( nvp = &service_flags[ 0 ] ; nvp->name != NULL ; nvp++ )
            if ( M_IS_SET( SC_XFLAGS(scp), nvp->value ) )
               Sprint( fd, " %s", nvp->name ) ;
         Sputchar( fd, '\n' ) ;
      }

      if ( ! M_ARE_ALL_CLEAR( SC_TYPE(scp) ) )
      {
         tabprint( fd, tab_level+1, "type =" ) ;
         for ( nvp = &service_types[ 0 ] ; nvp->name != NULL ; nvp++ )
            if ( M_IS_SET( SC_TYPE(scp), nvp->value ) )
               Sprint( fd, " %s", nvp->name ) ;
         Sputchar( fd, '\n' ) ;
      }

      tabprint( fd, tab_level+1, "socket_type = %s\n",
         nv_get_name( socket_types, SC_SOCKET_TYPE(scp) ) ) ;

      tabprint( fd, tab_level+1, "Protocol (name,number) = (%s,%d)\n",
            SC_PROTONAME(scp), SC_PROTOVAL(scp) ) ;
      
      if ( SC_SPECIFIED( scp, A_PORT ) )
         tabprint( fd, tab_level+1, "port = %d\n", SC_PORT(scp) ) ;
   }

   if ( SC_SPECIFIED( scp, A_INSTANCES ) ) {
      if ( SC_INSTANCES(scp) == UNLIMITED )
         tabprint( fd, tab_level+1, "Instances = UNLIMITED\n" ) ;
      else
         tabprint( fd, tab_level+1, "Instances = %d\n", SC_INSTANCES(scp) ) ;
   }

   if ( SC_SPECIFIED( scp, A_WAIT ) ) {
      if ( SC_WAIT(scp) )
         tabprint( fd, tab_level+1, "wait = yes\n" ) ;
      else
         tabprint( fd, tab_level+1, "wait = no\n" ) ;
   }
      
   if ( SC_SPECIFIED( scp, A_USER ) )
      tabprint( fd, tab_level+1, "user = %d\n", SC_UID(scp) ) ;
      
   if ( SC_SPECIFIED( scp, A_GROUP ) )
      tabprint( fd, tab_level+1, "group = %d\n", SC_GID(scp) ) ;
      
   if ( SC_SPECIFIED( scp, A_GROUPS ) )
   {
      if (SC_GROUPS(scp) == 1)
         tabprint( fd, tab_level+1, "Groups = yes\n" );
      else
         tabprint( fd, tab_level+1, "Groups = no\n" );
   }

   if ( SC_SPECIFIED( scp, A_UMASK ) )
      tabprint( fd, tab_level+1, "umask = %o\n", SC_UMASK(scp) ) ;
      
   if ( SC_SPECIFIED( scp, A_NICE ) )
      tabprint( fd, tab_level+1, "Nice = %d\n", SC_NICE(scp) ) ;

   if ( SC_SPECIFIED( scp, A_CPS ) )
      tabprint( fd, tab_level+1, "CPS = max conn:%lu wait:%lu\n", 
         SC_TIME_CONN_MAX(scp), SC_TIME_WAIT(scp) );

   if ( SC_SPECIFIED( scp, A_PER_SOURCE ) )
      tabprint( fd, tab_level+1, "PER_SOURCE = %d\n", 
         SC_PER_SOURCE(scp) );

   if ( SC_SPECIFIED( scp, A_BIND ) ) {
	   if (  SC_BIND_ADDR(scp) ) {
		  char bindname[NI_MAXHOST];
		  unsigned int len = 0;
		  if( SC_BIND_ADDR(scp)->sa.sa_family == AF_INET ) 
			 len = sizeof(struct sockaddr_in);
		  else  
			 len = sizeof(struct sockaddr_in6);
		  memset(bindname, 0, sizeof(bindname));
		  if( getnameinfo(&SC_BIND_ADDR(scp)->sa, len, bindname, 
                                  NI_MAXHOST, NULL, 0, 0) != 0 ) 
			 strcpy(bindname, "unknown");
		  tabprint( fd, tab_level+1, "Bind = %s\n", bindname );
	   }
	   else if ( SC_ORIG_BIND_ADDR(scp) ) {
		  tabprint( fd, tab_level+1, "Bind = %s\n", 
                            SC_ORIG_BIND_ADDR(scp) );
	   }
	   else { /* This should NEVER happen */
		msg(LOG_ERR, "sc_dump", "bad configuration for %s:", 
                    SC_NAME(scp));
	   }
   }
   else
      tabprint( fd, tab_level+1, "Bind = All addresses.\n" );

   if ( ! is_defaults )
   {
      if ( (! SC_IS_INTERNAL( scp )) && (SC_REDIR_ADDR(scp) == NULL) )
      {
         tabprint( fd, tab_level+1, "Server = %s\n", SC_SERVER(scp) ) ;
         tabprint( fd, tab_level+1, "Server argv =" ) ;
	 if ( SC_SERVER_ARGV(scp) )
	 {
            for ( pp = SC_SERVER_ARGV(scp) ; *pp ; pp++ )
               Sprint( fd, " %s", *pp ) ;
	 }
	 else
	    Sprint( fd, " (NULL)");
         Sputchar( fd, '\n' ) ;
      } 

#ifdef LIBWRAP
      if ( SC_LIBWRAP(scp) != NULL )
      {
         tabprint( fd, tab_level + 1, "Libwrap = %s\n", SC_LIBWRAP(scp) );
      }
#endif

      if ( SC_REDIR_ADDR(scp) != NULL ) 
      {
         char redirname[NI_MAXHOST];
         unsigned int len = 0;
         if( SC_REDIR_ADDR(scp)->sa.sa_family == AF_INET ) 
            len = sizeof(struct sockaddr_in);
         if( SC_REDIR_ADDR(scp)->sa.sa_family == AF_INET6 ) 
            len = sizeof(struct sockaddr_in6);
         memset(redirname, 0, sizeof(redirname));
         if( getnameinfo(&SC_REDIR_ADDR(scp)->sa, len,  redirname, NI_MAXHOST, 
               NULL, 0, 0) != 0 ) 
            strcpy(redirname, "unknown");
         tabprint( fd, tab_level+1, "Redirect = %s:%d\n", redirname, 
	    SC_REDIR_ADDR(scp)->sa_in.sin_port );
      }

      if ( SC_IS_RPC( scp ) )
      {
         struct rpc_data *rdp = SC_RPCDATA( scp ) ;

         tabprint( fd, tab_level+1, "RPC data\n" ) ;
         tabprint( fd, tab_level+2,
                           "program number = %ld\n", rdp->rd_program_number ) ;
         tabprint( fd, tab_level+2, "rpc_version = " ) ;
         if ( rdp->rd_min_version == rdp->rd_max_version )
            Sprint( fd, "%ld\n", rdp->rd_min_version ) ;
         else
            Sprint( fd, "%ld-%ld\n",
                           rdp->rd_min_version, rdp->rd_max_version ) ;
      }

      if ( SC_SPECIFIED( scp, A_ACCESS_TIMES ) )
      {
         tabprint( fd, tab_level+1, "Access times =" ) ;
         ti_dump( SC_ACCESS_TIMES(scp), fd ) ;
         Sputchar ( fd, '\n' ) ;
      }
   }

   /* This is important enough that each service should list it. */
   tabprint( fd, tab_level+1, "Only from: " ) ;
   if ( SC_ONLY_FROM(scp) )
   {  /* Next check is done since -= doesn't zero out lists. */
      if ( pset_count(SC_ONLY_FROM(scp)) == 0)
         Sprint( fd, "All sites" );
      else
         addrlist_dump( SC_ONLY_FROM(scp), fd ) ;
   }
   else
      Sprint( fd, "All sites" );
   Sputchar( fd, '\n' ) ;

   /* This is important enough that each service should list it. */
   tabprint( fd, tab_level+1, "No access: " ) ;
   if ( SC_NO_ACCESS(scp) )
   {  /* Next check is done since -= doesn't zero out lists. */
      if ( pset_count(SC_NO_ACCESS(scp)) == 0)
         Sprint( fd, "No blocked sites" );
      else
         addrlist_dump( SC_NO_ACCESS(scp), fd ) ;
   }
   else
      Sprint( fd, "No blocked sites" );
   Sputchar( fd, '\n' ) ;

   if ( SC_SENSOR(scp) )
   {
      tabprint( fd, tab_level+1, "Deny Time: " ) ;
      Sprint( fd, "%d\n", SC_DENY_TIME(scp));
   }
   
   dump_log_data( fd, scp, tab_level+1 ) ;

   if ( SC_IS_PRESENT( scp, A_PASSENV ) )
   {
      tabprint( fd, tab_level+1, "Passenv =" ) ;
      for ( u = 0 ; u < pset_count( SC_PASS_ENV_VARS(scp) ) ; u++ )
         Sprint( fd, " %s",
                  (char *) pset_pointer( SC_PASS_ENV_VARS(scp), u ) ) ;
      Sputchar ( fd, '\n' ) ;
   }

   if ( ! is_defaults )
      if ( SC_SPECIFIED( scp, A_ENV ) )
      {
         tabprint( fd, tab_level+1, "Environment additions:\n" ) ;
         for ( u = 0 ; u < pset_count( SC_ENV_VAR_DEFS(scp) ) ; u++ )
            tabprint( fd, tab_level+2,
                  "%s\n", (char *) pset_pointer( SC_ENV_VAR_DEFS(scp), u ) ) ;
      }
   
   if ( SC_ENV( scp )->env_type == CUSTOM_ENV )
   {
      tabprint( fd, tab_level+1, "Environment strings:\n" ) ;
      for ( pp = env_getvars( SC_ENV( scp )->env_handle ) ; *pp ; pp++ )
         tabprint( fd, tab_level+2, "%s\n", *pp ) ;
   }
   Sflush( fd ) ;
}
Ejemplo n.º 6
0
static status_e activate_normal( struct service *sp )
{
   union xsockaddr         tsin;
   int                     sd             = SVC_FD( sp ) ;
   struct service_config  *scp            = SVC_CONF( sp ) ;
   uint16_t                service_port   = SC_PORT( scp ) ;
   char                   *sid            = SC_ID( scp ) ;
   const char             *func           = "activate_normal" ;
   unsigned int            sin_len        = sizeof(tsin);
   int                     on             = 1;
#ifdef IPV6_V6ONLY
   int                     v6on           = 0;
#endif

   if( SC_BIND_ADDR(scp) != NULL )
      memcpy(&tsin, SC_BIND_ADDR(scp), sin_len);
   else
      memset(&tsin, 0, sin_len);
   
   if( SC_IPV4( scp ) ) {
      tsin.sa_in.sin_family = AF_INET ;
      tsin.sa_in.sin_port = htons( service_port ) ;
      sin_len = sizeof(struct sockaddr_in);
   } else if( SC_IPV6( scp ) ) {
      tsin.sa_in6.sin6_family = AF_INET6;
      tsin.sa_in6.sin6_port = htons( service_port );
      sin_len = sizeof(struct sockaddr_in6);
   }

#ifdef IPV6_V6ONLY
   if( SC_IPV6(scp) ) {
      if( SC_SPECIFIED(scp, A_V6ONLY) ) {
         v6on = 1;
      } else {
         v6on = 0;
      }
      if( setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6on, sizeof(v6on)) < 0 ) {
         msg( LOG_ERR, func, "Setting IPV6_V6ONLY option failed (%m)" );
      }
   }
#endif

   if ( setsockopt( sd, SOL_SOCKET, SO_REUSEADDR, 
                    (char *) &on, sizeof( on ) ) == -1 )
      msg( LOG_WARNING, func, 
           "setsockopt SO_REUSEADDR failed (%m). service = %s", sid ) ;

   if( SC_NODELAY( scp ) && (SC_PROTOVAL(scp) == IPPROTO_TCP) )
   {
      if ( setsockopt( sd, IPPROTO_TCP, TCP_NODELAY, 
                       (char *) &on, sizeof( on ) ) == -1 )
         msg( LOG_WARNING, func, 
              "setsockopt TCP_NODELAY failed (%m). service = %s", sid ) ;
   }

   if( SC_KEEPALIVE( scp ) && (SC_PROTOVAL(scp) == IPPROTO_TCP) ) 
   {
      if( setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, 
                     (char *)&on, sizeof( on ) ) < 0 )
         msg( LOG_WARNING, func, 
              "setsockopt SO_KEEPALIVE failed (%m). service = %s", sid ) ;
   }

   if ( bind( sd, &tsin.sa, sin_len ) == -1 )
   {
      msg( LOG_ERR, func, "bind failed (%m). service = %s", sid ) ;
      return( FAILED ) ;
   }

#ifdef IN_MULTICAST
   if( SC_IPV4(scp) && IN_MULTICAST( ntohl(tsin.sa_in.sin_addr.s_addr) ) ) {
      struct ifaddrs *addrs, *addr;
      struct ip_mreq mreq;
      
      if (getifaddrs(&addrs) == 0) {
         addr = addrs;

         while (addr)
         {
            if (addr->ifa_addr && (addr->ifa_flags & IFF_MULTICAST))
            {
               mreq.imr_multiaddr.s_addr = tsin.sa_in.sin_addr.s_addr;
               mreq.imr_interface.s_addr = ((struct sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr;
               setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
            }
            addr = addr->ifa_next;
         }
         freeifaddrs(addrs);
         if ( debug.on )
               msg( LOG_DEBUG, func, "Adding multicast membership." );
      }
      else {
         msg( LOG_ERR, func, "getifaddrs failed (%m). service = %s", sid );
      }
   }
#endif

   return( OK ) ;
}
Ejemplo n.º 7
0
Archivo: child.c Proyecto: aosm/xinetd
/*
 * This function is invoked in a forked process to run a server. 
 * If the service is internal the appropriate function is invoked
 * otherwise the server program is exec'ed.
 * This function also logs the remote user id if appropriate
 */
void child_process( struct server *serp )
{
   struct service          *sp  = SERVER_SERVICE( serp ) ;
   connection_s            *cp  = SERVER_CONNECTION( serp ) ;
   struct service_config   *scp = SVC_CONF( sp ) ;
   const char              *func = "child_process" ;

   signal_default_state();

   if ((signals_pending[0] >= 0 && Sclose(signals_pending[0])) ||
       (signals_pending[1] >= 0 && Sclose(signals_pending[1])))
   {
      msg(LOG_ERR, func, "Failed to close the signal pipe: %m");
      _exit(1);
   }
   signals_pending[0] = -1;
   signals_pending[1] = -1;

   Sclose(0);
   Sclose(1);
   Sclose(2);


#ifdef DEBUG_SERVER
   if ( debug.on )
   {
      msg( LOG_DEBUG, func, "Process %d is sleeping", getpid() ) ;
      sleep( 10 ) ;
   }
#endif

   if ( ! SC_IS_INTERCEPTED( scp ) )
   {
      set_credentials( scp ) ;
      if ( SC_SPECIFIED( scp, A_NICE ) )
         (void) nice( SC_NICE( scp ) ) ;
   }

   if ( svc_child_access_control(sp, cp) != OK )
      exit(0);

   if ( SERVER_LOGUSER( serp ) )
   {
      unsigned   timeout ;
      idresult_e result ;
      
      /*
       * We use LOGUSER_SUCCESS_TIMEOUT unless the service requires
       * identification, in which case we use an infinite timeout
       */
      timeout = SC_MUST_IDENTIFY( scp ) ? 0 : LOGUSER_SUCCESS_TIMEOUT ;
      result = log_remote_user( serp, timeout ) ;

      if ( result != IDR_OK && SC_MUST_IDENTIFY( scp ) )
      {
         svc_logprint( sp, NOID_ENTRY, "%s %s",
                  conn_addrstr( SERVER_CONNECTION( serp ) ),
                     idresult_explain( result ) ) ;
         _exit( 0 ) ;
      }
   }

#ifdef HAVE_SESSIONCREATE
   if ( scp->sc_sessioncreate == YES ) 
   {
      if ( SessionCreate(0, sessionHasTTY|sessionIsRemote) != noErr )
         svc_logprint( sp, "SessionCreate", "SessionCreate() failed!" );
   }
#endif

   /* this is where the server gets executed  -bbraun */
   if ( ! SC_IS_INTERNAL( scp ) )
   {
      if( scp->sc_redir_addr != NULL )
      {
         redir_handler( serp );
      }
      else
      {
#if defined(HAVE_SETENV)
         char buff[1024];

         strx_sprint(buff, sizeof(buff)-1, "REMOTE_HOST=%s", conn_addrstr(cp));
         if( env_addstr(SC_ENV(scp)->env_handle, buff) != ENV_OK ) {
            msg( LOG_ERR, func, "Error adding REMOTE_HOST variable for %s: %m", SC_NAME(scp) );
            _exit( 1 ) ;
         }
#endif
         exec_server( serp ) ;
      }
   }
   else
   {
      char name[ 180 ] ;
      /*
       * We don't bother to disassociate from the controlling terminal
       *   (we have a controlling terminal only if debug.on is TRUE)
       *
       * Also, for interceptor processes, we give them the name:
       *            <program_name> <service-id> interceptor
       */
      if ( SC_IS_INTERCEPTED( scp ) )
         strx_print( INT_NULL, name, sizeof( name ) - 1,
                           "%s %s interceptor", program_name, SC_ID( scp ) ) ;
      else
      {
         int namelen = sizeof( name ) - 1 ;      /* leave space for the NUL */
         char host[NI_MAXHOST];
         size_t hostlen = NI_MAXHOST;
         socklen_t addrlen = 0;
         union xsockaddr *sinp = CONN_XADDRESS(SERVER_CONNECTION(serp));
         int len;

         if( sinp == NULL )
            exit(0);

         if( SC_IPV6(scp) ) addrlen = sizeof(struct sockaddr_in6);
         else if( SC_IPV4(scp) ) addrlen = sizeof(struct sockaddr_in);

         len = strx_nprint(name, namelen, "(%s service) %s", program_name,
            SC_ID( scp ) ) ;

         if( getnameinfo( SA(sinp), addrlen, host, hostlen, NULL, 0, 0) != 0 )
               strcpy(host, "unknown");

         if ( SC_IPV6(scp) && SC_ACCEPTS_CONNECTIONS( scp ) && 
               !IN6_IS_ADDR_UNSPECIFIED(&sinp->sa_in6.sin6_addr) )
            strx_print( INT_NULL, &name[ len ], namelen - len, " %s" , host ) ;
         if ( SC_IPV4(scp) && SC_ACCEPTS_CONNECTIONS( scp ) )
            strx_print( INT_NULL, &name[ len ], namelen - len, " %s", host ) ;
      }
      rename_process( name ) ;
      SVC_INTERNAL( sp, serp ) ;
   }
   _exit( 0 ) ;
   /* NOTREACHED */
}
Ejemplo n.º 8
0
Archivo: child.c Proyecto: aosm/xinetd
static void set_credentials( const struct service_config *scp )
{
   const char *func = "set_credentials" ;

   if ( SC_SPECIFIED( scp, A_GROUP ) || SC_SPECIFIED( scp, A_USER ) ) {
      if ( ps.ros.is_superuser )
      {
         gid_t gid = SC_GETGID( scp ) ;

         if ( setgid( gid ) == -1 )
         {
            msg( LOG_ERR, func, "setgid failed: %m" ) ;
            _exit( 1 ) ;
         }

#ifndef NO_INITGROUPS
         /*
          * Bug discovered by [email protected] (a bug fix was also provided;
          * a slightly modified version is included here):
          *      initgroups was not being invoked to set the remaining
          *      groups appropriately
          */
         /* Solar Designer's groups fix */
         if ( SC_SPECIFIED( scp, A_USER ) && SC_SPECIFIED( scp, A_GROUPS ) &&
            scp->sc_groups == YES )
         {
            struct passwd *pwd ;

            /*
             * Invoke getpwuid() to get the user's name.
             *
             * XXX:   we should not need to invoke getpwuid(); we should
             *         remember the user name in the configuration file.
             */
            if ( ( pwd = getpwuid( SC_UID( scp ) ) ) == NULL )
            {
               msg( LOG_ERR, func, "getpwuid( %d ) (service=%s) failed: %m",
                  SC_UID( scp ), SC_ID( scp ) ) ;
               _exit( 1 ) ;
            }
            str_fill( pwd->pw_passwd, ' ' );

            if ( initgroups( pwd->pw_name, pwd->pw_gid ) == -1 )
            {
               msg( LOG_ERR, func, "initgroups( %s, %d ) failed: %m",
                  pwd->pw_name, pwd->pw_gid ) ;
               _exit( 1 ) ;
            }
         }
         else
         {
            if ( setgroups( 0, NULL ) )
            {
               msg( LOG_ERR, func, "setgroups( 0, NULL ) failed: %m" ) ;
               msg( LOG_ERR, func, "Your system may require that 'groups = yes' be defined for this service: %s", scp->sc_name);
               _exit( 1 ) ;
            }
         }
#endif   /* ! NO_INITGROUPS */
      }
   }

   if ( SC_SPECIFIED( scp, A_USER ) ) {
         if ( setuid( SC_UID( scp ) ) == -1 )
         {
            msg( LOG_ERR, func, "setuid failed: %m" ) ;
            _exit( 1 ) ;
         }
      }

   if ( SC_SPECIFIED( scp, A_UMASK ) ) 
      umask(scp->sc_umask);
}