Ticket #107: unix_socket.patch

File unix_socket.patch, 11.3 KB (added by naoki iimura, 14 years ago)

Patch for supporting unix sockets

  • Proxy/Proxy.pm

     
    111111    $self->config_( 'socks_server', '' );
    112112    $self->config_( 'socks_port',   1080 );
    113113
     114    # The name of the unix socket used for proxy service
     115    # If it is '', inet sockets are used.
     116    # If it is not '', unix sockets are used.
     117
     118    $self->config_( 'unix_socket', '' );
     119
    114120    return 1;
    115121}
    116122
     
    128134{
    129135    my ( $self ) = @_;
    130136
    131     # Open the socket used to receive request for proxy service
    132     $self->log_( 1, "Opening listening socket on port " . $self->config_('port') . '.' );
    133     $self->{server__} = IO::Socket::INET->new( Proto     => 'tcp', # PROFILE BLOCK START
    134                                     ($self->config_( 'local' ) || 0) == 1 ? (LocalAddr => 'localhost') : (),
    135                                     LocalPort => $self->config_( 'port' ),
    136                                     Listen    => SOMAXCONN,
    137                                     Reuse     => 1 ); # PROFILE BLOCK STOP
    138 
    139137    my $name = $self->name();
     138    my $unix_socket = $self->config_( 'unix_socket' );
    140139
    141     if ( !defined( $self->{server__} ) ) {
     140    if ( !$unix_socket ) {
     141
    142142        my $port = $self->config_( 'port' );
    143         print STDERR <<EOM; # PROFILE BLOCK START
     143        my $local = ( ( $self->config_( 'local' ) || 0 ) == 1 );
    144144
    145 \nCouldn't start the $name proxy because POPFile could not bind to the
     145        # Open the inet socket used to receive request for proxy service
     146
     147        $self->log_( 1, "Opening listening socket for $name proxy on port $port." );
     148
     149        $self->{server__} = IO::Socket::INET->new(  # PROFILE BLOCK START
     150                Proto     => 'tcp',
     151                ( $local ? ( LocalAddr => 'localhost' ) : () ),
     152                LocalPort => $port,
     153                Listen    => SOMAXCONN,
     154                Reuse     => 1
     155        );                                          # PROFILE BLOCK STOP
     156
     157        if ( !defined( $self->{server__} ) ) {
     158            print STDERR <<EOM; # PROFILE BLOCK START
     159
     160\nCouldn\'t start the $name proxy because POPFile could not bind to the
    146161listen port $port. This could be because there is another service
    147162using that port or because you do not have the right privileges on
    148163your system (On Unix systems this can happen if you are not root
    149164and the port you specified is less than 1024).
     165The original error message: $!
    150166
    151167EOM
    152168# PROFILE BLOCK STOP
    153         return 0;
     169            return 0;
     170        }
     171    } else {
     172
     173        unlink $unix_socket if ( -e $unix_socket );
     174
     175        # Open the unix socket to receive request for proxy service
     176
     177        $self->log_( 1, "Opening listening socket for $name proxy on unix socket $unix_socket." );
     178
     179        $self->{server__} = IO::Socket::UNIX->new(  # PROFILE BLOCK START
     180                Type      => SOCK_STREAM,
     181                Local     => $unix_socket,
     182                Listen    => SOMAXCONN,
     183        );                                          # PROFILE BLOCK STOP
     184
     185        if ( !defined( $self->{server__} ) ) {
     186            print STDERR <<EOM; # PROFILE BLOCK START
     187
     188\nCouldn\'t start the $name proxy because POPFile could not bind to the
     189unix socket $unix_socket. This could be because there is another
     190service using that socket or because you do not have the right
     191privileges on your system.
     192The original error message: $!
     193
     194EOM
     195# PROFILE BLOCK STOP
     196            return 0;
     197        }
    154198    }
    155199
    156200    # This is used to perform select calls on the $server socket so that we can decide when there is
     
    233277            # further processing.  We don't want to act as a proxy for
    234278            # just anyone's email
    235279
    236             my ( $remote_port, $remote_host ) = sockaddr_in(                # PROFILE BLOCK START
    237                                                     $client->peername() );  # PROFILE BLOCK STOP
     280            my $acceptable = 0;
    238281
    239             if  ( ( ( $self->config_( 'local' ) || 0 ) == 0 ) ||        # PROFILE BLOCK START
    240                     ( $remote_host eq inet_aton( "127.0.0.1" ) ) ) {    # PROFILE BLOCK STOP
     282            if ( ref $client eq 'IO::Socket::UNIX' ) {
    241283
     284                # Connection to the unix socket is always acceptable
     285                # because unix sockets are connected from localhost
     286                # only
     287
     288                $acceptable = 1;
     289            } else {
     290
     291                my ( $remote_port, $remote_host ) = sockaddr_in(           # PROFILE BLOCK START
     292                                                    $client->peername() ); # PROFILE BLOCK STOP
     293
     294                $acceptable = ( ( ( $self->config_( 'local' ) || 0 ) == 0 ) ||  # PROFILE BLOCK START
     295                                ( $remote_host eq inet_aton( "127.0.0.1" ) ) ); # PROFILE BLOCK STOP
     296            }
     297
     298            if ( $acceptable ) {
     299
    242300                # If we have force_fork turned on then we will do a
    243301                # fork, otherwise we will handle this inline, in the
    244302                # inline case we need to create the two ends of a pipe
     
    485543# $port        The port
    486544# $ssl         If set to 1 then the connection to the remote is established
    487545#              using SSL
     546# $unix_socket If it is not '', connect to the unix socket
    488547#
    489548# Check that we are connected to $hostname on port $port putting the
    490549# open handle in $mail.  Any messages need to be sent to $client
     
    492551# ----------------------------------------------------------------------------
    493552sub verify_connected_
    494553{
    495     my ( $self, $mail, $client, $hostname, $port, $ssl ) = @_;
     554    my ( $self, $mail, $client, $hostname, $port, $ssl, $unix_socket ) = @_;
    496555
    497556    $ssl = 0 if ( !defined( $ssl ) );
    498557
    499558    # Check to see if we are already connected
     559
    500560    return $mail if ( $mail && $mail->connected );
    501561
    502562    # Connect to the real mail server on the standard port, if we are using
     
    506566        require IO::Socket::Socks;
    507567        $self->log_( 0, "Attempting to connect to socks server at " # PROFILE BLOCK START
    508568                    . $self->config_( 'socks_server' ) . ":"
    509                     . ProxyPort => $self->config_( 'socks_port' ) ); # PROFILE BLOCK STOP
     569                    . $self->config_( 'socks_port' ) );            # PROFILE BLOCK STOP
    510570
    511         $mail = IO::Socket::Socks->new( # PROFILE BLOCK START
     571        $mail = IO::Socket::Socks->new(      # PROFILE BLOCK START
    512572                    ProxyAddr => $self->config_( 'socks_server' ),
    513573                    ProxyPort => $self->config_( 'socks_port' ),
    514574                    ConnectAddr  => $hostname,
     
    605665            }
    606666
    607667        } else {
    608             $self->log_( 0, "Attempting to connect to POP server at " # PROFILE BLOCK START
    609                         . "$hostname:$port" ); # PROFILE BLOCK STOP
     668            if ( $unix_socket ) {
    610669
    611             $mail = IO::Socket::INET->new( # PROFILE BLOCK START
     670                $self->log_( 0, "Attempting to connect to unix socket at $unix_socket" );
     671
     672                $mail = IO::Socket::UNIX->new(  # PROFILE BLOCK START
     673                        Type     => SOCK_STREAM,
     674                        Peer     => $unix_socket,
     675                        Timeout  => $self->global_config_( 'timeout' ),
     676                );                              # PROFILE BLOCK STOP
     677
     678            } else {
     679
     680                $self->log_( 0, "Attempting to connect to POP server at " # PROFILE BLOCK START
     681                            . "$hostname:$port" ); # PROFILE BLOCK STOP
     682
     683                $mail = IO::Socket::INET->new( # PROFILE BLOCK START
    612684                        Proto    => "tcp",
    613685                        PeerAddr => $hostname,
    614686                        PeerPort => $port,
    615687                        Timeout  => $self->global_config_( 'timeout' ),
    616             ); # PROFILE BLOCK STOP
     688                ); # PROFILE BLOCK STOP
     689
     690            }
    617691        }
    618692    }
    619693
     
    621695    if ( $mail ) {
    622696        if ( $mail->connected )  {
    623697
    624             $self->log_( 0, "Connected to $hostname:$port timeout " . $self->global_config_( 'timeout' ) );
     698            if ( $unix_socket ) {
     699                $self->log_( 0, "Connected to $unix_socket timeout " . $self->global_config_( 'timeout' ) );
     700            } else {
     701                $self->log_( 0, "Connected to $hostname:$port timeout " . $self->global_config_( 'timeout' ) );
     702            }
    625703
    626704            # Set binmode on the socket so that no translation of CRLF
    627705            # occurs
     
    690768        }
    691769    }
    692770
    693     $self->log_( 0, "IO::Socket::INET or IO::Socket::SSL gets an error: $!" );
     771    $self->log_( 0, "IO::Socket::* gets an error: $!" );
    694772
    695773    # Tell the client we failed
    696     $self->tee_(  $client, "$self->{connection_failed_error_} $hostname:$port$eol" );
     774    if ( $unix_socket ) {
     775        $self->tee_( $client, "$self->{connection_failed_error_} $unix_socket$eol" );
     776    } else {
     777        $self->tee_( $client, "$self->{connection_failed_error_} $hostname:$port$eol" );
     778    }
    697779
    698780    return undef;
    699781}
  • Proxy/SMTP.pm

     
    7979    $self->config_( 'chain_server', '' );
    8080    $self->config_( 'chain_port', 25 );
    8181
     82    # Forward on to unix socket
     83    $self->config_( 'chain_unix_socket', '' );
     84
    8285    # Only accept connections from the local machine for smtp
    8386    $self->config_( 'local', 1 );
    8487
     
    183186        $self->log_( 2, "Command: --$command--" );
    184187
    185188        if ( $command =~ /HELO/i ) {
    186             if ( $self->config_( 'chain_server' ) )  {
    187                 if ( $mail = $self->verify_connected_( $mail, $client, $self->config_( 'chain_server' ),  $self->config_( 'chain_port' ) ) )  {
     189            if ( $self->config_( 'chain_server' ) ||        # PROFILE BLOCK START
     190                 $self->config_( 'chain_unix_socket' ) )  { # PROFILE BLOCK STOP
     191                if ( $mail = $self->verify_connected_(               # PROFILE BLOCK START
     192                        $mail,
     193                        $client,
     194                        $self->config_( 'chain_server' ),
     195                        $self->config_( 'chain_port' ),
     196                        0,
     197                        $self->config_( 'chain_unix_socket' ) ) )  { # PROFILE BLOCK STOP
    188198
    189199                    $self->smtp_echo_response_( $mail, $client, $command );
    190200                } else {
     
    200210        # Handle EHLO specially so we can control what ESMTP extensions are negotiated
    201211
    202212        if ( $command =~ /EHLO/i ) {
    203             if ( $self->config_( 'chain_server' ) )  {
    204                 if ( $mail = $self->verify_connected_( $mail, $client, $self->config_( 'chain_server' ),  $self->config_( 'chain_port' ) ) )  {
     213            if ( $self->config_( 'chain_server' ) ||        # PROFILE BLOCK START
     214                 $self->config_( 'chain_unix_socket' ) )  { # PROFILE BLOCK STOP
     215                if ( $mail = $self->verify_connected_(               # PROFILE BLOCK START
     216                        $mail,
     217                        $client,
     218                        $self->config_( 'chain_server' ),
     219                        $self->config_( 'chain_port' ),
     220                        0,
     221                        $self->config_( 'chain_unix_socket' ) ) )  { # PROFILE BLOCK STOP
    205222
    206223                    # TODO: Make this user-configurable (-smtp_add_unsupported, -smtp_remove_unsupported)
    207224