Пример #1
0
static char *verify_line( char *line,
                          unsigned local_port,
                          unsigned remote_port )
{
    char   *p ;
    char   *start = line ;
    int     port;

    /*
     * Verify port numbers
     */
    p = strchr( start, ',' ) ;
    if ( p == NULL )
        return( NULL ) ;
    *p = NUL ;
    if ( parse_base10( start, &port ) ||
            port < 0 || (unsigned)port != remote_port ) {
        *p = ',';
        return( NULL ) ;
    }
    *p = ',' ;

    start = p+1 ;
    p = strchr( start, ':' ) ;
    if ( p == NULL )
        return( NULL ) ;
    *p = NUL ;
    if ( parse_base10( start, &port ) ||
            port < 0 || (unsigned)port != local_port ) {
        *p = ':';
        return( NULL ) ;
    }
    *p = ':';

    /*
     * Look for the 'USERID' string
     */
    {
        const char *line_id = "USERID" ;
        unsigned int line_id_len = strlen( line_id ) ;

        start = p+1 ;
        for ( p = start ; isspace( *p ) ; p++ ) ;
        if ( *p == NUL )
            return( NULL ) ;
        start = p ;
        if ( strncmp( start, line_id, line_id_len ) != 0 )
            return( NULL ) ;
        start += line_id_len ;      /* skip it */
    }

    for ( p = start ; isspace( *p ) ; p++ ) ;      /* skip any white-space */
    if ( *p != ':' )
        return( NULL ) ;
    for ( p++ ; isspace( *p ) ; p++ ) ;
    if ( *p == NUL )
        return( NULL ) ;
    return( p ) ;
}
Пример #2
0
static int get_next_inet_entry( int fd, pset_h sconfs, 
                          struct service_config *defaults)
{
   char *p;
   str_h strp;
   char *line = next_line(fd);
   struct service_config *scp;
   unsigned u, i;
   const char *func = "get_next_inet_entry";
   char *name = NULL, *rpcvers = NULL, *rpcproto = NULL;
   char *group, *proto, *stype;
   const struct name_value *nvp;
   struct protoent *pep ;
   struct passwd *pw ;
   struct group *grp ;
   const char *dot = ".";
   const char *slash = "/";
   pset_h args;
   
   if( line == CHAR_NULL )
      return -2;

   strp = str_parse( line, " \t", STR_RETURN_ERROR, INT_NULL ) ;
   if( strp == NULL )
   {
      parsemsg( LOG_CRIT, func, "inetd.conf - str_parse failed" ) ;
      return( -1 ) ;
   }

   if( (args = pset_create(10,10)) == NULL )
   {
      out_of_memory(func);
      return -1;
   }

   /* Break the line into components, based on spaces */
   while( (p = str_component( strp )) )
   {
      if( pset_add(args, p) == NULL )
      {
         parsemsg( LOG_CRIT, func, ES_NOMEM );
         pset_destroy(args);
         return -1;
      }
   }
   str_endparse( strp );

   /* get the service name */
   name = new_string((char *)pset_pointer( args, 0 ));
   if( name == NULL ) {
      parsemsg( LOG_ERR, func, "inetd.conf - Invalid service name" );
      pset_destroy(args);
      return -1;
   }

   /* Check to find the '/' for specifying RPC version numbers */
   if( (rpcvers = strstr(name, slash)) != NULL ) {
      *rpcvers = '\0';
      rpcvers++;
   }

   scp = sc_alloc( name );
   if( scp == NULL )
   {
      pset_destroy(args);
      free( name );
      return -1;
   }
   /*
    * sc_alloc makes its own copy of name. At this point, sc_alloc worked
    * so we will free our copy to avoid leaks.
    */
   free( name );

   /* Replicate inetd behavior in this regard.  Also makes sure the
    * service actually works on system where setgroups(0,NULL) doesn't
    * work.
    */
   SC_GROUPS(scp) = YES;
   SC_SPECIFY( scp, A_GROUPS );

