2 SSL server program listens on a port, accepts client connection, reads
3 the data into a temporary file, calls the systemtap translator and
4 then transmits the resulting file back to the client.
6 Copyright (C) 2011-2013 Red Hat Inc.
8 This file is part of systemtap, and is free software. You can
9 redistribute it and/or modify it under the terms of the GNU General Public
10 License as published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
38 #include <sys/utsname.h>
39 #include <sys/types.h>
41 #include <semaphore.h>
51 #include <avahi-client/publish.h>
52 #include <avahi-common/alternative.h>
53 #include <avahi-common/thread-watch.h>
54 #include <avahi-common/malloc.h>
55 #include <avahi-common/error.h>
56 #include <avahi-common/domain.h>
61 #include "nsscommon.h"
67 static void cleanup ();
68 static PRStatus
spawn_and_wait (const vector
<string
> &argv
, int *result
,
69 const char* fd0
, const char* fd1
, const char* fd2
,
70 const char *pwd
, const vector
<string
>& envVec
= vector
<string
> ());
79 typedef map
<string
, mok_info_t
*> mok_map_t
;
80 typedef map
<string
, mok_info_t
*>::const_iterator mok_map_iterator
;
82 /* getopt variables */
85 /* File scope statics. Set during argument parsing and initialization. */
86 static bool use_db_password
;
87 static unsigned short port
;
88 static long max_threads
;
89 static string cert_db_path
;
90 static string stap_options
;
91 static string uname_r
;
92 static string kernel_build_tree
;
94 static string cert_serial_number
;
95 static string B_options
;
96 static string I_options
;
97 static string R_option
;
98 static string D_options
;
99 static bool keep_temp
;
100 static mok_map_t server_mok_map
;
103 static int pending_interrupts
;
104 #define CONCURRENCY_TIMEOUT_S 3
107 // Server_error messages are printed to stderr and logged, if requested.
109 server_error (const string
&msg
, int logit
= true)
111 cerr
<< msg
<< endl
<< flush
;
112 // Log it, but avoid repeated messages to the terminal.
113 if (logit
&& log_ok ())
117 // client_error messages are treated as server errors and also printed to the client's stderr.
119 client_error (const string
&msg
, string stapstderr
)
122 if (! stapstderr
.empty ())
125 errfile
.open (stapstderr
.c_str (), ios_base::app
);
126 if (! errfile
.good ())
127 server_error (_F("Could not open client stderr file %s: %s", stapstderr
.c_str (),
130 errfile
<< "Server: " << msg
<< endl
;
131 // NB: No need to close errfile
135 // Messages from the nss common code are treated as server errors.
138 nsscommon_error (const char *msg
, int logit
)
140 server_error (msg
, logit
);
143 // Fatal errors are treated as server errors but also result in termination
146 fatal (const string
&msg
)
155 process_a (const string
&arg
)
158 stap_options
+= " -a " + arg
;
162 process_r (const string
&arg
)
164 if (arg
[0] == '/') // fully specified path
166 kernel_build_tree
= arg
;
167 uname_r
= kernel_release_from_build_tree (arg
);
171 kernel_build_tree
= "/lib/modules/" + arg
+ "/build";
174 stap_options
+= " -r " + arg
; // Pass the argument to stap directly.
178 process_log (const char *arg
)
184 parse_options (int argc
, char **argv
)
186 // Examine the command line. This is the command line for us (stap-serverd) not the command
187 // line for spawned stap instances.
193 // NB: The values of these enumerators must not conflict with the values of ordinary
194 // characters, since those are returned by getopt_long for short options.
201 static struct option long_options
[] = {
202 { "port", 1, NULL
, LONG_OPT_PORT
},
203 { "ssl", 1, NULL
, LONG_OPT_SSL
},
204 { "log", 1, NULL
, LONG_OPT_LOG
},
205 { "max-threads", 1, NULL
, LONG_OPT_MAXTHREADS
},
208 int grc
= getopt_long (argc
, argv
, "a:B:D:I:kPr:R:", long_options
, NULL
);
217 B_options
+= string (" -") + (char)grc
+ optarg
;
218 stap_options
+= string (" -") + (char)grc
+ optarg
;
221 D_options
+= string (" -") + (char)grc
+ optarg
;
222 stap_options
+= string (" -") + (char)grc
+ optarg
;
225 I_options
+= string (" -") + (char)grc
+ optarg
;
226 stap_options
+= string (" -") + (char)grc
+ optarg
;
232 use_db_password
= true;
238 R_option
= string (" -") + (char)grc
+ optarg
;
239 stap_options
+= string (" -") + (char)grc
+ optarg
;
242 port_tmp
= strtol (optarg
, &num_endptr
, 10);
243 if (*num_endptr
!= '\0')
244 fatal (_F("%s: cannot parse number '--port=%s'", argv
[0], optarg
));
245 else if (port_tmp
< 0 || port_tmp
> 65535)
246 fatal (_F("%s: invalid entry: port must be between 0 and 65535 '--port=%s'", argv
[0],
249 port
= (unsigned short) port_tmp
;
252 cert_db_path
= optarg
;
255 process_log (optarg
);
257 case LONG_OPT_MAXTHREADS
:
258 max_threads
= strtol (optarg
, &num_endptr
, 0);
259 if (*num_endptr
!= '\0')
260 fatal (_F("%s: cannot parse number '--max-threads=%s'", argv
[0], optarg
));
261 else if (max_threads
< 0)
262 fatal (_F("%s: invalid entry: max threads must not be negative '--max-threads=%s'",
266 // Invalid/unrecognized option given. Message has already been issued.
269 // Reached when one added a getopt option but not a corresponding switch/case:
271 server_error (_F("%s: unhandled option '%c %s'", argv
[0], (char)grc
, optarg
));
273 server_error (_F("%s: unhandled option '%c'", argv
[0], (char)grc
));
278 for (int i
= optind
; i
< argc
; i
++)
279 server_error (_F("%s: unrecognized argument '%s'", argv
[0], argv
[i
]));
285 return server_cert_db_path () + "/stap.cert";
288 // Signal handling. When an interrupt is received, kill any spawned processes
292 handle_interrupt (int sig
)
294 pending_interrupts
++;
295 if(pending_interrupts
>= 2)
297 log (_F("Received another signal %d, exiting (forced)", sig
));
300 log (_F("Received signal %d, exiting", sig
));
304 setup_signals (sighandler_t handler
)
308 memset(&sa
, 0, sizeof(sa
));
309 sa
.sa_handler
= handler
;
310 sigemptyset (&sa
.sa_mask
);
311 if (handler
!= SIG_IGN
)
313 sigaddset (&sa
.sa_mask
, SIGHUP
);
314 sigaddset (&sa
.sa_mask
, SIGPIPE
);
315 sigaddset (&sa
.sa_mask
, SIGINT
);
316 sigaddset (&sa
.sa_mask
, SIGTERM
);
317 sigaddset (&sa
.sa_mask
, SIGTTIN
);
318 sigaddset (&sa
.sa_mask
, SIGTTOU
);
319 sigaddset (&sa
.sa_mask
, SIGXFSZ
);
320 sigaddset (&sa
.sa_mask
, SIGXCPU
);
322 sa
.sa_flags
= SA_RESTART
;
324 sigaction (SIGHUP
, &sa
, NULL
);
325 sigaction (SIGPIPE
, &sa
, NULL
);
326 sigaction (SIGINT
, &sa
, NULL
);
327 sigaction (SIGTERM
, &sa
, NULL
);
328 sigaction (SIGTTIN
, &sa
, NULL
);
329 sigaction (SIGTTOU
, &sa
, NULL
);
330 sigaction (SIGXFSZ
, &sa
, NULL
);
331 sigaction (SIGXCPU
, &sa
, NULL
);
335 static AvahiEntryGroup
*avahi_group
= NULL
;
336 static AvahiThreadedPoll
*avahi_threaded_poll
= NULL
;
337 static char *avahi_service_name
= NULL
;
338 static const char * const avahi_service_tag
= "_stap._tcp";
339 static AvahiClient
*avahi_client
= 0;
340 static int avahi_collisions
= 0;
342 static void create_services (AvahiClient
*c
);
348 * Each service must have a unique name on the local network.
349 * When there is a collision, we try to rename the service.
350 * However, we need to limit the number of attempts, since the
351 * service namespace could be maliciously flooded with service
352 * names designed to maximize collisions.
353 * Arbitrarily choose a limit of 65535, which is the number of
357 if (avahi_collisions
>= 65535) {
358 server_error (_F("Too many service name collisions for Avahi service %s",
364 * Use the avahi-supplied function to generate a new service name.
366 char *n
= avahi_alternative_service_name(avahi_service_name
);
368 server_error (_F("Avahi service name collision, renaming service '%s' to '%s'",
369 avahi_service_name
, n
));
370 avahi_free(avahi_service_name
);
371 avahi_service_name
= n
;
377 entry_group_callback (
379 AvahiEntryGroupState state
,
380 AVAHI_GCC_UNUSED
void *userdata
382 assert(g
== avahi_group
|| avahi_group
== NULL
);
385 // Called whenever the entry group state changes.
388 case AVAHI_ENTRY_GROUP_ESTABLISHED
:
389 // The entry group has been established successfully.
390 log (_F("Avahi service '%s' successfully established.", avahi_service_name
));
393 case AVAHI_ENTRY_GROUP_COLLISION
:
394 // A service name collision with a remote service happened.
395 // Unfortunately, we don't know which entry collided.
396 // We need to rename them all and recreate the services.
397 if (rename_service () == 0)
398 create_services (avahi_entry_group_get_client (g
));
401 case AVAHI_ENTRY_GROUP_FAILURE
:
402 // Some kind of failure happened.
403 server_error (_F("Avahi entry group failure: %s",
404 avahi_strerror (avahi_client_errno (avahi_entry_group_get_client (g
)))));
407 case AVAHI_ENTRY_GROUP_UNCOMMITED
:
408 case AVAHI_ENTRY_GROUP_REGISTERING
:
414 create_services (AvahiClient
*c
) {
417 // Create a new entry group, if necessary, or reset the existing one.
420 if (! (avahi_group
= avahi_entry_group_new (c
, entry_group_callback
, NULL
)))
422 server_error (_F("avahi_entry_group_new () failed: %s",
423 avahi_strerror (avahi_client_errno (c
))));
428 avahi_entry_group_reset(avahi_group
);
431 // Contruct the information needed for our service.
432 log (_F("Adding Avahi service '%s'", avahi_service_name
));
434 // Create the txt tags that will be registered with our service.
435 string sysinfo
= "sysinfo=" + uname_r
+ " " + arch
;
436 string certinfo
= "certinfo=" + cert_serial_number
;
437 string version
= string ("version=") + CURRENT_CS_PROTOCOL_VERSION
;;
438 string optinfo
= "optinfo=";
440 // These option strings already have a leading space.
441 if (! R_option
.empty ())
443 optinfo
+= R_option
.substr(1);
446 if (! B_options
.empty ())
448 optinfo
+= separator
+ B_options
.substr(1);
451 if (! D_options
.empty ())
453 optinfo
+= separator
+ D_options
.substr(1);
456 if (! I_options
.empty ())
457 optinfo
+= separator
+ I_options
.substr(1);
459 // Create an avahi string list with the info we have so far.
460 AvahiStringList
*strlst
= avahi_string_list_new(sysinfo
.c_str (),
463 certinfo
.c_str (), NULL
);
466 server_error (_("Failed to allocate string list"));
470 // Add server MOK info, if available.
472 // FIXME: Hmm, is this the right way to transmit this data? This
473 // method is fairly easy, but I wonder if we're abusing the avahi
474 // stuff with too much data here.
475 if (! server_mok_map
.empty())
479 for (it
= server_mok_map
.begin(), i
= 1; it
!= server_mok_map
.end();
482 string tmp
= _F("mok_info%d=", i
) + it
->second
->fingerprint
+ " "
483 + it
->second
->serial_number
+ " " + it
->second
->issuer
;
484 strlst
= avahi_string_list_add(strlst
, tmp
.c_str ());
487 server_error (_("Failed to add a string to the list"));
493 // We will now add our service to the entry group.
494 // Loop until no collisions.
497 ret
= avahi_entry_group_add_service_strlst (avahi_group
,
500 (AvahiPublishFlags
)0,
503 NULL
, NULL
, port
, strlst
);
507 if (ret
== AVAHI_ERR_COLLISION
)
509 // A service name collision with a local service happened.
511 if (rename_service () < 0) {
512 // Too many collisions. Message already issued.
515 continue; // try again.
518 server_error (_F("Failed to add %s service: %s",
519 avahi_service_tag
, avahi_strerror (ret
)));
523 // Tell the server to register the service.
524 if ((ret
= avahi_entry_group_commit (avahi_group
)) < 0)
526 server_error (_F("Failed to commit avahi entry group: %s", avahi_strerror (ret
)));
530 avahi_string_list_free(strlst
);
534 avahi_entry_group_reset (avahi_group
);
535 avahi_string_list_free(strlst
);
538 static void avahi_cleanup_client () {
539 // This also frees the entry group, if any
541 avahi_client_free (avahi_client
);
548 client_callback (AvahiClient
*c
, AvahiClientState state
, AVAHI_GCC_UNUSED
void * userdata
)
552 // Called whenever the client or server state changes.
555 case AVAHI_CLIENT_S_RUNNING
:
556 // The server has startup successfully and registered its host
557 // name on the network, so it's time to create our services.
561 case AVAHI_CLIENT_FAILURE
:
562 server_error (_F("Avahi client failure: %s", avahi_strerror (avahi_client_errno (c
))));
563 if (avahi_client_errno (c
) == AVAHI_ERR_DISCONNECTED
)
565 // The client has been disconnected; probably because the avahi daemon has been
566 // restarted. We can free the client here and try to reconnect using a new one.
567 // Passing AVAHI_CLIENT_NO_FAIL allows the new client to be
568 // created, even if the avahi daemon is not running. Our service will be advertised
569 // if/when the daemon is started.
570 avahi_cleanup_client ();
572 avahi_client
= avahi_client_new (avahi_threaded_poll_get (avahi_threaded_poll
),
573 (AvahiClientFlags
)AVAHI_CLIENT_NO_FAIL
,
574 client_callback
, NULL
, & error
);
578 case AVAHI_CLIENT_S_COLLISION
:
579 // Let's drop our registered services. When the server is back
580 // in AVAHI_SERVER_RUNNING state we will register them
581 // again with the new host name.
583 case AVAHI_CLIENT_S_REGISTERING
:
584 // The server records are now being established. This
585 // might be caused by a host name change. We need to wait
586 // for our own records to register until the host name is
587 // properly esatblished.
589 avahi_entry_group_reset (avahi_group
);
592 case AVAHI_CLIENT_CONNECTING
:
593 // The avahi-daemon is not currently running. Our service will be advertised
594 // if/when the deamon is started.
595 server_error (_F("The Avahi daemon is not running. Avahi service '%s' will be established when the deamon is started", avahi_service_name
));
602 if (avahi_service_name
)
603 log (_F("Removing Avahi service '%s'", avahi_service_name
));
605 // Stop the avahi client, if it's running
606 if (avahi_threaded_poll
)
607 avahi_threaded_poll_stop (avahi_threaded_poll
);
609 // Clean up the avahi objects. The order of freeing these is significant.
610 avahi_cleanup_client ();
611 if (avahi_threaded_poll
) {
612 avahi_threaded_poll_free (avahi_threaded_poll
);
613 avahi_threaded_poll
= 0;
615 if (avahi_service_name
) {
616 avahi_free (avahi_service_name
);
617 avahi_service_name
= 0;
621 // The entry point for the avahi client thread.
623 avahi_publish_service (CERTCertificate
*cert
)
625 // Get the certificate serial number.
626 cert_serial_number
= get_cert_serial_number (cert
);
628 // Construct the Avahi service name.
629 char host
[HOST_NAME_MAX
+ 1];
630 gethostname (host
, sizeof(host
));
631 host
[sizeof(host
) - 1] = '\0';
633 buf
= string ("Systemtap Compile Server on ") + host
;
635 // Make sure the service name is valid
636 const char *initial_service_name
= buf
.c_str ();
637 if (! avahi_is_valid_service_name (initial_service_name
)) {
638 // The only restriction on service names is that the buffer must not exceed
639 // AVAHI_LABEL_MAX in size, which means that the name cannot be longer than
640 // AVAHI_LABEL_MAX-1 in length.
641 assert (strlen (initial_service_name
) >= AVAHI_LABEL_MAX
);
642 buf
= buf
.substr (0, AVAHI_LABEL_MAX
- 1);
643 initial_service_name
= buf
.c_str ();
644 assert (avahi_is_valid_service_name (initial_service_name
));
646 avahi_service_name
= avahi_strdup (initial_service_name
);
648 // Allocate main loop object.
649 if (! (avahi_threaded_poll
= avahi_threaded_poll_new ()))
651 server_error (_("Failed to create avahi threaded poll object."));
655 // Always allocate a new client. Passing AVAHI_CLIENT_NO_FAIL allows the client to be
656 // created, even if the avahi daemon is not running. Our service will be advertised
657 // if/when the daemon is started.
659 avahi_client
= avahi_client_new (avahi_threaded_poll_get (avahi_threaded_poll
),
660 (AvahiClientFlags
)AVAHI_CLIENT_NO_FAIL
,
661 client_callback
, NULL
, & error
);
662 // Check whether creating the client object succeeded.
665 server_error (_F("Failed to create avahi client: %s", avahi_strerror(error
)));
669 // Run the main loop.
670 avahi_threaded_poll_start (avahi_threaded_poll
);
677 advertise_presence (CERTCertificate
*cert
__attribute ((unused
)))
680 avahi_publish_service (cert
);
682 server_error (_("Unable to advertise presence on the network. Avahi is not available"));
687 unadvertise_presence ()
695 initialize_server_moks()
697 string mok_path
= server_cert_db_path() + "/moks";
698 DIR *dirp
= opendir(mok_path
.c_str());
699 struct dirent
*direntp
;
701 bool initialized_nss
= false;
703 // The directory of machine owner keys (MOK) is optional, so if it
704 // doesn't exist, we don't worry about it.
706 // If the error isn't ENOENT (Directory does not exist), we've got
707 // a non-fatal error.
709 server_error(_F("Could not open server MOK directory %s: %s",
710 mok_path
.c_str(), strerror(errno
)));
714 // Create a regular expression object to verify MOK fingerprints
717 if ((regcomp(&checkre
, "^[0-9a-f]{2}(:[0-9a-f]{2})+$",
718 REG_EXTENDED
| REG_NOSUB
) != 0)) {
719 // Not fatal, just ignore the MOK fingerprints.
720 server_error(_F("Error in MOK fingerprint regcomp: %s", strerror (errno
)));
725 // We've opened the directory, so read all the directory names from
727 while ((direntp
= readdir(dirp
)) != NULL
) {
728 // We're only interested in directories (of key files).
729 if (direntp
->d_type
!= DT_DIR
)
732 // We've got a directory. If the directory name isn't in the right
733 // format for a MOK fingerprint, skip it.
734 if ((regexec(&checkre
, direntp
->d_name
, (size_t) 0, NULL
, 0) != 0))
737 // OK, we've got a directory name in the right format, so save it.
738 temp
.push_back(string(direntp
->d_name
));
743 // read_cert_info_from_file() needs NSS to be initialized...
744 if (! NSS_IsInitialized ()) {
745 // If NSS can't be initialized, just return (a message should have
746 // been already issued).
747 if (nssInit (cert_db_path
.c_str ()) != SECSuccess
)
749 initialized_nss
= true;
752 // At this point, we've got a list of directories with names in the
753 // proper format. Make sure each directory contains a x509
754 // certificate and private key file.
755 vector
<string
>::const_iterator it
;
756 for (it
= temp
.begin(); it
!= temp
.end(); it
++) {
757 string keydir
= mok_path
+ "/" + *it
;
758 dirp
= opendir(keydir
.c_str());
760 // The directory name was in the right format, but we can't open
761 // it for some reason. Just skip it.
762 server_error(_F("Could not open server MOK fingerprint directory %s: %s",
763 keydir
.c_str(), strerror(errno
)));
767 // Find both the x509 certificate and private key files.
769 // FIXME: We could verify that the private key file's mode is 0600
770 // here and refuse to use it otherwise. Really needed?
771 bool priv_found
= false;
772 bool cert_found
= false;
773 while ((direntp
= readdir(dirp
)) != NULL
) {
774 if (! priv_found
&& direntp
->d_type
== DT_REG
775 && strcmp(direntp
->d_name
, "signing_key.priv") == 0) {
779 if (! cert_found
&& direntp
->d_type
== DT_REG
780 && strcmp(direntp
->d_name
, "signing_key.x509") == 0) {
784 if (priv_found
&& cert_found
)
788 if (!priv_found
|| !cert_found
) {
789 // We didn't find one (or both) of the required files. Skip the
791 server_error(_F("Could not find server MOK files in directory %s",
796 // Grab info from the cert.
797 string issuer
, serial_number
, fingerprint
;
798 if (read_cert_info_from_file(keydir
+ "/signing_key.x509", issuer
,
799 serial_number
, fingerprint
) == SECSuccess
) {
800 // Make sure the fingerprint from the certificate matches the
802 if (fingerprint
!= *it
) {
803 server_error(_F("Server MOK directory name '%s' doesn't match fingerprint from certificate %s",
804 keydir
.c_str(), fingerprint
.c_str()));
809 mok_info_t
*mki
= new mok_info_t
;
810 mki
->issuer
= issuer
;
811 mki
->serial_number
= serial_number
;
812 mki
->fingerprint
= fingerprint
;
813 mki
->directory
= keydir
;
814 server_mok_map
[fingerprint
] = mki
;
815 server_error(_F("Found MOK: issuer='%s' serial number='%s'",
816 issuer
.c_str(), serial_number
.c_str()));
820 // If we initialized NSS, clean it up.
822 nssCleanup (cert_db_path
.c_str ());
828 initialize (int argc
, char **argv
) {
829 pending_interrupts
= 0;
830 setup_signals (& handle_interrupt
);
832 // Seed the random number generator. Used to generate noise used during key generation.
836 use_db_password
= false;
838 max_threads
= sysconf( _SC_NPROCESSORS_ONLN
); // Default to number of processors
840 struct utsname utsname
;
842 uname_r
= utsname
.release
;
843 kernel_build_tree
= "/lib/modules/" + uname_r
+ "/build";
844 arch
= normalize_machine (utsname
.machine
);
846 // Parse the arguments. This also starts the server log, if any, and should be done before
847 // any messages are issued.
848 parse_options (argc
, argv
);
850 // PR11197: security prophylactics.
851 // Reject use as root, except via a special environment variable.
852 if (! getenv ("STAP_PR11197_OVERRIDE")) {
854 fatal ("For security reasons, invocation of stap-serverd as root is not supported.");
857 struct passwd
*pw
= getpwuid (geteuid ());
859 fatal (_F("Unable to determine effective user name: %s", strerror (errno
)));
860 string username
= pw
->pw_name
;
861 pid_t pid
= getpid ();
862 log (_F("===== compile server pid %d starting as %s =====", pid
, username
.c_str ()));
864 // Where is the ssl certificate/key database?
865 if (cert_db_path
.empty ())
866 cert_db_path
= server_cert_db_path ();
868 // Make sure NSPR is initialized. Must be done before NSS is initialized
869 PR_Init (PR_SYSTEM_THREAD
, PR_PRIORITY_NORMAL
, 1);
870 /* Set the cert database password callback. */
871 PK11_SetPasswordFunc (nssPasswordCallback
);
873 // Get the list of optional machine owner keys (MOK) this server
875 initialize_server_moks ();
881 unadvertise_presence ();
885 /* Function: readDataFromSocket()
887 * Purpose: Read data from the socket into a temporary file.
891 readDataFromSocket(PRFileDesc
*sslSocket
, const char *requestFileName
)
893 PRFileDesc
*local_file_fd
= 0;
894 PRInt32 numBytesExpected
;
895 PRInt32 numBytesRead
;
896 PRInt32 numBytesWritten
;
897 PRInt32 totalBytes
= 0;
898 #define READ_BUFFER_SIZE 4096
899 char buffer
[READ_BUFFER_SIZE
];
901 // Read the number of bytes to be received.
902 /* XXX: impose a limit to prevent disk space consumption DoS */
903 numBytesRead
= PR_Read_Complete (sslSocket
, & numBytesExpected
,
904 (PRInt32
)sizeof (numBytesExpected
));
905 if (numBytesRead
== 0) /* EOF */
907 server_error (_("Error reading size of request file"));
910 if (numBytesRead
< 0)
912 server_error (_("Error in PR_Read"));
917 /* Convert numBytesExpected from network byte order to host byte order. */
918 numBytesExpected
= ntohl (numBytesExpected
);
920 /* If 0 bytes are expected, then we were contacted only to obtain our certificate.
921 There is no client request. */
922 if (numBytesExpected
== 0)
925 /* Open the output file. */
926 local_file_fd
= PR_Open(requestFileName
, PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
,
927 PR_IRUSR
| PR_IWUSR
);
928 if (local_file_fd
== NULL
)
930 server_error (_F("Could not open output file %s", requestFileName
));
935 // Read until EOF or until the expected number of bytes has been read.
936 for (totalBytes
= 0; totalBytes
< numBytesExpected
; totalBytes
+= numBytesRead
)
938 // No need for PR_Read_Complete here, since we're already managing multiple
939 // reads to a fixed size buffer.
940 numBytesRead
= PR_Read (sslSocket
, buffer
, READ_BUFFER_SIZE
);
941 if (numBytesRead
== 0)
943 if (numBytesRead
< 0)
945 server_error (_("Error in PR_Read"));
950 /* Write to the request file. */
951 numBytesWritten
= PR_Write(local_file_fd
, buffer
, numBytesRead
);
952 if (numBytesWritten
< 0 || (numBytesWritten
!= numBytesRead
))
954 server_error (_F("Could not write to output file %s", requestFileName
));
960 if (totalBytes
!= numBytesExpected
)
962 server_error (_F("Expected %d bytes, got %d while reading client request from socket",
963 numBytesExpected
, totalBytes
));
969 PR_Close (local_file_fd
);
973 /* Function: setupSSLSocket()
975 * Purpose: Configure a socket for SSL.
980 setupSSLSocket (PRFileDesc
*tcpSocket
, CERTCertificate
*cert
, SECKEYPrivateKey
*privKey
)
982 PRFileDesc
*sslSocket
;
986 /* Inport the socket into SSL. */
987 sslSocket
= SSL_ImportFD (NULL
, tcpSocket
);
988 if (sslSocket
== NULL
)
990 server_error (_("Could not import socket into SSL"));
995 /* Set the appropriate flags. */
996 secStatus
= SSL_OptionSet (sslSocket
, SSL_SECURITY
, PR_TRUE
);
997 if (secStatus
!= SECSuccess
)
999 server_error (_("Error setting SSL security for socket"));
1004 secStatus
= SSL_OptionSet(sslSocket
, SSL_HANDSHAKE_AS_SERVER
, PR_TRUE
);
1005 if (secStatus
!= SECSuccess
)
1007 server_error (_("Error setting handshake as server for socket"));
1012 secStatus
= SSL_OptionSet(sslSocket
, SSL_REQUEST_CERTIFICATE
, PR_FALSE
);
1013 if (secStatus
!= SECSuccess
)
1015 server_error (_("Error setting SSL client authentication mode for socket"));
1020 secStatus
= SSL_OptionSet(sslSocket
, SSL_REQUIRE_CERTIFICATE
, PR_FALSE
);
1021 if (secStatus
!= SECSuccess
)
1023 server_error (_("Error setting SSL client authentication mode for socket"));
1028 /* Set the appropriate callback routines. */
1029 #if 0 /* use the default */
1030 secStatus
= SSL_AuthCertificateHook (sslSocket
, myAuthCertificate
, CERT_GetDefaultCertDB());
1031 if (secStatus
!= SECSuccess
)
1034 server_error (_("Error in SSL_AuthCertificateHook"));
1038 #if 0 /* Use the default */
1039 secStatus
= SSL_BadCertHook(sslSocket
, (SSLBadCertHandler
)myBadCertHandler
, &certErr
);
1040 if (secStatus
!= SECSuccess
)
1043 server_error (_("Error in SSL_BadCertHook"));
1047 #if 0 /* no handshake callback */
1048 secStatus
= SSL_HandshakeCallback(sslSocket
, myHandshakeCallback
, NULL
);
1049 if (secStatus
!= SECSuccess
)
1051 server_error (_("Error in SSL_HandshakeCallback"));
1057 certKEA
= NSS_FindCertKEAType (cert
);
1059 secStatus
= SSL_ConfigSecureServer (sslSocket
, cert
, privKey
, certKEA
);
1060 if (secStatus
!= SECSuccess
)
1062 server_error (_("Error configuring SSL server"));
1070 #if 0 /* No client authentication (for now) and not authenticating after each transaction. */
1071 /* Function: authenticateSocket()
1073 * Purpose: Perform client authentication on the socket.
1077 authenticateSocket (PRFileDesc
*sslSocket
, PRBool requireCert
)
1079 CERTCertificate
*cert
;
1080 SECStatus secStatus
;
1082 /* Returns NULL if client authentication is not enabled or if the
1083 * client had no certificate. */
1084 cert
= SSL_PeerCertificate(sslSocket
);
1087 /* Client had a certificate, so authentication is through. */
1088 CERT_DestroyCertificate(cert
);
1092 /* Request client to authenticate itself. */
1093 secStatus
= SSL_OptionSet(sslSocket
, SSL_REQUEST_CERTIFICATE
, PR_TRUE
);
1094 if (secStatus
!= SECSuccess
)
1096 server_error (_("Error in SSL_OptionSet:SSL_REQUEST_CERTIFICATE"));
1101 /* If desired, require client to authenticate itself. Note
1102 * SSL_REQUEST_CERTIFICATE must also be on, as above. */
1103 secStatus
= SSL_OptionSet(sslSocket
, SSL_REQUIRE_CERTIFICATE
, requireCert
);
1104 if (secStatus
!= SECSuccess
)
1106 server_error (_("Error in SSL_OptionSet:SSL_REQUIRE_CERTIFICATE"));
1111 /* Having changed socket configuration parameters, redo handshake. */
1112 secStatus
= SSL_ReHandshake(sslSocket
, PR_TRUE
);
1113 if (secStatus
!= SECSuccess
)
1115 server_error (_("Error in SSL_ReHandshake"));
1120 /* Force the handshake to complete before moving on. */
1121 secStatus
= SSL_ForceHandshake(sslSocket
);
1122 if (secStatus
!= SECSuccess
)
1124 server_error (_("Error in SSL_ForceHandshake"));
1131 #endif /* No client authentication and not authenticating after each transaction. */
1133 /* Function: writeDataToSocket
1135 * Purpose: Write the server's response back to the socket.
1139 writeDataToSocket(PRFileDesc
*sslSocket
, const char *responseFileName
)
1141 PRFileDesc
*local_file_fd
= PR_Open (responseFileName
, PR_RDONLY
, 0);
1142 if (local_file_fd
== NULL
)
1144 server_error (_F("Could not open input file %s", responseFileName
));
1149 /* Transmit the local file across the socket.
1151 int numBytes
= PR_TransmitFile (sslSocket
, local_file_fd
,
1153 PR_TRANSMITFILE_KEEP_OPEN
,
1154 PR_INTERVAL_NO_TIMEOUT
);
1156 /* Error in transmission. */
1157 SECStatus secStatus
= SECSuccess
;
1160 server_error (_("Error writing response to socket"));
1162 secStatus
= SECFailure
;
1165 PR_Close (local_file_fd
);
1170 get_stap_locale (const string
&staplang
, vector
<string
> &envVec
, string stapstderr
, cs_protocol_version
*client_version
)
1172 // If the client version is < 1.6, then no file containing environment
1173 // variables defining the locale has been passed.
1174 if (*client_version
< "1.6")
1177 /* Go through each line of the file, verify it, then add it to the vector */
1179 langfile
.open(staplang
.c_str());
1180 if (!langfile
.is_open())
1182 // Not fatal. Proceed with the environment we have.
1183 server_error(_F("Unable to open file %s for reading: %s", staplang
.c_str(),
1188 /* Unpackage internationalization variables and verify their contents */
1189 map
<string
, string
> envMap
; /* To temporarily store the entire array of strings */
1191 const set
<string
> &locVars
= localization_variables();
1193 /* Copy the global environ variable into the map */
1196 for (unsigned i
=0; environ
[i
]; i
++)
1198 string line
= (string
)environ
[i
];
1200 /* Find the first '=' sign */
1201 size_t pos
= line
.find("=");
1203 /* Make sure it found an '=' sign */
1204 if(pos
!= string::npos
)
1205 /* Everything before the '=' sign is the key, and everything after is the value. */
1206 envMap
[line
.substr(0, pos
)] = line
.substr(pos
+1);
1210 /* Create regular expression objects to verify lines read from file. Should not allow
1211 spaces, ctrl characters, etc */
1213 if ((regcomp(&checkre
, "^[a-zA-Z0-9@_.=-]*$", REG_EXTENDED
| REG_NOSUB
) != 0))
1215 // Not fatal. Proceed with the environment we have.
1216 server_error(_F("Error in regcomp: %s", strerror (errno
)));
1222 getline(langfile
, line
);
1223 if (!langfile
.good())
1226 /* Extract key and value from the line. Note: value may contain "=". */
1230 pos
= line
.find("=");
1231 if (pos
== string::npos
)
1233 client_error(_F("Localization key=value line '%s' cannot be parsed", line
.c_str()), stapstderr
);
1236 key
= line
.substr(0, pos
);
1238 value
= line
.substr(pos
);
1240 /* Make sure the key is found in the localization variables global set */
1241 if (locVars
.find(key
) == locVars
.end())
1243 // Not fatal. Just ignore it.
1244 client_error(_F("Localization key '%s' not found in global list", key
.c_str()), stapstderr
);
1248 /* Make sure the value does not contain illegal characters */
1249 if ((regexec(&checkre
, value
.c_str(), (size_t) 0, NULL
, 0) != 0))
1251 // Not fatal. Just ignore it.
1252 client_error(_F("Localization value '%s' contains illegal characters", value
.c_str()), stapstderr
);
1256 /* All is good, copy line into envMap, replacing if already there */
1257 envMap
[key
] = value
;
1260 if (!langfile
.eof())
1262 // Not fatal. Proceed with what we have.
1263 server_error(_F("Error reading file %s: %s", staplang
.c_str(), strerror (errno
)));
1268 /* Copy map into vector */
1269 for (map
<string
, string
>::iterator it
= envMap
.begin(); it
!= envMap
.end(); it
++)
1270 envVec
.push_back(it
->first
+ "=" + it
->second
);
1274 get_client_mok_fingerprints (const string
&filename
,
1275 vector
<string
> &mok_fingerprints
,
1277 cs_protocol_version
*client_version
)
1279 // If the client version is < 1.6, then no file containing MOK
1280 // fingerprints could have been passed.
1281 if (*client_version
< "1.6") {
1285 // Go through each line of the file and add it to the vector.
1287 file
.open(filename
.c_str());
1288 if (! file
.is_open())
1289 // If the file isn't present, that's fine. It just means that the
1290 // module doesn't need to be signed.
1293 // Create a regular expression object to verify lines read from the
1296 if (regcomp(&checkre
, "^([0-9a-f]{2}(:[0-9a-f]{2})+)$", REG_EXTENDED
)
1299 // Not fatal, just ignore the MOK fingerprints.
1300 server_error(_F("Error in MOK fingerprint regcomp: %s",
1305 // Unpack the MOK fingerprints. Notice we make sure the fingerprint
1306 // is in the right format, but that's all we can do at this
1307 // point. Later we'll check this client list against our server
1310 regmatch_t matches
[3];
1311 while (getline (file
, line
))
1313 string fingerprint
, issuer
;
1315 if ((regexec(&checkre
, line
.c_str(), 3, matches
, 0) != 0))
1317 // Not fatal. Just ignore it.
1318 client_error(_F("MOK fingerprint value '%s' isn't in the correct forma",
1319 line
.c_str()), stapstderr
);
1323 // Save the fingerprint:
1324 // matches[0] is the range of the entire match
1325 // matches[1] is the entire fingerprint
1326 // matches[2] is a portion of the fingerprint
1327 if (matches
[1].rm_so
>= 0)
1328 fingerprint
= line
.substr(matches
[1].rm_so
,
1329 matches
[1].rm_eo
- matches
[1].rm_so
);
1330 if (! fingerprint
.empty())
1331 mok_fingerprints
.push_back(fingerprint
);
1337 mok_sign_file (mok_info_t
&mok_info
,
1338 const std::string
&kernel_build_tree
,
1339 const std::string
&name
,
1340 std::string stapstderr
)
1346 cmd
.push_back (kernel_build_tree
+ "/scripts/sign-file");
1347 cmd
.push_back ("sha512");
1348 cmd
.push_back (mok_info
.directory
+ "/signing_key.priv");
1349 cmd
.push_back (mok_info
.directory
+ "/signing_key.x509");
1350 cmd
.push_back (name
);
1351 // FIXME: Should we do anything if this fails?
1352 rc
= stap_system (0, cmd
);
1354 server_error (_F("Running sign-file failed, rc = %d", rc
));
1356 client_error (_F("Module signed with MOK, issuer \"%s\", serial number \"%s\"",
1357 mok_info
.issuer
.c_str(), mok_info
.serial_number
.c_str()),
1361 // Filter paths prefixed with the server's home directory from the given file.
1364 filter_response_file (const string
&file_name
, const string
&responseDirName
)
1368 // Filter the server's home directory name
1370 cmd
.push_back ("sed");
1371 cmd
.push_back ("-i");
1372 cmd
.push_back (string ("s,") + get_home_directory () + ",<server>,g");
1373 cmd
.push_back (file_name
);
1374 stap_system (0, cmd
);
1376 // Filter the server's response directory name
1378 cmd
.push_back ("sed");
1379 cmd
.push_back ("-i");
1380 cmd
.push_back (string ("s,") + responseDirName
+ ",<server>,g");
1381 cmd
.push_back (file_name
);
1382 stap_system (0, cmd
);
1386 getRequestedPrivilege (const vector
<string
> &stapargv
)
1388 // The purpose of this function is to find the --privilege or --unprivileged option specified
1389 // by the user on the client side. We need to parse the command line completely, but we can
1390 // exit when we find the first --privilege or --unprivileged option, since stap does not allow
1391 // multiple privilege levels to specified on the same command line.
1393 // Note that we need not do any options consistency checking since our spawned stap instance
1396 // Create an argv/argc for use by getopt_long.
1397 int argc
= stapargv
.size();
1398 char ** argv
= new char *[argc
+ 1];
1399 for (unsigned i
= 0; i
< stapargv
.size(); ++i
)
1400 argv
[i
] = (char *)stapargv
[i
].c_str();
1403 privilege_t privilege
= pr_highest
; // Until specified otherwise.
1407 // We need only allow getopt to parse the options until we find a
1408 // --privilege or --unprivileged option.
1409 int grc
= getopt_long (argc
, argv
, STAP_SHORT_OPTIONS
, stap_long_options
, NULL
);
1415 // We can ignore all options other than --privilege and --unprivileged.
1417 case LONG_OPT_PRIVILEGE
:
1418 if (strcmp (optarg
, "stapdev") == 0)
1419 privilege
= pr_stapdev
;
1420 else if (strcmp (optarg
, "stapsys") == 0)
1421 privilege
= pr_stapsys
;
1422 else if (strcmp (optarg
, "stapusr") == 0)
1423 privilege
= pr_stapusr
;
1426 server_error (_F("Invalid argument '%s' for --privilege", optarg
));
1427 privilege
= pr_highest
;
1429 // We have discovered the client side --privilege option. We can exit now since
1430 // stap only tolerates one privilege setting option.
1431 goto done
; // break 2 switches and a loop
1432 case LONG_OPT_UNPRIVILEGED
:
1433 privilege
= pr_unprivileged
;
1434 // We have discovered the client side --unprivileged option. We can exit now since
1435 // stap only tolerates one privilege setting option.
1436 goto done
; // break 2 switches and a loop
1444 /* Run the translator on the data in the request directory, and produce output
1445 in the given output directory. */
1447 handleRequest (const string
&requestDirName
, const string
&responseDirName
, string stapstderr
)
1449 vector
<string
> stapargv
;
1450 cs_protocol_version client_version
= "1.0"; // Assumed until discovered otherwise
1457 // Save the server version. Do this early, so the client knows what version of the server
1458 // it is dealing with, even if the request is not fully completed.
1459 string stapversion
= responseDirName
+ "/version";
1460 f
= fopen (stapversion
.c_str (), "w");
1463 fputs (CURRENT_CS_PROTOCOL_VERSION
, f
);
1467 server_error (_F("Unable to open client version file %s", stapversion
.c_str ()));
1469 // Get the client version. The default version is already set. Use it if we fail here.
1470 string filename
= requestDirName
+ "/version";
1471 if (file_exists (filename
))
1472 read_from_file (filename
, client_version
);
1473 log (_F("Client version is %s", client_version
.v
));
1475 // The name of the translator executable.
1476 stapargv
.push_back ((char *)(getenv ("SYSTEMTAP_STAP") ?: STAP_PREFIX
"/bin/stap"));
1478 /* Transcribe stap_options. We use plain wordexp(3), since these
1479 options are coming from the local trusted user, so malicious
1480 content is not a concern. */
1481 // TODO: Use tokenize here.
1482 rc
= wordexp (stap_options
.c_str (), & words
, WRDE_NOCMD
|WRDE_UNDEF
);
1485 server_error (_("Cannot parse stap options"));
1489 for (u
=0; u
<words
.we_wordc
; u
++)
1490 stapargv
.push_back (words
.we_wordv
[u
]);
1492 /* Process the saved command line arguments. Avoid quoting/unquoting errors by
1493 transcribing literally. */
1494 string new_staptmpdir
= responseDirName
+ "/stap000000";
1495 rc
= mkdir(new_staptmpdir
.c_str(), 0700);
1497 server_error(_F("Could not create temporary directory %s", new_staptmpdir
.c_str()));
1499 stapargv
.push_back("--tmpdir=" + new_staptmpdir
);
1501 stapargv
.push_back ("--client-options");
1504 char stapargfile
[PATH_MAX
];
1509 snprintf (stapargfile
, PATH_MAX
, "%s/argv%d", requestDirName
.c_str (), i
);
1511 rc
= stat(stapargfile
, & st
);
1514 arg
= (char *)malloc (st
.st_size
+1);
1517 server_error (_("Out of memory"));
1521 argfile
= fopen(stapargfile
, "r");
1525 server_error (_F("Error opening %s: %s", stapargfile
, strerror (errno
)));
1529 rc
= fread(arg
, 1, st
.st_size
, argfile
);
1530 if (rc
!= st
.st_size
)
1534 server_error (_F("Error reading %s: %s", stapargfile
, strerror (errno
)));
1538 arg
[st
.st_size
] = '\0';
1539 stapargv
.push_back (arg
);
1544 string stapstdout
= responseDirName
+ "/stdout";
1546 // NB: Before, when we did not fully parse the client's command line using getopt_long,
1547 // we used to insert a --privilege=XXX option here in case some other argument was mistaken
1548 // for a --privilege or --unprivileged option by our spawned stap. Since we now parse
1549 // the client's command line using getopt_long and share the getopt_long options
1550 // string and table with stap, this is no longer necessary. stap will parse the
1551 // command line identically to the way we have parsed it and will discover the same
1552 // privilege-setting option.
1554 // Environment variables (possibly empty) to be passed to spawn_and_wait().
1555 string staplang
= requestDirName
+ "/locale";
1556 vector
<string
> envVec
;
1557 get_stap_locale (staplang
, envVec
, stapstderr
, &client_version
);
1559 // Machine owner keys (MOK) fingerprints (possibly nonexistent), to
1560 // be used as a list of valid keys that the module must be signed with.
1561 vector
<string
> client_mok_fingerprints
;
1563 // Matching MOK fingerprint path and issuer.
1564 mok_info_t
*mok_info
= NULL
;
1565 get_client_mok_fingerprints(requestDirName
+ "/mok_fingerprints",
1566 client_mok_fingerprints
, stapstderr
,
1568 if (! client_mok_fingerprints
.empty())
1570 // If the client requires signing, and we don't have any keys on
1571 // the server, we can't build a signed module.
1572 if (server_mok_map
.empty())
1574 client_error(_("No machine owner keys (MOK) are available on the server to sign the module."), stapstderr
);
1578 // Check the list of client MOK fingerprints against the list of
1579 // server MOK fingerprints. Look for any match.
1580 vector
<string
>::const_iterator it
;
1581 for (it
= client_mok_fingerprints
.begin();
1582 it
!= client_mok_fingerprints
.end(); it
++)
1584 mok_map_iterator mi
;
1585 mi
= server_mok_map
.find(*it
);
1586 if (mi
!= server_mok_map
.end())
1588 mok_info
= mi
->second
;
1593 // If the client requires signing, but we couldn't find a
1594 // matching machine owner key installed on the server, we can't
1595 // build a signed module.
1596 if (mok_info
== NULL
)
1598 client_error(_("No matching machine owner key (MOK) available on the server to sign the module."), stapstderr
);
1601 server_error(_F("The module will be signed with the following MOK, issuer=\"%s\" serial number=\"%s\"",
1602 mok_info
->issuer
.c_str(),
1603 mok_info
->serial_number
.c_str()));
1606 /* All ready, let's run the translator! */
1608 rc
= spawn_and_wait(stapargv
, &staprc
, "/dev/null", stapstdout
.c_str (),
1609 stapstderr
.c_str (), requestDirName
.c_str (), envVec
);
1610 if (rc
!= PR_SUCCESS
)
1612 server_error(_("Failed spawning translator"));
1617 ofstream
ofs((responseDirName
+ "/rc").c_str());
1621 // In unprivileged modes, if we have a module built, we need to sign
1622 // the sucker. We also might need to sign the module for secure
1624 privilege_t privilege
= getRequestedPrivilege (stapargv
);
1625 if (pr_contains (privilege
, pr_stapusr
)
1626 || pr_contains (privilege
, pr_stapsys
) || mok_info
)
1629 char pattern
[PATH_MAX
];
1630 snprintf (pattern
, PATH_MAX
, "%s/*.ko", new_staptmpdir
.c_str());
1631 rc
= glob (pattern
, GLOB_ERR
, NULL
, &globber
);
1633 server_error (_F("Unable to find a module in %s", new_staptmpdir
.c_str()));
1634 else if (globber
.gl_pathc
!= 1)
1635 server_error (_F("Too many modules (%zu) in %s", globber
.gl_pathc
, new_staptmpdir
.c_str()));
1638 if (pr_contains (privilege
, pr_stapusr
)
1639 || pr_contains (privilege
, pr_stapsys
))
1640 sign_file (cert_db_path
, server_cert_nickname(),
1641 globber
.gl_pathv
[0],
1642 string(globber
.gl_pathv
[0]) + ".sgn");
1644 mok_sign_file(*mok_info
, kernel_build_tree
, globber
.gl_pathv
[0],
1649 /* If uprobes.ko is required, it will have been built or cache-copied into
1650 * the temp directory. We need to pack it into the response where the client
1651 * can find it, and sign, if necessary, for unprivileged users.
1653 string uprobes_ko
= new_staptmpdir
+ "/uprobes/uprobes.ko";
1654 if (get_file_size(uprobes_ko
) > 0)
1656 /* uprobes.ko is required.
1658 * It's already underneath the stap tmpdir, but older stap clients
1659 * don't know to look for it there, so, for these clients, we end up packing uprobes twice
1660 * into the zip. We could move instead of symlink.
1662 string uprobes_response
;
1663 if (client_version
< "1.6")
1665 uprobes_response
= (string
)responseDirName
+ "/uprobes.ko";
1666 rc
= symlink(uprobes_ko
.c_str(), uprobes_response
.c_str());
1668 server_error (_F("Could not link to %s from %s",
1669 uprobes_ko
.c_str(), uprobes_response
.c_str()));
1672 uprobes_response
= uprobes_ko
;
1674 /* In unprivileged mode, we need a signature on uprobes as well. */
1675 if (! pr_contains (privilege
, pr_stapdev
))
1677 sign_file (cert_db_path
, server_cert_nickname(),
1678 uprobes_response
, uprobes_response
+ ".sgn");
1681 mok_sign_file(*mok_info
, kernel_build_tree
, uprobes_response
,
1685 /* Free up all the arg string copies. Note that the first few were alloc'd
1686 by wordexp(), which wordfree() frees; others were hand-set to literal strings. */
1689 // Filter paths prefixed with the server's home directory from the stdout and stderr
1690 // files in the response.
1691 filter_response_file (stapstdout
, responseDirName
);
1692 filter_response_file (stapstderr
, responseDirName
);
1694 /* Sorry about the inconvenience. C string/file processing is such a pleasure. */
1698 /* A front end for stap_spawn that handles stdin, stdout, stderr, switches to a working
1699 directory and returns overall success or failure. */
1701 spawn_and_wait (const vector
<string
> &argv
, int *spawnrc
,
1702 const char* fd0
, const char* fd1
, const char* fd2
,
1703 const char *pwd
, const vector
<string
>& envVec
)
1707 posix_spawn_file_actions_t actions
;
1710 #define CHECKRC(msg) do { if (rc) { server_error (_(msg)); return PR_FAILURE; } } while (0)
1712 rc
= posix_spawn_file_actions_init (& actions
);
1713 CHECKRC ("Error in spawn file actions ctor");
1715 rc
= posix_spawn_file_actions_addopen(& actions
, 0, fd0
, O_RDONLY
, 0600);
1716 CHECKRC ("Error in spawn file actions fd0");
1719 rc
= posix_spawn_file_actions_addopen(& actions
, 1, fd1
, O_WRONLY
|O_CREAT
, 0600);
1720 CHECKRC ("Error in spawn file actions fd1");
1723 // Use append mode for stderr because it gets written to in other places in the server.
1724 rc
= posix_spawn_file_actions_addopen(& actions
, 2, fd2
, O_WRONLY
|O_APPEND
|O_CREAT
, 0600);
1725 CHECKRC ("Error in spawn file actions fd2");
1728 /* change temporarily to a directory if requested */
1731 dotfd
= open (".", O_RDONLY
);
1734 server_error (_("Error in spawn getcwd"));
1742 server_error(_("Error in spawn chdir"));
1747 pid
= stap_spawn (0, argv
, & actions
, envVec
);
1748 /* NB: don't react to pid==-1 right away; need to chdir back first. */
1750 if (pwd
&& dotfd
>= 0)
1753 subrc
= fchdir (dotfd
);
1754 subrc
|= close (dotfd
);
1756 server_error (_("Error in spawn unchdir"));
1761 server_error (_F("Error in spawn: %s", strerror (errno
)));
1765 *spawnrc
= stap_waitpid (0, pid
);
1766 if (*spawnrc
== -1) // something wrong with waitpid() call itself
1768 server_error (_("Error in waitpid"));
1772 rc
= posix_spawn_file_actions_destroy (&actions
);
1773 CHECKRC ("Error in spawn file actions dtor");
1779 /* Function: void *handle_connection()
1781 * Purpose: Handle a connection to a socket. Copy in request zip
1782 * file, process it, copy out response. Temporary directories are
1783 * created & destroyed here.
1787 handle_connection (void *arg
)
1789 PRFileDesc
* sslSocket
= NULL
;
1790 SECStatus secStatus
= SECFailure
;
1794 char tmpdir
[PATH_MAX
];
1795 char requestFileName
[PATH_MAX
];
1796 char requestDirName
[PATH_MAX
];
1797 char responseDirName
[PATH_MAX
];
1798 char responseFileName
[PATH_MAX
];
1799 string stapstderr
; /* Cannot be global since we need a unique
1800 copy for each connection.*/
1801 vector
<string
> argv
;
1804 /* Detatch to avoid a memory leak */
1806 pthread_detach(pthread_self());
1808 /* Unpack the arg */
1809 thread_arg
*t_arg
= (thread_arg
*) arg
;
1810 PRFileDesc
*tcpSocket
= t_arg
->tcpSocket
;
1811 CERTCertificate
*cert
= t_arg
->cert
;
1812 SECKEYPrivateKey
*privKey
= t_arg
->privKey
;
1813 PRNetAddr addr
= t_arg
->addr
;
1815 tmpdir
[0]='\0'; /* prevent cleanup-time /bin/rm of uninitialized directory */
1817 #if 0 // already done on the listenSocket
1818 /* Make sure the socket is blocking. */
1819 PRSocketOptionData socketOption
;
1820 socketOption
.option
= PR_SockOpt_Nonblocking
;
1821 socketOption
.value
.non_blocking
= PR_FALSE
;
1822 PR_SetSocketOption (tcpSocket
, &socketOption
);
1824 secStatus
= SECFailure
;
1825 sslSocket
= setupSSLSocket (tcpSocket
, cert
, privKey
);
1826 if (sslSocket
== NULL
)
1828 // Message already issued.
1832 secStatus
= SSL_ResetHandshake(sslSocket
, /* asServer */ PR_TRUE
);
1833 if (secStatus
!= SECSuccess
)
1835 server_error (_("Error resetting SSL handshake"));
1840 #if 0 // The client authenticates the server, so the client initiates the handshake
1841 /* Force the handshake to complete before moving on. */
1842 secStatus
= SSL_ForceHandshake(sslSocket
);
1843 if (secStatus
!= SECSuccess
)
1845 server_error (_("Error forcing SSL handshake"));
1851 secStatus
= SECFailure
;
1852 snprintf(tmpdir
, PATH_MAX
, "%s/stap-server.XXXXXX", getenv("TMPDIR") ?: "/tmp");
1853 rc1
= mkdtemp(tmpdir
);
1856 server_error (_F("Could not create temporary directory %s: %s", tmpdir
, strerror(errno
)));
1857 tmpdir
[0]=0; /* prevent /bin/rm */
1861 /* Create a temporary files names and directories. */
1862 snprintf (requestFileName
, PATH_MAX
, "%s/request.zip", tmpdir
);
1864 snprintf (requestDirName
, PATH_MAX
, "%s/request", tmpdir
);
1865 rc
= mkdir(requestDirName
, 0700);
1868 server_error (_F("Could not create temporary directory %s: %s", requestDirName
, strerror (errno
)));
1872 snprintf (responseDirName
, PATH_MAX
, "%s/response", tmpdir
);
1873 rc
= mkdir(responseDirName
, 0700);
1876 server_error (_F("Could not create temporary directory %s: %s", responseDirName
, strerror (errno
)));
1879 // Set this early, since it gets used for errors to be returned to the client.
1880 stapstderr
= string(responseDirName
) + "/stderr";
1882 snprintf (responseFileName
, PATH_MAX
, "%s/response.zip", tmpdir
);
1884 /* Read data from the socket.
1885 * If the user is requesting/requiring authentication, authenticate
1887 bytesRead
= readDataFromSocket(sslSocket
, requestFileName
);
1888 if (bytesRead
< 0) // Error
1890 if (bytesRead
== 0) // No request -- not an error
1892 secStatus
= SECSuccess
;
1896 #if 0 /* Don't authenticate after each transaction */
1897 if (REQUEST_CERT_ALL
)
1899 secStatus
= authenticateSocket(sslSocket
);
1900 if (secStatus
!= SECSuccess
)
1905 /* Unzip the request. */
1906 secStatus
= SECFailure
;
1907 argv
.push_back ("unzip");
1908 argv
.push_back ("-q");
1909 argv
.push_back ("-d");
1910 argv
.push_back (requestDirName
);
1911 argv
.push_back (requestFileName
);
1912 rc
= stap_system (0, argv
);
1915 server_error (_("Unable to extract client request"));
1919 /* Handle the request zip file. An error therein should still result
1920 in a response zip file (containing stderr etc.) so we don't have to
1921 have a result code here. */
1922 handleRequest(requestDirName
, responseDirName
, stapstderr
);
1924 /* Zip the response. */
1927 argv
.push_back ("zip");
1928 argv
.push_back ("-q");
1929 argv
.push_back ("-r");
1930 argv
.push_back (responseFileName
);
1931 argv
.push_back (".");
1932 rc
= spawn_and_wait (argv
, &ziprc
, NULL
, NULL
, NULL
, responseDirName
);
1933 if (rc
!= PR_SUCCESS
|| ziprc
!= 0)
1935 server_error (_("Unable to compress server response"));
1939 secStatus
= writeDataToSocket (sslSocket
, responseFileName
);
1943 if (PR_Close (sslSocket
) != PR_SUCCESS
)
1945 server_error (_("Error closing ssl socket"));
1951 // Remove the whole tmpdir and all that lies beneath, unless -k was specified.
1953 log (_F("Keeping temporary directory %s", tmpdir
));
1957 argv
.push_back ("rm");
1958 argv
.push_back ("-r");
1959 argv
.push_back (tmpdir
);
1960 rc
= stap_system (0, argv
);
1962 server_error (_("Error in tmpdir cleanup"));
1966 if (secStatus
!= SECSuccess
)
1967 server_error (_("Error processing client request"));
1969 // Log the end of the request.
1971 prStatus
= PR_NetAddrToString (& addr
, buf
, sizeof (buf
));
1972 if (prStatus
== PR_SUCCESS
)
1974 if (addr
.raw
.family
== PR_AF_INET
)
1975 log (_F("Request from %s:%d complete", buf
, addr
.inet
.port
));
1976 else if (addr
.raw
.family
== PR_AF_INET6
)
1977 log (_F("Request from [%s]:%d complete", buf
, addr
.ipv6
.port
));
1980 /* Increment semephore to indicate this thread is finished. */
1982 if (max_threads
> 0)
1984 sem_post(&sem_client
);
1991 /* Function: int accept_connection()
1993 * Purpose: Accept a connection to the socket.
1997 accept_connections (PRFileDesc
*listenSocket
, CERTCertificate
*cert
)
2000 PRFileDesc
*tcpSocket
;
2002 SECStatus secStatus
;
2003 CERTCertDBHandle
*dbHandle
;
2008 dbHandle
= CERT_GetDefaultCertDB ();
2010 // cert_db_path gets passed to nssPasswordCallback.
2011 SECKEYPrivateKey
*privKey
= PK11_FindKeyByAnyCert (cert
, (void*)cert_db_path
.c_str ());
2012 if (privKey
== NULL
)
2014 server_error (_("Unable to obtain certificate private key"));
2019 while (pending_interrupts
== 0)
2021 /* Accept a connection to the socket. */
2022 tcpSocket
= PR_Accept (listenSocket
, &addr
, PR_INTERVAL_MIN
);
2023 if (tcpSocket
== NULL
)
2025 if(PR_GetError() == PR_IO_TIMEOUT_ERROR
)
2029 server_error (_("Error accepting client connection"));
2034 /* Log the accepted connection. */
2036 prStatus
= PR_NetAddrToString (&addr
, buf
, sizeof (buf
));
2037 if (prStatus
== PR_SUCCESS
)
2039 if (addr
.raw
.family
== PR_AF_INET
)
2040 log (_F("Accepted connection from %s:%d", buf
, addr
.inet
.port
));
2041 else if (addr
.raw
.family
== PR_AF_INET6
)
2042 log (_F("Accepted connection from [%s]:%d", buf
, addr
.ipv6
.port
));
2045 /* XXX: alarm() or somesuch to set a timeout. */
2047 /* Accepted the connection, now handle it. */
2049 /* Wait for a thread to finish if there are none available */
2053 sem_getvalue(&sem_client
, &idle_threads
);
2054 if(idle_threads
<= 0)
2055 log(_("Server is overloaded. Processing times may be longer than normal."));
2056 else if (idle_threads
== max_threads
)
2057 log(_("Processing 1 request..."));
2059 log(_F("Processing %d concurrent requests...", ((int)max_threads
- idle_threads
) + 1));
2061 sem_wait(&sem_client
);
2064 /* Create the argument structure to pass to pthread_create
2065 * (or directly to handle_connection if max_threads == 0 */
2066 t_arg
= (thread_arg
*)malloc(sizeof(*t_arg
));
2068 fatal(_("No memory available for new thread arg!"));
2069 t_arg
->tcpSocket
= tcpSocket
;
2071 t_arg
->privKey
= privKey
;
2074 /* Handle the conncection */
2075 if (max_threads
> 0)
2076 /* Create the worker thread and handle the connection. */
2077 pthread_create(&tid
, NULL
, handle_connection
, t_arg
);
2079 /* Since max_threads == 0, don't spawn a new thread,
2080 * just handle in the current thread. */
2081 handle_connection(t_arg
);
2083 // If our certificate is no longer valid (e.g. has expired), then exit.
2084 secStatus
= CERT_VerifyCertNow (dbHandle
, cert
, PR_TRUE
/*checkSig*/,
2085 certUsageSSLServer
, NULL
/*wincx*/);
2086 if (secStatus
!= SECSuccess
)
2088 // Not an error. Exit the loop so a new cert can be generated.
2093 SECKEY_DestroyPrivateKey (privKey
);
2097 /* Function: void server_main()
2099 * Purpose: This is the server's main function. It configures a socket
2100 * and listens to it.
2104 server_main (PRFileDesc
*listenSocket
)
2110 SECStatus secStatus
= nssInit (cert_db_path
.c_str ());
2111 if (secStatus
!= SECSuccess
)
2113 // Message already issued.
2117 // Preinitialized here due to jumps to the label 'done'.
2118 CERTCertificate
*cert
= NULL
;
2119 bool serverCacheConfigured
= false;
2121 // Enable all cipher suites.
2122 // NB: The NSS docs say that SSL_ClearSessionCache is required for the new settings to take
2123 // effect, however, calling it puts NSS in a state where it will not shut down cleanly.
2124 // We need to be able to shut down NSS cleanly if we are to generate a new certificate when
2125 // ours expires. It should be noted however, thet SSL_ClearSessionCache only clears the
2126 // client cache, and we are a server.
2127 /* Some NSS versions don't do this correctly in NSS_SetDomesticPolicy. */
2129 const PRUint16
*cipher
;
2130 for (cipher
= SSL_ImplementedCiphers
; *cipher
!= 0; ++cipher
)
2131 SSL_CipherPolicySet(*cipher
, SSL_ALLOWED
);
2133 // SSL_ClearSessionCache ();
2135 // Configure the SSL session cache for a single process server with the default settings.
2136 secStatus
= SSL_ConfigServerSessionIDCache (0, 0, 0, NULL
);
2137 if (secStatus
!= SECSuccess
)
2139 server_error (_("Unable to configure SSL server session ID cache"));
2143 serverCacheConfigured
= true;
2145 /* Get own certificate. */
2146 cert
= PK11_FindCertFromNickname (server_cert_nickname (), NULL
);
2149 server_error (_F("Unable to find our certificate in the database at %s",
2150 cert_db_path
.c_str ()));
2155 // Tell the world that we're listening.
2156 advertise_presence (cert
);
2158 /* Handle connections to the socket. */
2159 secStatus
= accept_connections (listenSocket
, cert
);
2161 // Tell the world we're no longer listening.
2162 unadvertise_presence ();
2164 sem_getvalue(&sem_client
, &idle_threads
);
2166 /* Wait for requests to finish or the timeout to be reached.
2167 * If we got here from an interrupt, exit immediately if
2168 * the timeout is reached. Otherwise, wait indefinitiely
2169 * until the threads exit (or an interrupt is recieved).*/
2170 if(idle_threads
< max_threads
)
2171 log(_F("Waiting for %d outstanding requests to complete...", (int)max_threads
- idle_threads
));
2172 while(idle_threads
< max_threads
)
2174 if(pending_interrupts
&& timeout
++ > CONCURRENCY_TIMEOUT_S
)
2176 log(_("Timeout reached, exiting (forced)"));
2177 kill_stap_spawn (SIGTERM
);
2182 sem_getvalue(&sem_client
, &idle_threads
);
2188 CERT_DestroyCertificate (cert
);
2191 if (serverCacheConfigured
&& SSL_ShutdownServerSessionIDCache () != SECSuccess
)
2193 server_error (_("Unable to shut down server session ID cache"));
2196 nssCleanup (cert_db_path
.c_str ());
2204 // Create a new socket.
2205 PRFileDesc
*listenSocket
= PR_OpenTCPSocket (PR_AF_INET6
); // Accepts IPv4 too
2206 if (listenSocket
== NULL
)
2208 server_error (_("Error creating socket"));
2213 // Set socket to be blocking - on some platforms the default is nonblocking.
2214 PRSocketOptionData socketOption
;
2215 socketOption
.option
= PR_SockOpt_Nonblocking
;
2216 socketOption
.value
.non_blocking
= PR_FALSE
;
2217 PRStatus prStatus
= PR_SetSocketOption (listenSocket
, & socketOption
);
2218 if (prStatus
!= PR_SUCCESS
)
2220 server_error (_("Error setting socket properties"));
2225 // Allow the socket address to be reused, in case we want the same port across a
2226 // 'service stap-server restart'
2227 socketOption
.option
= PR_SockOpt_Reuseaddr
;
2228 socketOption
.value
.reuse_addr
= PR_TRUE
;
2229 prStatus
= PR_SetSocketOption (listenSocket
, & socketOption
);
2230 if (prStatus
!= PR_SUCCESS
)
2232 server_error (_("Error setting socket properties"));
2237 // Configure the network connection.
2239 memset (& addr
, 0, sizeof(addr
));
2240 prStatus
= PR_InitializeNetAddr (PR_IpAddrAny
, port
, & addr
);
2241 addr
.ipv6
.family
= PR_AF_INET6
;
2243 // addr.inet.ip = PR_htonl(PR_INADDR_ANY);
2244 PR_StringToNetAddr ("::", & addr
);
2245 // PR_StringToNetAddr ("fe80::5eff:35ff:fe07:55ca", & addr);
2246 // PR_StringToNetAddr ("::1", & addr);
2247 addr
.ipv6
.port
= PR_htons (port
);
2250 // Bind the socket to an address. Retry if the selected port is busy, unless the port was
2251 // specified directly.
2254 /* Bind the address to the listener socket. */
2255 prStatus
= PR_Bind (listenSocket
, & addr
);
2256 if (prStatus
== PR_SUCCESS
)
2259 // If the selected port is busy. Try another, but only if a specific port was not specified.
2260 PRErrorCode errorNumber
= PR_GetError ();
2261 switch (errorNumber
)
2263 case PR_ADDRESS_NOT_AVAILABLE_ERROR
:
2266 server_error (_F("Network port %hu is unavailable. Trying another port", port
));
2270 case PR_ADDRESS_IN_USE_ERROR
:
2273 server_error (_F("Network port %hu is busy. Trying another port", port
));
2280 server_error (_("Error setting socket address"));
2285 // Query the socket for the port that was assigned.
2286 prStatus
= PR_GetSockName (listenSocket
, &addr
);
2287 if (prStatus
!= PR_SUCCESS
)
2289 server_error (_("Unable to obtain socket address"));
2294 prStatus
= PR_NetAddrToString (&addr
, buf
, sizeof (buf
));
2295 port
= PR_ntohs (addr
.ipv6
.port
);
2296 log (_F("Using network address [%s]:%hu", buf
, port
));
2298 if (max_threads
> 0)
2299 log (_F("Using a maximum of %ld threads", max_threads
));
2301 log (_("Concurrency disabled"));
2303 // Listen for connection on the socket. The second argument is the maximum size of the queue
2304 // for pending connections.
2305 prStatus
= PR_Listen (listenSocket
, 5);
2306 if (prStatus
!= PR_SUCCESS
)
2308 server_error (_("Error listening on socket"));
2313 /* Initialize semephore with the maximum number of threads
2314 * defined by --max-threads. If it is not defined, the
2315 * default is the number of processors */
2316 sem_init(&sem_client
, 0, max_threads
);
2318 // Loop forever. We check our certificate (and regenerate, if necessary) and then start the
2319 // server. The server will go down when our certificate is no longer valid (e.g. expired). We
2320 // then generate a new one and start the server again.
2321 while(!pending_interrupts
)
2323 // Ensure that our certificate is valid. Generate a new one if not.
2324 if (check_cert (cert_db_path
, server_cert_nickname (), use_db_password
) != 0)
2326 // Message already issued
2330 // Ensure that our certificate is trusted by our local client.
2331 // Construct the client database path relative to the server database path.
2332 SECStatus secStatus
= add_client_cert (server_cert_file (),
2333 local_client_cert_db_path ());
2334 if (secStatus
!= SECSuccess
)
2336 // Not fatal. Other clients may trust the server and trust can be added
2337 // for the local client in other ways.
2338 server_error (_("Unable to authorize certificate for the local client"));
2341 // Launch the server.
2342 secStatus
= server_main (listenSocket
);
2346 sem_destroy(&sem_client
); /*Not really necessary, as we are shutting down...but for correctness */
2347 if (PR_Close (listenSocket
) != PR_SUCCESS
)
2349 server_error (_("Error closing listen socket"));
2355 main (int argc
, char **argv
) {
2356 initialize (argc
, argv
);
2362 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */