1NAME
2 RPC::PlServer - Perl extension for writing PlRPC servers
3
4SYNOPSIS
5 # Create a subclass of RPC::PlServer
6 use RPC::PlServer;
7
8 package MyServer;
9 $MyServer::VERSION = '0.01';
10 @MyServer::ISA = qw(RPC::PlServer);
11
12 # Overwrite the Run() method to handle a single connection
13 sub Run {
14 my $self = shift;
15 my $socket = $self->{'socket'};
16 }
17
18 # Create an instance of the MyServer class
19 package main;
20 my $server = MyServer->new({'localport' => '1234'}, \@ARGV);
21
22 # Bind the server to its port to make it actually running
23 $server->Bind();
24
25DESCRIPTION
26 PlRPC (Perl RPC) is a package for implementing servers and clients that
27 are written in Perl entirely. The name is borrowed from Sun's RPC
28 (Remote Procedure Call), but it could as well be RMI like Java's "Remote
29 Method Interface), because PlRPC gives you the complete power of Perl's
30 OO framework in a very simple manner.
31
32 RPC::PlServer is the package used on the server side, and you guess what
33 RPC::PlClient is for. Both share the package RPC::PlServer::Comm for
34 communication purposes. See PlRPC::Client(3) and RPC::PlServer::Comm for
35 these parts.
36
37 PlRPC works by defining a set of methods that may be executed by the
38 client. For example, the server might offer a method "multiply" to the
39 client. Now the clients method call
40
41 @result = $client->multiply($a, $b);
42
43 will be immediately mapped to a method call
44
45 @result = $server->multiply($a, $b);
46
47 on the server. The arguments and results will be transferred to or from
48 the server automagically. (This magic has a name in Perl: It's the
49 Storable module, my thanks to Raphael Manfredi for this excellent
50 package.) Simple, eh? :-)
51
52 The RPC::PlServer and RPC::PlClient are abstract servers and clients:
53 You have to derive your own classes from it.
54
55 Additional options
56 The RPC::PlServer inherits all of Net::Daemon's options and attributes
57 and adds the following:
58
59 *cipher*
60 The attribute value is an instance of Crypt::DES, Crypt::IDEA or
61 any other class with the same API for block encryption. If you
62 supply such an attribute, the traffic between client and server
63 will be encrypted using this option.
64
65 *maxmessage* (--maxmessage=size)
66 The size of messages exchanged between client and server is
67 restricted, in order to omit denial of service attacks. By
68 default the limit is 65536 bytes.
69
70 users This is an attribute of the client object used for Permit/Deny
71 rules in the config file. It's value is an array ref of user
72 names that are allowed to connect from the given client. See the
73 example config file below. "CONFIGURATION FILE".
74
75 Error Handling
76 Error handling is simple with the RPC package, because it is based on
77 Perl exceptions completely. Thus your typical code looks like this:
78
79 eval {
80 # Do something here. Don't care for errors.
81 ...
82 };
83 if ($@) {
84 # An error occurred.
85 ...
86 }
87
88 Server Constructors
89 my $server = RPC::PlServer(\%options, \@args);
90
91 (Class method) This constructor is immediately inherited from the
92 Net::Daemon package. See Net::Daemon(3) for details.
93
94 Access Control
95 $ok = $self->AcceptApplication($app);
96 $ok = $self->AcceptVersion($version);
97 $ok = $self->AcceptUser($user, $password);
98
99 The RPC::PlServer package has a very detailed access control scheme:
100 First of all it inherits Net::Daemon's host based access control. It
101 adds version control and user authorization. To achieve that, the method
102 *Accept* from Net::Daemon is split into three methods,
103 *AcceptApplication*, *AcceptVersion* and *AcceptUser*, each of them
104 returning TRUE or FALSE. The client receives the arguments as the
105 attributes *application*, *version*, *user* and *password*. A client is
106 accepted only if all of the above methods are returning TRUE.
107
108 The default implementations are as follows: The AcceptApplication method
109 returns TRUE, if $self is a subclass of $app. The AcceptVersion method
110 returns TRUE, if the requested version is less or equal to
111 ${$class}::VERSION, $self being an instance of $class. Whether a user is
112 permitted to connect depends on the client configuration. See
113 "CONFIGURATION FILE" below for examples.
114
115 Method based access control
116 Giving a client the ability to invoke arbitrary methods can be a
117 terrible security hole. Thus the server has a *methods* attribute. This
118 is a hash ref of class names as keys, the values being hash refs again
119 with method names as the keys. That is, if your hash looks as follows:
120
121 $self->{'methods'} = {
122 'CalcServer' => {
123 'NewHandle' => 1,
124 'CallMethod' => 1 },
125 'Calculator' => {
126 'new' => 1,
127 'multiply' => 1,
128 'add' => 1,
129 'divide' => 1,
130 'subtract' => 1 }
131 };
132
133 then the client may use the CalcServer's *NewHandle* method to create
134 objects, but only via the permitted constructor Calculator->new. Once a
135 Calculator object is created, the server may invoke the methods
136 multiply, add, divide and subtract.
137
138CONFIGURATION FILE
139 The server config file is inherited from Net::Daemon. It adds the
140 *users* and *cipher* attribute to the client list. Thus a typical config
141 file might look as follows:
142
143 # Load external modules; this is not required unless you use
144 # the chroot() option.
145 #require DBD::mysql;
146 #require DBD::CSV;
147
148 # Create keys
149 my $myhost_key = Crypt::IDEA->new('83fbd23390ade239');
150 my $bob_key = Crypt::IDEA->new('be39893df23f98a2');
151
152 {
153 # 'chroot' => '/var/dbiproxy',
154 'facility' => 'daemon',
155 'pidfile' => '/var/dbiproxy/dbiproxy.pid',
156 'user' => 'nobody',
157 'group' => 'nobody',
158 'localport' => '1003',
159 'mode' => 'fork',
160
161 # Access control
162 'clients' => [
163 # Accept the local LAN (192.168.1.*)
164 {
165 'mask' => '^192\.168\.1\.\d+$',
166 'accept' => 1,
167 'users' => [ 'bob', 'jim' ],
168 'cipher' => $myhost_key
169 },
170 # Accept myhost.company.com
171 {
172 'mask' => '^myhost\.company\.com$',
173 'accept' => 1,
174 'users' => [ {
175 'name' => 'bob',
176 'cipher' => $bob_key
177 } ]
178 },
179 # Deny everything else
180 {
181 'mask' => '.*',
182 'accept' => 0
183 }
184 ]
185 }
186
187 Things you should note: The user list of 192.168.1.* contains scalar
188 values, but the user list of myhost.company.com contains hash refs: This
189 is required, because the user configuration is more specific for user
190 based encryption.
191
192EXAMPLE
193 Enough wasted time, spread the example, not the word. :-) Let's write a
194 simple server, say a server for MD5 digests. The server uses the
195 external package MD5, but the client doesn't need to install the
196 package. MD5(3). We present the server source here, the client is part
197 of the RPC::PlClient man page. See RPC::PlClient(3).
198
199 #!/usr/bin/perl -wT
200 # Note the -T switch! This is always recommended for Perl servers.
201
202 use strict; # Always a good choice.
203
204 require RPC::PlServer;
205 require MD5;
206
207 package MD5_Server; # Clients need to request application
208 # "MD5_Server"
209
210 $MD5_Server::VERSION = '1.0'; # Clients will be refused, if they
211 # request version 1.1
212 @MD5_Server::ISA = qw(RPC::PlServer);
213
214 eval {
215 # Server options below can be overwritten in the config file or
216 # on the command line.
217 my $server = MD5_Server->new({
218 'pidfile' => '/var/run/md5serv.pid',
219 'configfile' => '/etc/md5serv.conf',
220 'facility' => 'daemon', # Default
221 'user' => 'nobody',
222 'group' => 'nobody',
223 'localport' => 2000,
224 'logfile' => 0, # Use syslog
225 'mode' => 'fork', # Recommended for Unix
226 'methods' => {
227 'MD5_Server' => {
228 'ClientObject' => 1,
229 'CallMethod' => 1,
230 'NewHandle' => 1
231 },
232 'MD5' => {
233 'new' => 1,
234 'add' => 1,
235 'hexdigest' => 1
236 },
237 }
238 });
239 $server->Bind();
240 };
241
242SECURITY
243 It has to be said: PlRPC based servers are a potential security problem!
244 I did my best to avoid security problems, but it is more than likely,
245 that I missed something. Security was a design goal, but not *the*
246 design goal. (A well known problem ...)
247
248 I highly recommend the following design principles:
249
250 Protection against "trusted" users
251 perlsec
252 Read the perl security FAQ ("perldoc perlsec") and use the "-T"
253 switch.
254
255 taintperl
256 Use the "-T" switch. I mean it!
257
258 Verify data
259 Never untaint strings withouth verification, better verify twice.
260 For example the *CallMethod* function first checks, whether an
261 object handle is valid before coercing a method on it.
262
263 Be restrictive
264 Think twice, before you give a client access to a method.
265
266 perlsec
267 And just in case I forgot it: Read the "perlsec" man page. :-)
268
269 Protection against untrusted users
270 Host based authorization
271 PlRPC has a builtin host based authorization scheme; use it! See
272 "CONFIGURATION FILE".
273
274 User based authorization
275 PlRPC has a builtin user based authorization scheme; use it! See
276 "CONFIGURATION FILE".
277
278 Encryption
279 Using encryption with PlRPC is extremely easy. There is absolutely
280 no reason for communicating unencrypted with the clients. Even more:
281 I recommend two phase encryption: The first phase is the login
282 phase, where to use a host based key. As soon as the user has
283 authorized, you should switch to a user based key. See the
284 DBI::ProxyServer for an example.
285
286AUTHOR AND COPYRIGHT
287 The PlRPC-modules are
288
289 Copyright (C) 1998, Jochen Wiedmann
290 Email: jochen.wiedmann at freenet.de
291
292 All rights reserved.
293
294 You may distribute this package under the terms of either the GNU
295 General Public License or the Artistic License, as specified in the Perl
296 README file.
297
298SEE ALSO
299 RPC::PlClient(3), RPC::PlServer::Comm(3), Net::Daemon(3),
300 Net::Daemon::Log(3), Storable(3), Sys::Syslog(3), Win32::EventLog(3)
301
302 See DBI::ProxyServer(3) for an example application.
303
304