   /* Get the socket type (stream dgram) */
   stype = (char *)pset_pointer(args, 1);
   if( stype == NULL ) {
      parsemsg( LOG_ERR, func, "inetd.conf - Invalid socket type" );
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }
   nvp = nv_find_value( socket_types, stype );
   if( nvp == NULL )
   {
      parsemsg( LOG_ERR, func, "inetd.conf - Bad socket type: %s", p);
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }

   SC_SOCKET_TYPE(scp) = nvp->value;

   /* Get the protocol type */
   proto = (char *)pset_pointer(args,2);
   if( strstr(proto, "rpc") != NULL )
   {
      int rpcmin, rpcmax;
      struct rpc_data *rdp = SC_RPCDATA( scp ) ;

      if( rpcvers == NULL ) {
         pset_destroy(args);
         sc_free(scp);
         return -1;
         /* uh oh */
      }

      p = strchr(rpcvers, '-');
      if( p && parse_int(rpcvers, 10, '-', &rpcmin) == 0 ) {
         if( parse_base10(p + 1, &rpcmax) || rpcmin > rpcmax ) {
            pset_destroy(args);
            sc_free(scp);
            return -1;
         }
      } else {
         if( parse_base10(rpcvers, &rpcmin) ) {
            pset_destroy(args);
            sc_free(scp);
            return -1;
         }

         rpcmax = rpcmin;
      }

      /* now have min and max rpc versions */
      rdp->rd_min_version = rpcmin;      
      rdp->rd_max_version = rpcmax;      

      rpcproto = strstr(proto, slash);
      if( rpcproto == NULL ) {
         parsemsg( LOG_ERR, func, "inetd.conf - bad rpc version numbers" );
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
      *rpcproto = '\0';
      rpcproto++;
      proto = rpcproto;

      /* Set the RPC type field */
      nvp = nv_find_value( service_types, "RPC" );
      if ( nvp == NULL )
      {
         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }

      M_SET(SC_TYPE(scp), nvp->value);
   }
   if ( ( pep = getprotobyname( proto ) ) == NULL )
   {
      parsemsg( LOG_ERR, func, "inetd.conf - Protocol %s not in /etc/protocols",
	        proto ) ;
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }

   SC_PROTONAME(scp) = new_string( proto ) ;
   if ( SC_PROTONAME(scp) == NULL )
   {
      out_of_memory( func ) ;
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }
   SC_PROTOVAL(scp) = pep->p_proto;
   SC_SPECIFY(scp, A_PROTOCOL);

   /* Get the wait attribute */
   p = (char *)pset_pointer(args, 3);
   if ( p == NULL ) {
      parsemsg( LOG_ERR, func, "inetd.conf - No value specified for wait" );
      sc_free(scp);
      return -1;
   }
   if ( EQ( p, "wait" ) )
      SC_WAIT(scp) = YES ;
   else if ( EQ( p, "nowait" ) )
      SC_WAIT(scp) = NO ;
   else
      parsemsg( LOG_ERR, func, "inetd.conf - Bad value for wait: %s", p ) ;

   /* Get the user to run as */
   p = (char *)pset_pointer(args, 4);
   if ( p == NULL ) {
      parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" );
      sc_free(scp);
      return -1;
   }
   if( (group = strstr(p, dot)) )
   {
      *group = '\0';
      group++;
   
      grp = (struct group *)getgrnam( (char *)group ) ;
      if ( grp == NULL )
      {
         parsemsg( LOG_ERR, func, "inetd.conf - Unknown group: %s", group ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }   

      SC_GID(scp) = ((struct group *)grp)->gr_gid;
      SC_SPECIFY( scp, A_GROUP );
   }

   pw = getpwnam( p );
   if ( pw == NULL )
   {
      parsemsg( LOG_ERR, func, "inetd.conf - Unknown user: %s", p ) ;
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }
   str_fill( pw->pw_passwd, ' ' );
   SC_UID(scp) = pw->pw_uid;
   SC_USER_GID(scp) = pw->pw_gid;

   /* Get server name, or flag as internal */
   p = (char *)pset_pointer(args, 5);
   if ( p == NULL ) {
      parsemsg( LOG_ERR, func, "inetd.conf - No value specified for user" );
      sc_free(scp);
      return -1;
   }
   if( EQ( p, "internal" ) ) 
   {
      nvp = nv_find_value( service_types, "INTERNAL" );
      if ( nvp == NULL )
      {
         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }

      M_SET(SC_TYPE(scp), nvp->value);

      if( EQ( SC_NAME(scp), "time" ) ) {
         if( EQ( proto, "stream" ) )
            SC_ID(scp) = new_string("time-stream");
         else
            SC_ID(scp) = new_string("time-dgram");
      }

      if( EQ( SC_NAME(scp), "daytime" ) ) {
         if( EQ( proto, "stream" ) )
            SC_ID(scp) = new_string("daytime-stream");
         else
            SC_ID(scp) = new_string("daytime-dgram");
      }

      if( EQ( SC_NAME(scp), "chargen" ) ) {
         if( EQ( proto, "stream" ) )
            SC_ID(scp) = new_string("chargen-stream");
         else
            SC_ID(scp) = new_string("chargen-dgram");
      }

      if( EQ( SC_NAME(scp), "echo" ) ) {
         if( EQ( proto, "stream" ) )
            SC_ID(scp) = new_string("echo-stream");
         else
            SC_ID(scp) = new_string("echo-dgram");
      }

      if( EQ( SC_NAME(scp), "discard" ) ) 
      {
         parsemsg(LOG_WARNING, func, 
		  "inetd.conf - service discard not supported");
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
   }
   else
   {
      SC_SERVER(scp) = new_string( p );
      if ( SC_SERVER(scp) == NULL )
      {
         out_of_memory( func ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
      SC_SPECIFY( scp, A_SERVER);

      /* Get argv */ 
      SC_SERVER_ARGV(scp) = (char **)argv_alloc(pset_count(args)+1);

      for( u = 0; u < pset_count(args)-6 ; u++ )
      {
         p = new_string((char *)pset_pointer(args, u+6));
         if( p == NULL )
         {
            for ( i = 1 ; i < u ; i++ )
               free( SC_SERVER_ARGV(scp)[i] );
            free( SC_SERVER_ARGV(scp) );
            pset_destroy(args);
            sc_free(scp);
            return -1;
         }
         SC_SERVER_ARGV(scp)[u] = p;
      }
      /* Set the reuse flag, as this is the default for inetd */
      nvp = nv_find_value( service_flags, "REUSE" );
      if ( nvp == NULL )
      {
         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
      M_SET(SC_XFLAGS(scp), nvp->value);

      /* Set the NOLIBWRAP flag, since inetd doesn't have libwrap built in */
      nvp = nv_find_value( service_flags, "NOLIBWRAP" );
      if ( nvp == NULL )
      {
         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
      M_SET(SC_XFLAGS(scp), nvp->value);
   
      /* Set the NAMEINARGS flag, as that's the default for inetd */
      nvp = nv_find_value( service_flags, "NAMEINARGS" );
      if ( nvp == NULL )
      {
         parsemsg( LOG_WARNING, func, "inetd.conf - Bad foo %s", name ) ;
         pset_destroy(args);
         sc_free(scp);
         return (-1);
      }
      M_SET(SC_XFLAGS(scp), nvp->value);
      SC_SPECIFY( scp, A_SERVER_ARGS );

      if ( (SC_ID(scp) = new_string( SC_NAME(scp) )) )
         SC_PRESENT( scp, A_ID ) ;
      else
      {
         out_of_memory( func ) ;
         pset_destroy(args);
         sc_free(scp);
         return -1;
      }
   }
   
   SC_SPECIFY( scp, A_PROTOCOL );
   SC_SPECIFY( scp, A_USER );
   SC_SPECIFY( scp, A_SOCKET_TYPE );
   SC_SPECIFY( scp, A_WAIT );

   if( ! pset_add(sconfs, scp) )
   {
      out_of_memory( func );
      pset_destroy(args);
      sc_free(scp);
      return -1;
   }

   pset_destroy(args);
   parsemsg( LOG_DEBUG, func, "added service %s", SC_NAME(scp));
   return 0;
}
Пример #3
0
/*
 * This function runs in the parent context and updates the global_no_access
 * list. 
 */
void process_sensor( const struct service *sp, const union xsockaddr *addr)
{
   const char *func = "process_sensor";

   if (SC_DENY_TIME(SVC_CONF(sp)) != 0)   /* 0 simply logs it   */
   {
      if ( pset_count( global_no_access ) < MAX_GLOBAL_NO_ACCESS)
      {
         int item_matched = addrlist_match( global_no_access, SA(addr) );

	 if ( item_matched == 0)
	 {   /* no match...adding to the list   */
            char *dup_addr = new_string(xaddrname( addr ) );

	    if (dup_addr == NULL )
               return ;

	    if (addrlist_add(global_no_access, dup_addr) == FAILED)
               msg(LOG_ERR, func,
                  "Failed adding %s to the global_no_access list", dup_addr);
            else
            {
               time_t nowtime;
               char time_buf[40], *tmp;

	       nowtime = time(NULL);
	       msg(LOG_CRIT, func,
	           "Adding %s to the global_no_access list for %d minutes",
	            dup_addr, SC_DENY_TIME(SVC_CONF(sp)));

	       if (SC_DENY_TIME(SVC_CONF(sp)) == -1)
                    strcpy(time_buf, "-1");
               else
                    strx_nprint(time_buf, 38, "%ld",
                       (time_t)nowtime+(60*SC_DENY_TIME(SVC_CONF(sp))));

	       tmp = new_string(time_buf);
               if (tmp != NULL)
               {
                  if (pset_add(global_no_access_time, tmp) == NULL)
                  {
                     msg(LOG_ERR, func,
                         "Failed adding %s to the global_no_access_time list. "
                         "global_no_access list is broken, xinetd needs "
			 "restarting.", dup_addr);
                 /* ideally, we should rollback the previous addr addition.   */
                  }
               }
	       if (pset_count(global_no_access) && (timer_id == 0) )
                  timer_id = xtimer_add( scrub_global_access_list, 60 );
            }
            free(dup_addr);
         }
         else
	 {
	    /* Here again, eh?...update time stamp. */
            char *exp_time;
	    time_t stored_time;

	    item_matched--; /* Is # plus 1, to even get here must be >= 1 */
            exp_time = pset_pointer( global_no_access_time, item_matched ) ;
            if (exp_time == NULL)
               return ;

            if ( parse_base10(exp_time, (int *)&stored_time) )
            {  /* if never let them off, bypass */
               if (stored_time != -1)
               {
                  time_t nowtime, new_time;

                  nowtime = time(NULL);
                  new_time = (time_t)nowtime+(60*SC_DENY_TIME(SVC_CONF(sp)));                     if (difftime(new_time, (time_t)stored_time) > 0.0)
	          {   /* new_time is longer save it   */
		     char time_buf[40], *new_exp_time;

		     strx_nprint(time_buf, 38, "%ld", (long)new_time);
		     new_exp_time = new_string(time_buf);
		     if ( new_exp_time )
		     {
		        free(exp_time);
			global_no_access_time->ptrs[ 
                        (unsigned)item_matched ] = new_exp_time;
                     }
                  }
               }
            }
         }
      }
      else
         msg(LOG_ERR, func, "Maximum global_no_access count reached.");
   }
}