Пример #1
0
/*
 * Generate the current time using the SMTP format:
 *      02 FEB 1991 12:31:42 MST
 *
 * The result is placed in buf.
 * buflen is a value-result parameter. It indicates the size of
 * buf and on exit it has the length of the string placed in buf.
 */
static void daytime_protocol( char *buf, unsigned int *buflen )
{
   static const char *month_name[] =
      {
         "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
         "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
      } ;
   time_t      now ;
   struct tm   *tmp ;
   int         size = *buflen ;
#ifdef HAVE_STRFTIME
   int      cc ;
#endif

   (void) time( &now ) ;
   tmp = localtime( &now ) ;
#ifndef HAVE_STRFTIME
   strx_print( buflen, buf, size,
      "%02d %s %d %02d:%02d:%02d %s\r\n",
         tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
            tmp->tm_hour, tmp->tm_min, tmp->tm_sec, tmp->tm_zone ) ;
#else
   cc = strx_nprint( buf, size,
      "%02d %s %d %02d:%02d:%02d",
         tmp->tm_mday, month_name[ tmp->tm_mon ], 1900 + tmp->tm_year,
            tmp->tm_hour, tmp->tm_min, tmp->tm_sec ) ;
   if ( cc >= 0 ) { 
      *buflen = cc ;
      size -= cc ;
      cc = strftime( &buf[ *buflen ], size, " %Z\r\n", tmp ) ;
      *buflen += cc ;
   }
#endif
}
Пример #2
0
int
APPEND (FUNC_PREFIX, fcvt_r) (FLOAT_TYPE value, 
                              int ndigit, 
                              int *decpt, 
                              int *sign, 
                              char *buf, 
                              size_t len)
{
   int n, i;
   int left;

   if (buf == NULL) {
      __set_errno (EINVAL);
      return -1;
   }

   left = 0;
   if (!ISINF (value) && !ISNAN (value)) {
      /* OK, the following is not entirely correct.  -0.0 is not handled
       * correctly but glibc 2.0 does not have a portable function to
       * implement this test.  
       */
       *sign = value < 0.0;
       if (*sign)
          value = -value;

       if (ndigit < 0) {
          /* Rounding to the left of the decimal point.  */
          while (ndigit < 0) {
             FLOAT_TYPE new_value = value * 0.1;

             if (new_value < 1.0) {
                ndigit = 0;
                break;
             }

             value = new_value;
             ++left;
             ++ndigit;
          }
       }
    } else {
       /* Value is Inf or NaN.  */
       *sign = 0;
    }

    n = strx_nprint (buf, len, "%.*" FLOAT_FMT_FLAG "f", ndigit, value);
    if (n < 0)
       return -1;

    i = 0;
    while (i < n && isdigit (buf[i]))
       ++i;
    *decpt = i;

    if (i == 0)
       /* Value is Inf or NaN.  */
       return 0;

    if (i < n) {
       do
       ++i;
       while (i < n && !isdigit (buf[i]));

       if (*decpt == 1 && buf[0] == '0' && value != 0.0) {
          /* We must not have leading zeroes.  Strip them all out and
           * adjust *DECPT if necessary.  */
          --*decpt;
          while (i < n && buf[i] == '0')
          {
             --*decpt;
             ++i;
          }
       }

       memmove (&buf[MAX (*decpt, 0)], &buf[i], n - i);
       buf[n - (i - MAX (*decpt, 0))] = '\0';
    }

    if (left) {
       *decpt += left;
       if (--len > n) {
          while (left-- > 0 && n < len)
             buf[n++] = '0';
          buf[n] = '\0';
       }
    }

    return 0;
}
Пример #3
0
/*
 * 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 */
}
Пример #4
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.");
   }
}
Пример #5
0
/*
 * This function always runs in a forked process.
 */
