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