This file is indexed.

/usr/share/perl5/Mail/SRS/Daemon.pm is in libmail-srs-perl 0.31-5.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
package Mail::SRS::Daemon;

use strict;
use warnings;
use vars qw(@ISA @EXPORT_OK %EXPORT_TAGS $SRSSOCKET);
use Exporter;
use IO::Socket;
use IO::Select;
use Getopt::Long;
use Mail::SRS qw(:all);

@ISA = qw(Exporter);

@EXPORT_OK = qw($SRSSOCKET);
%EXPORT_TAGS = (
		all	=> \@EXPORT_OK,
			);

$SRSSOCKET = '/tmp/srsd';

sub new {
	my $class = shift;
	my $args = ($#_ == 0) ? %{ (shift) } : { @_ };

	my @secrets = ref($args->{Secret}) eq 'ARRAY'
					? @{ $args->{Secret} }
					: [ $args->{Secret} ];

	if (exists $args->{SecretFile} && defined $args->{SecretFile}) {
		my $secretfile = $args->{SecretFile};
		die "Secret file $secretfile not readable"
						unless -r $secretfile;
		local *FH;
		open(FH, "<$secretfile")
						or die "Cannot open $secretfile: $!";
		while (<FH>) {
			next unless /\S/;
			next if /^#/;
			push(@secrets, $_);
		}
		close(FH);
	}

	die "No secret or secretfile given. Use --secret or --secretfile, ".
					"and ensure the secret file is not empty."
						unless @secrets;

	# Preserve the pertinent original arguments, mostly for fun.
	my $self = {
		Secret		=> $args->{Secret},
		SecretFile	=> $args->{SecretFile},
			};
	$self->{Socket} = delete $args->{Socket} if exists $args->{Socket};

	# An alternative pattern would be to inherit this, rather than
	# delegate to it.
	$args->{Secret} = \@secrets;
	# All other args are passed on verbatim.
	my $srs = new Mail::SRS($args);

	$self->{Instance} = $srs;

	return bless $self, $class;
}

sub run {
	my ($self) = @_;
	my $srs = $self->{Instance};

	print STDERR "Starting SRS daemon in PID $$\n";

	# Until we decide that forward() and reverse() can die, this will
	# allow us to trap the error messages from those subroutines.
	local $SIG{__WARN__} = sub { die @_; };

	my $listen = $self->{Socket};
	unless ($listen) {
		unlink($SRSSOCKET) if -e $SRSSOCKET;
		$listen ||= new IO::Socket::UNIX(
						Type	=> SOCK_STREAM,
						Local	=> $SRSSOCKET,
						Listen	=> 1,
							);
		die "Unable to create listen socket: $!" unless $listen;
	}

	my $select = new IO::Select();
	$select->add($listen);

	while (my @socks = $select->can_read) {
		foreach my $sock (@socks) {
			if ($sock == $listen) {
				# print "Accept on $sock\n";
				$select->add($listen->accept());
			}
			else {
				my $line = <$sock>;
				if (defined($line)) {
					chomp($line);
					# print "Read '$line' on $sock\n";
					my @args = split(/\s+/, $line);
					my $cmd = uc shift @args;
					eval {
						if ($cmd eq 'FORWARD') {
							$sock->print($srs->forward(@args), "\n");
						}
						elsif ($cmd eq 'REVERSE') {
							$sock->print($srs->reverse(@args), "\n");
						}
						else {
							die "Invalid command $cmd";
						}
					};
					if ($@) {
						$sock->print("ERROR: $@");
						$select->remove($sock);
						$sock->close();
					}
				}

				# Exim requires that we unconditionally close the socket
				# print "Close on $sock\n";
				$select->remove($sock);
				$sock->flush();
				$sock->close();
				undef $sock;
			}
		}
		my @exc = $select->has_exception(0);
		foreach my $sock (@exc) {
			# print "Exception on $sock\n";
			$select->remove($sock);
			$sock->close();
		}
	}
}

__END__

=head1 NAME

Mail::SRS::Daemon - modular daemon for Mail::SRS

=head1 SYNOPSIS

my $daemon = new Mail::SRS::Daemon(
	SecretFile  => $secretfile,
	Separator   => $separator,
		);
$daemon->run();

=head1 DESCRIPTION

The SRS daemon listens on a socket for SRS address transformation
requests. It transforms the addresses and returns the new addresses
on the socket.

It may be invoked from exim using ${readsocket ...}, and probably
from other MTAs as well. See http://www.anarres.org/projects/srs/
for examples.

=head1 METHODS

=head2 $daemon = new Mail::SRS::Daemon(...)

Construct a new Mail::SRS object and return it.  All parameters which
are valid for Mail::SRS are also valid for Mail::SRS::Daemon and will
be passed to the constructor of Mail::SRS verbatim. The exception to
this rule is the Secret parameter, which will be promoted to a list
and will have all secrets from SecretFile included. New parameters
are documented here. See L<Mail::SRS> for the rest.

=over 4

=item SecretFile => $string

A file to read for secrets. Secrets are specified once per line. The
first specified secret is used for encoding. Secrets are written
one per line. Blank lines and lines starting with a # are ignored.
If Secret is not given, then the secret file must be nonempty.

Secret will specify a primary secret and override SecretFile if both
are specified. However, secrets read from SecretFile still be used
for decoding if both are specified.

=item Socket => $socket

An instance of IO::Socket, presumed to be a listening socket. This
may be provided in order to use a preexisting socket, rather than have
Mail::SRS::Daemon construct a new socket.

=back

=head2 $daemon->run()

Run the daemon. This method will never return. Errors and exceptions
are caught, and error messages are returned down the socket.

=head1 EXPORTS

Given :all, this module exports the following variables.

=over 4

=item $SRSSOCKET

The filename of the default socket created by Mail::SRS::Daemon.

=back

=head1 PROTOCOL

The daemon waits for a single line of text from the client, and will
respond with a single line. The lines are all of the form "COMMAND
args...". Currently, two commands are supported: forward and reverse.

A forward request looks like:

	FORWARD sender@source.com alias@forwarder.com

A reverse request looks like:

	REVERSE srs0+HHH=TT=domain=local-part@forwarder.com

In either case, the daemon will respond with either a translated
address, or a line starting "ERROR ", followed by a message.

=head1 TODO

Add more daemon-related options, such as path to socket, or inet
socket address.

=head1 SEE ALSO

L<Mail::SRS>, L<srsd>, http://www.anarres.org/projects/srs/

=head1 AUTHOR

    Shevek
    CPAN ID: SHEVEK
    cpan@anarres.org
    http://www.anarres.org/projects/

=head1 COPYRIGHT

Copyright (c) 2004 Shevek. All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

1;
__END__