idresult_e log_remote_user( const struct server *serp, unsigned timeout )
{
    static char         buf[ IBUFSIZE ] ;
    int                 cc ;
    union xsockaddr     sin_local, sin_remote, sin_contact, sin_bind;
    volatile unsigned   local_port;
    volatile unsigned   remote_port;
    int                 sd ;
    socklen_t           sin_len ;
    char               *p ;
    const char         *func = "log_remote_user" ;

    if ( timeout && signal( SIGALRM, sigalrm_handler ) == SIG_ERR )
    {
        msg( LOG_ERR, func, "signal: %m" ) ;
        return( IDR_ERROR ) ;
    }

    /*
     * Determine local and remote addresses
     */
    sin_len = sizeof( sin_local ) ;
    if ( getsockname( SERVER_FD( serp ), &sin_local.sa, &sin_len ) == -1 )
    {
        msg( LOG_ERR, func, "(%d) getsockname: %m", getpid() ) ;
        return( IDR_ERROR ) ;
    }

    if ( CONN_XADDRESS( SERVER_CONNECTION( serp ) ) == NULL )
    {
        /*
         * This shouldn't happen since identification only works for
         * connection-based services.
         */
        msg( LOG_ERR, func, "connection has no address" ) ;
        return( IDR_ERROR ) ;
    }

    CLEAR( sin_contact );
    sin_remote = *CONN_XADDRESS( SERVER_CONNECTION( serp ) ) ;
    sin_contact = sin_remote;
    memcpy( &sin_bind, &sin_local, sizeof(sin_bind) ) ;
    local_port = 0;
    remote_port = 0;
    if( sin_remote.sa.sa_family == AF_INET ) {
        local_port = ntohs( sin_local.sa_in6.sin6_port ) ;
        remote_port = ntohs( sin_remote.sa_in6.sin6_port ) ;
        sin_contact.sa_in6.sin6_port = htons( IDENTITY_SERVICE_PORT ) ;
        sin_bind.sa_in.sin_port = 0 ;
    } else if( sin_remote.sa.sa_family == AF_INET6 ) {
        local_port = ntohs( sin_local.sa_in.sin_port ) ;
        remote_port = ntohs( sin_remote.sa_in.sin_port ) ;
        sin_contact.sa_in.sin_port = htons( IDENTITY_SERVICE_PORT ) ;
        sin_bind.sa_in6.sin6_port = 0 ;
    }

    /*
     * Create a socket, bind it, and set the close-on-exec flag on the
     * descriptor. We set the flag in case we are called as part of a
     * successful attempt to start a server (i.e. execve will follow).
     * The socket must be bound to the receiving address or ident might
     * fail for multi-homed hosts.
     */
    sd = socket( sin_remote.sa.sa_family, SOCK_STREAM, 0 ) ;
    if ( sd == -1 )
    {
        msg( LOG_ERR, func, "socket creation: %m" ) ;
        return( IDR_ERROR ) ;
    }
    if ( bind(sd, &sin_bind.sa, sizeof(sin_bind.sa)) == -1 )
    {
        msg( LOG_ERR, func, "socket bind: %m" ) ;
        (void) Sclose( sd ) ;
        return( IDR_ERROR ) ;
    }
    if ( fcntl( sd, F_SETFD, FD_CLOEXEC ) == -1 )
    {
        msg( LOG_ERR, func, "fcntl F_SETFD: %m" ) ;
        (void) Sclose( sd ) ;
        return( IDR_ERROR ) ;
    }

    if ( timeout ) {
        if ( sigsetjmp( env, 1 ) == 0 )
            START_TIMER( timeout ) ;
        else {
            Sclose( sd ) ;
            return( IDR_TIMEDOUT ) ;
        }
    }

    if ( connect( sd, &sin_contact.sa, sizeof( sin_contact ) ) == -1 )
    {
        if ( timeout ) {
            STOP_TIMER() ;
            signal ( SIGALRM, SIG_DFL ) ;
        }
        Sclose( sd );
        return( IDR_NOSERVER ) ;
    }

    cc = strx_nprint( buf, sizeof( buf ),
                      "%d,%d\r\n", remote_port, local_port ) ;
    if ( write_buf( sd, buf, cc ) == FAILED )
    {
        if ( timeout ) {
            STOP_TIMER() ;
            signal ( SIGALRM, SIG_DFL ) ;
        }
        Sclose( sd );
        return( IDR_ERROR ) ;
    }

    p = get_line( sd, buf, sizeof( buf ) ) ;

    if ( timeout ) {
        STOP_TIMER() ;
        signal ( SIGALRM, SIG_DFL ) ;
    }

    if ( p == NULL ) {
        Sclose( sd );
        return( IDR_RESPERR ) ;
    }

    /*
     * Verify that the received line is OK
     */
    if ( ( p = verify_line( buf, local_port, remote_port ) ) == NULL )
    {
        msg(LOG_ERR, func, "Bad line received from identity server at %s: %s",
            xaddrname( &sin_remote ), buf ) ;
        Sclose( sd );
        return( IDR_BADRESP ) ;
    }

    svc_logprint( SERVER_CONNSERVICE( serp ), USERID_ENTRY, "%s", p ) ;
    return( IDR_OK ) ;
}