static status_e udp_local_to_remote( channel_s *chp ) { char buf[ MAX_DATAGRAM_SIZE ] ; int cc ; const char *func = "udp_local_to_remote" ; for ( ;; ) { cc = recv( chp->ch_local_socket, buf, sizeof( buf ), 0 ) ; if ( cc == -1 ) { if ( errno != EINTR ) { msg( LOG_ERR, func, "recv from daemon: %m" ) ; return( FAILED ) ; } } else if ( cc == 0 ) return( FAILED ) ; else break ; } #ifdef DEBUG_UDPINT if ( debug.on ) msg( LOG_DEBUG, func, "sending %d bytes to address %s,%d", cc, xaddrname( &chp->ch_from ), ntohs( xaddrport(&chp->ch_from) ) ) ; #endif send_data( chp->ch_remote_socket, buf, cc, &chp->ch_from ) ; return( OK ) ; }
static status_e get_incoming_packet( struct intercept_s *ip, packet_s *pp ) { socklen_t from_len = 0; const char *func = "get_incoming_packet" ; if( SC_IPV4( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) ) from_len = sizeof( struct sockaddr_in ); if( SC_IPV6( SVC_CONF( SERVER_SERVICE( INT_SERVER( ip ) ) ) ) ) from_len = sizeof( struct sockaddr_in6 ); for ( ;; ) { int cc ; from_len = sizeof( pp->from ) ; cc = recvfrom( INT_REMOTE( ip ), pp->data, pp->size, 0, SA( &pp->from ), &from_len ) ; if ( cc == -1 ) { if ( errno != EINTR ) { msg( LOG_ERR, func, "recvfrom error: %m" ) ; return( FAILED ) ; } } else if ( cc == 0 ) return( FAILED ) ; else { pp->size = cc ; IDP( ip->int_priv )->received_packets++ ; break ; } } if ( from_len == 0 ) { msg( LOG_ERR, func, "incoming packet had 0 length address" ) ; return( FAILED ) ; } #ifdef DEBUG_UDPINT if ( debug.on ) msg( LOG_DEBUG, func, "Received %d bytes from address: %s,%d", pp->size, xaddrname( &pp->from ), ntohs( xaddrport(&pp->from) ) ); #endif return( OK ) ; }
/* This function gets called from child.c after we have been forked */ void redir_handler( struct server *serp ) { struct service *sp = SERVER_SERVICE( serp ); struct service_config *scp = SVC_CONF( sp ); int RedirDescrip = SERVER_FD( serp ); int maxfd, num_read, num_wrote=0, ret=0; unsigned int sin_len = 0; unsigned long bytes_in = 0, bytes_out = 0; int no_to_nagle = 1; int on = 1, v6on; char buff[NET_BUFFER]; fd_set rdfd, msfd; struct timeval *timep = NULL; const char *func = "redir_handler"; union xsockaddr serveraddr ; if( signal(SIGPIPE, redir_sigpipe) == SIG_ERR ) msg(LOG_ERR, func, "unable to setup signal handler"); close_all_svc_descriptors(); /* If it's a tcp service we are redirecting */ if( scp->sc_protocol.value == IPPROTO_TCP ) { memcpy(&serveraddr, scp->sc_redir_addr, sizeof(serveraddr)); if( serveraddr.sa_in.sin_family == AF_INET ) { sin_len = sizeof( struct sockaddr_in ); RedirServerFd = socket(AF_INET, SOCK_STREAM, 0); } else if( serveraddr.sa_in.sin_family == AF_INET6 ) { sin_len = sizeof( struct sockaddr_in6 ); RedirServerFd = socket(AF_INET6, SOCK_STREAM, 0); } else { msg(LOG_ERR, func, "not a valid protocol. Use IPv4 or IPv6."); exit(0); } if( RedirServerFd < 0 ) { msg(LOG_ERR, func, "cannot create socket: %m"); exit(0); } if( SC_IPV6( scp ) ) { if( SC_V6ONLY( scp ) ) { v6on = 1; } else { v6on = 0; } #ifdef IPV6_V6ONLY if( setsockopt(RedirServerFd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6on, sizeof(v6on)) < 0 ) { msg( LOG_ERR, func, "Setting IPV6_V6ONLY option failed (%m)" ); } #endif } if( SC_KEEPALIVE( scp ) ) if (setsockopt(RedirServerFd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof( on ) ) < 0 ) msg(LOG_ERR, func, "setsockopt SO_KEEPALIVE RedirServerFd failed: %m"); if( serveraddr.sa_in.sin_family == AF_INET ) serveraddr.sa_in.sin_port = htons(serveraddr.sa_in.sin_port); if( serveraddr.sa_in.sin_family == AF_INET6 ) serveraddr.sa_in6.sin6_port = htons(serveraddr.sa_in6.sin6_port); if( connect(RedirServerFd, &serveraddr.sa, sin_len) < 0 ) { msg(LOG_ERR, func, "can't connect to remote host %s: %m", xaddrname( &serveraddr ) ); exit(0); } /* connection now established */ if (setsockopt(RedirServerFd, IPPROTO_TCP, TCP_NODELAY, (char *) &no_to_nagle, sizeof( on ) ) < 0) { msg(LOG_ERR, func, "setsockopt RedirServerFd failed: %m"); } if (setsockopt(RedirDescrip, IPPROTO_TCP, TCP_NODELAY, (char *) &no_to_nagle, sizeof( on ) ) < 0) { msg(LOG_ERR, func, "setsockopt RedirDescrip failed: %m"); } maxfd = (RedirServerFd > RedirDescrip)?RedirServerFd:RedirDescrip; FD_ZERO(&msfd); FD_SET(RedirDescrip, &msfd); FD_SET(RedirServerFd, &msfd); while(1) { memcpy(&rdfd, &msfd, sizeof(rdfd)); if (select(maxfd + 1, &rdfd, (fd_set *)0, (fd_set *)0, timep) <= 0) { /* place for timeout code, currently does not time out */ break; } if (FD_ISSET(RedirDescrip, &rdfd)) { do { num_read = read(RedirDescrip, buff, sizeof(buff)); if (num_read == -1 && errno == EINTR) continue; if (num_read <= 0) goto REDIROUT; bytes_in += num_read; } while (num_read < 0); /* Loop until we have written everything * that was read */ num_wrote = 0; while( num_wrote < num_read ) { ret = write(RedirServerFd, buff + num_wrote, num_read - num_wrote); if (ret == -1 && errno == EINTR) continue; if (ret <= 0) goto REDIROUT; num_wrote += ret; } } if (FD_ISSET(RedirServerFd, &rdfd)) { do { num_read = read(RedirServerFd, buff, sizeof(buff)); if (num_read == -1 && errno == EINTR) continue; if (num_read <= 0) goto REDIROUT; bytes_out += num_read; } while (num_read < 0); /* Loop until we have written everything * that was read */ num_wrote = 0; while( num_wrote < num_read ) { ret = write(RedirDescrip, buff + num_wrote, num_read - num_wrote); if (ret == -1 && errno == EINTR) continue; if (ret <= 0) goto REDIROUT; num_wrote += ret; } } } REDIROUT: if( M_IS_SET( (scp)->sc_log_on_success, LO_TRAFFIC ) ) { svc_logprint( SERVER_CONNSERVICE( serp ), "TRAFFIC", "in=%lu(bytes) out=%lu(bytes)", bytes_in, bytes_out ); } exit(0); } msg(LOG_ERR, func, "redirect with any protocol other than tcp is not supported at this time."); exit(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."); } }
/* * 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 ) ; }