1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2010 - 2015, Göteborg Bit Factory.
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included
13 // in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 //
23 // http://www.opensource.org/licenses/mit-license.php
24 //
25 ////////////////////////////////////////////////////////////////////////////////
26 
27 #include <cmake.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <fcntl.h>
36 #include <signal.h>
37 #include <errno.h>
38 #include <unistd.h>
39 #include <syslog.h>
40 #include <string.h>
41 #include <assert.h>
42 #include <Server.h>
43 #include <TLSServer.h>
44 #include <Timer.h>
45 #include <text.h>
46 
47 // Indicates that certain signals were caught.
48 bool _sighup  = false;
49 bool _sigusr1 = false;
50 bool _sigusr2 = false;
51 
52 ////////////////////////////////////////////////////////////////////////////////
signal_handler(int s)53 static void signal_handler (int s)
54 {
55   switch (s)
56   {
57   case SIGHUP:  _sighup  = true; break;  // Graceful stop
58   case SIGUSR1: _sigusr1 = true; break;  // Config reload
59   case SIGUSR2: _sigusr2 = true; break;
60   }
61 }
62 
63 ////////////////////////////////////////////////////////////////////////////////
Server()64 Server::Server ()
65   : _log (NULL)
66   , _log_clients (false)
67   , _client_address ("")
68   , _client_port (0)
69   , _host ("::")
70   , _port ("12345")
71   , _pool_size (4)
72   , _queue_size (10)
73   , _daemon (false)
74   , _pid_file ("")
75   , _request_count (0)
76   , _limit (0)        // Unlimited
77   , _ca_file ("")
78   , _cert_file ("")
79   , _key_file ("")
80   , _crl_file ("")
81 {
82 }
83 
84 ////////////////////////////////////////////////////////////////////////////////
~Server()85 Server::~Server ()
86 {
87 }
88 
89 ////////////////////////////////////////////////////////////////////////////////
setPort(const std::string & port)90 void Server::setPort (const std::string& port)
91 {
92   if (_log) _log->format ("Using port %s", port.c_str ());
93   _port = port;
94 }
95 
96 ////////////////////////////////////////////////////////////////////////////////
setHost(const std::string & host)97 void Server::setHost (const std::string& host)
98 {
99   if (_log) _log->format ("Using address %s", host.c_str ());
100   _host = host;
101 }
102 
103 ////////////////////////////////////////////////////////////////////////////////
setFamily(const std::string & family)104 void Server::setFamily (const std::string& family)
105 {
106   if (_log) _log->format ("Using family %s", family.c_str ());
107   _family = family;
108 }
109 
110 ////////////////////////////////////////////////////////////////////////////////
setQueueSize(int size)111 void Server::setQueueSize (int size)
112 {
113   if (_log) _log->format ("Queue size %d requests", size);
114   _queue_size = size;
115 }
116 
117 ////////////////////////////////////////////////////////////////////////////////
setPoolSize(int size)118 void Server::setPoolSize (int size)
119 {
120   if (_log) _log->format ("Thread Pool size %d", size);
121   _pool_size = size;
122 }
123 
124 ////////////////////////////////////////////////////////////////////////////////
setDaemon()125 void Server::setDaemon ()
126 {
127   if (_log) _log->write ("Will run as daemon");
128   _daemon = true;
129 }
130 
131 ////////////////////////////////////////////////////////////////////////////////
setPidFile(const std::string & file)132 void Server::setPidFile (const std::string& file)
133 {
134   if (_log) _log->write ("PID file " + file);
135   assert (file.length () > 0);
136   _pid_file = file;
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////////
setLimit(int max)140 void Server::setLimit (int max)
141 {
142   if (_log) _log->format ("Request size limit %d bytes", max);
143   assert (max >= 0);
144   _limit = max;
145 }
146 
147 ////////////////////////////////////////////////////////////////////////////////
setCAFile(const std::string & file)148 void Server::setCAFile (const std::string& file)
149 {
150   if (_log) _log->format ("CA          %s", file.c_str ());
151   _ca_file = file;
152   File cert (file);
153   if (! cert.readable ())
154     throw format ("CA Certificate not readable: '{1}'", file);
155 }
156 
157 ////////////////////////////////////////////////////////////////////////////////
setCertFile(const std::string & file)158 void Server::setCertFile (const std::string& file)
159 {
160   if (_log) _log->format ("Certificate %s", file.c_str ());
161   _cert_file = file;
162   File cert (file);
163   if (! cert.readable ())
164     throw format ("Server Certificate not readable: '{1}'", file);
165 }
166 
167 ////////////////////////////////////////////////////////////////////////////////
setKeyFile(const std::string & file)168 void Server::setKeyFile (const std::string& file)
169 {
170   if (_log) _log->format ("Private Key %s", file.c_str ());
171   _key_file = file;
172   File key (file);
173   if (! key.readable ())
174     throw format ("Server key not readable: '{1}'", file);
175 }
176 
177 ////////////////////////////////////////////////////////////////////////////////
setCRLFile(const std::string & file)178 void Server::setCRLFile (const std::string& file)
179 {
180   if (_log) _log->format ("CRL         %s", file.c_str ());
181   _crl_file = file;
182   File crl (file);
183   if (! crl.readable ())
184     throw format ("CRL Certificate not readable: '{1}'", file);
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
setLogClients(bool value)188 void Server::setLogClients (bool value)
189 {
190   if (_log) _log->format ("IP logging %s", (value ? "on" : "off"));
191   _log_clients = value;
192 }
193 
194 ////////////////////////////////////////////////////////////////////////////////
setLog(Log * l)195 void Server::setLog (Log* l)
196 {
197   _log = l;
198 }
199 
200 ////////////////////////////////////////////////////////////////////////////////
setConfig(Config * c)201 void Server::setConfig (Config* c)
202 {
203   _config = c;
204 }
205 
206 ////////////////////////////////////////////////////////////////////////////////
beginServer()207 void Server::beginServer ()
208 {
209   if (_log) _log->write ("Server starting");
210 
211   if (_daemon)
212   {
213     daemonize ();  // Only the child returns.
214     writePidFile ();
215   }
216 
217   signal (SIGHUP,  signal_handler);  // Graceful stop
218   signal (SIGUSR1, signal_handler);  // Config reload
219   signal (SIGUSR2, signal_handler);
220 
221   TLSServer server;
222   if (_config)
223   {
224     server.debug (_config->getInteger ("debug.tls"));
225 
226     std::string ciphers = _config->get ("ciphers");
227     if (ciphers != "")
228     {
229       server.ciphers (ciphers);
230       if (_log) _log->format ("Using ciphers: %s", ciphers.c_str ());
231     }
232 
233     std::string trust = _config->get ("trust");
234     if (trust == "allow all")
235       server.trust (TLSServer::allow_all);
236     else if (trust == "strict")
237       server.trust (TLSServer::strict);
238     else if (_log)
239       _log->format ("Invalid 'trust' setting value of '%s'", trust.c_str ());
240   }
241 
242   server.init (_ca_file,        // CA
243                _crl_file,       // CRL
244                _cert_file,      // Cert
245                _key_file);      // Key
246   server.queue (_queue_size);
247   server.bind (_host, _port, _family);
248   server.listen ();
249 
250   if (_log) _log->write ("Server ready");
251 
252   _request_count = 0;
253   while (1)
254   {
255     try
256     {
257       TLSTransaction tx;
258       tx.trust (server.trust ());
259       server.accept (tx);
260 
261       if (_sighup)
262         throw "SIGHUP shutdown.";
263 
264       // Get client address and port, for logging.
265       if (_log_clients)
266         tx.getClient (_client_address, _client_port);
267 
268       // Metrics.
269       HighResTimer timer;
270       timer.start ();
271 
272       std::string input;
273       tx.recv (input);
274 
275       // Handle the request.
276       ++_request_count;
277 
278       // Call the derived class handler.
279       std::string output;
280       handler (input, output);
281       if (output.length ())
282         tx.send (output);
283 
284       if (_log)
285       {
286         timer.stop ();
287         _log->format ("[%d] Serviced in %.6fs", _request_count, timer.total ());
288       }
289     }
290 
291     catch (std::string& e) { if (_log) _log->write (std::string ("Error: ") + e); }
292     catch (char* e)        { if (_log) _log->write (std::string ("Error: ") + e); }
293     catch (...)            { if (_log) _log->write ("Error: Unknown exception"); }
294   }
295 }
296 
297 ////////////////////////////////////////////////////////////////////////////////
298 // TODO To provide these data, a request count, a start time, and a cumulative
299 //      utilization time must be tracked.
stats(int & requests,time_t & uptime,double & utilization)300 void Server::stats (int& requests, time_t& uptime, double& utilization)
301 {
302   requests = _request_count;
303   uptime = 0;
304   utilization = 0.0;
305 }
306 
307 ////////////////////////////////////////////////////////////////////////////////
daemonize()308 void Server::daemonize ()
309 {
310   if (_log) _log->write ("Daemonizing");
311 
312 /* TODO Load RUN_AS_USER from config.
313 
314   // If run as root, switch to preferred user.
315   if (getuid () == 0 || geteuid () == 0 )
316   {
317     struct passwd *pw = getpwnam (RUN_AS_USER);
318     if (pw)
319     {
320       if (_log) _log->write ("setting user to " RUN_AS_USER);
321       setuid (pw->pw_uid);
322     }
323   }
324 */
325 
326   // Fork off the parent process
327   pid_t pid = fork ();
328   if (pid < 0)
329   {
330     exit (EXIT_FAILURE);
331   }
332 
333   // If we got a good PID, then we can exit the parent process.
334   if (pid > 0)
335   {
336     exit (EXIT_SUCCESS);
337   }
338 
339   // Change the file mode mask
340   umask (0);
341 
342   // Create a new SID for the child process
343   pid_t sid = setsid ();
344   if (sid < 0)
345   {
346     if (_log) _log->write ("setsid failed");
347     exit (EXIT_FAILURE);
348   }
349 
350   // Change the current working directory
351   // Why is this important?  To ensure that program is independent of $CWD?
352   if ((chdir ("/")) < 0)
353   {
354     if (_log) _log->write ("chdir failed");
355     exit (EXIT_FAILURE);
356   }
357 
358   // Redirect standard files to /dev/null.
359   freopen ("/dev/null", "r", stdin);
360   freopen ("/dev/null", "w", stdout);
361   freopen ("/dev/null", "w", stderr);
362 
363   if (_log) _log->write ("Daemonized");
364 }
365 
366 ////////////////////////////////////////////////////////////////////////////////
writePidFile()367 void Server::writePidFile ()
368 {
369   pid_t pid = getpid ();
370 
371   FILE* output = fopen (_pid_file.c_str (), "w");
372   if (output)
373   {
374     fprintf (output, "%d", pid);
375     fclose (output);
376   }
377   else
378     if (_log) _log->write ("Error: could not write PID to '" + _pid_file + "'.");
379 }
380 
381 ////////////////////////////////////////////////////////////////////////////////
removePidFile()382 void Server::removePidFile ()
383 {
384   assert (_pid_file.length () > 0);
385   unlink (_pid_file.c_str ());
386 }
387 
388 ////////////////////////////////////////////////////////////////////////////////
389