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-2018 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/>.
39 #include <sys/utsname.h>
40 #include <sys/types.h>
42 #include <semaphore.h>
51 #include <sys/ioctl.h>
54 #include <avahi-client/publish.h>
55 #include <avahi-common/alternative.h>
56 #include <avahi-common/thread-watch.h>
57 #include <avahi-common/malloc.h>
58 #include <avahi-common/error.h>
59 #include <avahi-common/domain.h>
60 #include <sys/inotify.h>
65 #include "nsscommon.h"
71 static void cleanup ();
72 static PRStatus
spawn_and_wait (const vector
<string
> &argv
, int *result
,
73 const char* fd0
, const char* fd1
, const char* fd2
,
74 const char *pwd
, const vector
<string
>& envVec
= vector
<string
> ());
76 #define MOK_PRIVATE_CERT_NAME "signing_key.priv"
77 #define MOK_PRIVATE_CERT_FILE "/" MOK_PRIVATE_CERT_NAME
78 #define MOK_CONFIG_FILE "/x509.genkey"
79 // MOK_CONFIG_TEXT is the default MOK config text used when creating
80 // new MOKs. This text is saved to the MOK config file. Once we've
81 // created it, the server administrator can modify it.
82 #define MOK_CONFIG_TEXT \
84 "default_bits = 4096\n" \
85 "distinguished_name = req_distinguished_name\n" \
87 "x509_extensions = myexts\n" \
89 "[ req_distinguished_name ]\n" \
91 "CN = Systemtap module signing key\n" \
94 "basicConstraints=critical,CA:FALSE\n" \
95 "keyUsage=digitalSignature\n" \
96 "subjectKeyIdentifier=hash\n" \
97 "authorityKeyIdentifier=keyid\n"
99 /* getopt variables */
102 /* File scope statics. Set during argument parsing and initialization. */
103 static bool use_db_password
;
104 static unsigned short port
;
105 static long max_threads
;
106 static size_t max_uncompressed_req_size
;
107 static size_t max_compressed_req_size
;
108 static string cert_db_path
;
109 static string stap_options
;
110 static map
<string
,string
> kernel_build_tree
; // Kernel version -> build tree
112 static string cert_serial_number
;
113 static string B_options
;
114 static string I_options
;
115 static string R_option
;
116 static string D_options
;
117 static bool keep_temp
;
118 static string mok_path
;
121 static int pending_interrupts
;
122 #define CONCURRENCY_TIMEOUT_S 3
125 // Server_error messages are printed to stderr and logged, if requested.
127 server_error (const string
&msg
, int logit
= true)
129 cerr
<< msg
<< endl
<< flush
;
130 // Log it, but avoid repeated messages to the terminal.
131 if (logit
&& log_ok ())
135 // client_error messages are treated as server errors and also printed to the client's stderr.
137 client_error (const string
&msg
, string stapstderr
)
140 if (! stapstderr
.empty ())
143 errfile
.open (stapstderr
.c_str (), ios_base::app
);
144 if (! errfile
.good ())
145 server_error (_F("Could not open client stderr file %s: %s", stapstderr
.c_str (),
148 errfile
<< "Server: " << msg
<< endl
;
149 // NB: No need to close errfile
153 // Messages from the nss common code are treated as server errors.
156 nsscommon_error (const char *msg
, int logit
)
158 server_error (msg
, logit
);
161 // Fatal errors are treated as server errors but also result in termination
164 fatal (const string
&msg
)
173 process_a (const string
&arg
)
176 stap_options
+= " -a " + arg
;
180 process_r (const string
&arg
)
182 if (arg
[0] == '/') // fully specified path
183 kernel_build_tree
.insert({kernel_release_from_build_tree(arg
), arg
});
185 kernel_build_tree
.insert({arg
, "/lib/modules/" + arg
+ "/build" });
189 process_log (const char *arg
)
195 parse_options (int argc
, char **argv
)
197 // Examine the command line. This is the command line for us (stap-serverd) not the command
198 // line for spawned stap instances.
205 // NB: The values of these enumerators must not conflict with the values of ordinary
206 // characters, since those are returned by getopt_long for short options.
212 LONG_OPT_MAXREQSIZE
= 254,
213 LONG_OPT_MAXCOMPRESSEDREQ
= 255 /* need to set a value otherwise there are conflicts */
215 static struct option long_options
[] = {
216 { "port", 1, NULL
, LONG_OPT_PORT
},
217 { "ssl", 1, NULL
, LONG_OPT_SSL
},
218 { "log", 1, NULL
, LONG_OPT_LOG
},
219 { "max-threads", 1, NULL
, LONG_OPT_MAXTHREADS
},
220 { "max-request-size", 1, NULL
, LONG_OPT_MAXREQSIZE
},
221 { "max-compressed-request", 1, NULL
, LONG_OPT_MAXCOMPRESSEDREQ
},
224 int grc
= getopt_long (argc
, argv
, "a:B:D:I:kPr:R:", long_options
, NULL
);
233 B_options
+= string (" -") + (char)grc
+ optarg
;
234 stap_options
+= string (" -") + (char)grc
+ optarg
;
237 D_options
+= string (" -") + (char)grc
+ optarg
;
238 stap_options
+= string (" -") + (char)grc
+ optarg
;
241 I_options
+= string (" -") + (char)grc
+ optarg
;
242 stap_options
+= string (" -") + (char)grc
+ optarg
;
248 use_db_password
= true;
254 R_option
= string (" -") + (char)grc
+ optarg
;
255 stap_options
+= string (" -") + (char)grc
+ optarg
;
258 port_tmp
= strtol (optarg
, &num_endptr
, 10);
259 if (*num_endptr
!= '\0')
260 fatal (_F("%s: cannot parse number '--port=%s'", argv
[0], optarg
));
261 else if (port_tmp
< 0 || port_tmp
> 65535)
262 fatal (_F("%s: invalid entry: port must be between 0 and 65535 '--port=%s'", argv
[0],
265 port
= (unsigned short) port_tmp
;
268 cert_db_path
= optarg
;
271 process_log (optarg
);
273 case LONG_OPT_MAXTHREADS
:
274 max_threads
= strtol (optarg
, &num_endptr
, 0);
275 if (*num_endptr
!= '\0')
276 fatal (_F("%s: cannot parse number '--max-threads=%s'", argv
[0], optarg
));
277 else if (max_threads
< 0)
278 fatal (_F("%s: invalid entry: max threads must not be negative '--max-threads=%s'",
281 case LONG_OPT_MAXREQSIZE
:
282 maxsize_tmp
= strtoul(optarg
, &num_endptr
, 0); // store as a long for now
283 if (*num_endptr
!= '\0')
284 fatal (_F("%s: cannot parse number '--max-request-size=%s'", argv
[0], optarg
));
285 else if (maxsize_tmp
< 1)
286 fatal (_F("%s: invalid entry: max (uncompressed) request size must be greater than 0 '--max-request-size=%s'",
288 max_uncompressed_req_size
= (size_t) maxsize_tmp
; // convert the long to an unsigned
290 case LONG_OPT_MAXCOMPRESSEDREQ
:
291 maxsize_tmp
= strtoul(optarg
, &num_endptr
, 0); // store as a long for now
292 if (*num_endptr
!= '\0')
293 fatal (_F("%s: cannot parse number '--max-compressed-request=%s'", argv
[0], optarg
));
294 else if (maxsize_tmp
< 1)
295 fatal (_F("%s: invalid entry: max compressed request size must be greater than 0 '--max-compressed-request=%s'",
297 max_compressed_req_size
= (size_t) maxsize_tmp
; // convert the long to an unsigned
300 // Invalid/unrecognized option given. Message has already been issued.
303 // Reached when one added a getopt option but not a corresponding switch/case:
305 server_error (_F("%s: unhandled option '%c %s'", argv
[0], (char)grc
, optarg
));
307 server_error (_F("%s: unhandled option '%c'", argv
[0], (char)grc
));
312 for (int i
= optind
; i
< argc
; i
++)
313 server_error (_F("%s: unrecognized argument '%s'", argv
[0], argv
[i
]));
319 return server_cert_db_path () + "/stap.cert";
322 // Signal handling. When an interrupt is received, kill any spawned processes
326 handle_interrupt (int sig
)
328 pending_interrupts
++;
329 if(pending_interrupts
>= 2)
331 log (_F("Received another signal %d, exiting (forced)", sig
));
334 log (_F("Received signal %d, exiting", sig
));
338 setup_signals (sighandler_t handler
)
342 memset(&sa
, 0, sizeof(sa
));
343 sa
.sa_handler
= handler
;
344 sigemptyset (&sa
.sa_mask
);
345 if (handler
!= SIG_IGN
)
347 sigaddset (&sa
.sa_mask
, SIGHUP
);
348 sigaddset (&sa
.sa_mask
, SIGPIPE
);
349 sigaddset (&sa
.sa_mask
, SIGINT
);
350 sigaddset (&sa
.sa_mask
, SIGTERM
);
351 sigaddset (&sa
.sa_mask
, SIGTTIN
);
352 sigaddset (&sa
.sa_mask
, SIGTTOU
);
353 sigaddset (&sa
.sa_mask
, SIGXFSZ
);
354 sigaddset (&sa
.sa_mask
, SIGXCPU
);
356 sa
.sa_flags
= SA_RESTART
;
358 sigaction (SIGHUP
, &sa
, NULL
);
359 sigaction (SIGPIPE
, &sa
, NULL
);
360 sigaction (SIGINT
, &sa
, NULL
);
361 sigaction (SIGTERM
, &sa
, NULL
);
362 sigaction (SIGTTIN
, &sa
, NULL
);
363 sigaction (SIGTTOU
, &sa
, NULL
);
364 sigaction (SIGXFSZ
, &sa
, NULL
);
365 sigaction (SIGXCPU
, &sa
, NULL
);
368 // Does the server contain a valid directory for the MOK fingerprint?
370 mok_dir_valid_p (string mok_fingerprint
, bool verbose
)
372 string mok_dir
= mok_path
+ "/" + mok_fingerprint
;
373 DIR *dirp
= opendir (mok_dir
.c_str());
376 // We can't open the directory. Just quit.
378 server_error (_F("Could not open server MOK fingerprint directory %s: %s",
379 mok_dir
.c_str(), strerror(errno
)));
383 // Find both the x509 certificate and private key files.
384 bool priv_found
= false;
385 bool cert_found
= false;
386 struct dirent
*direntp
;
387 while ((direntp
= readdir (dirp
)) != NULL
)
389 bool reg_file
= false;
391 if (direntp
->d_type
== DT_REG
)
393 else if (direntp
->d_type
== DT_UNKNOWN
)
397 // If the filesystem doesn't support d_type, we'll have to
399 int rc
= stat((mok_dir
+ "/" + direntp
->d_name
).c_str (), &tmpstat
);
400 if (rc
== 0 && S_ISREG(tmpstat
.st_mode
))
404 if (! priv_found
&& reg_file
405 && strcmp (direntp
->d_name
, MOK_PRIVATE_CERT_NAME
) == 0)
410 if (! cert_found
&& reg_file
411 && strcmp (direntp
->d_name
, MOK_PUBLIC_CERT_NAME
) == 0)
416 if (priv_found
&& cert_found
)
420 if (! priv_found
|| ! cert_found
)
422 // We didn't find one (or both) of the required files. Quit.
424 server_error (_F("Could not find server MOK files in directory %s",
429 // Grab info from the cert.
431 if (read_cert_info_from_file (mok_dir
+ MOK_PUBLIC_CERT_FILE
, fingerprint
)
434 // Make sure the fingerprint from the certificate matches the
436 if (fingerprint
!= mok_fingerprint
)
439 server_error (_F("Server MOK directory name '%s' doesn't match fingerprint from certificate %s",
440 mok_dir
.c_str(), fingerprint
.c_str()));
447 // Get the list of MOK fingerprints on the server. If
448 // 'only_one_needed' is true, just return the first MOK.
450 get_server_mok_fingerprints(vector
<string
> &mok_fingerprints
, bool verbose
,
451 bool only_one_needed
)
454 struct dirent
*direntp
;
458 mok_fingerprints
.clear ();
460 // The directory of machine owner keys (MOK) is optional, so if it
461 // doesn't exist, we don't worry about it.
462 dirp
= opendir (mok_path
.c_str ());
465 // If the error isn't ENOENT (Directory does not exist), we've got
466 // a non-fatal error.
468 server_error (_F("Could not open server MOK directory %s: %s",
469 mok_path
.c_str (), strerror (errno
)));
473 // Create a regular expression object to verify MOK fingerprints
476 if ((regcomp (&checkre
, "^[0-9a-f]{2}(:[0-9a-f]{2})+$",
477 REG_EXTENDED
| REG_NOSUB
) != 0))
479 // Not fatal, just ignore the MOK fingerprints.
480 server_error (_F("Error in MOK fingerprint regcomp: %s",
486 // We've opened the directory, so read all the directory names from
488 while ((direntp
= readdir (dirp
)) != NULL
)
490 // We're only interested in directories (of key files).
491 if (direntp
->d_type
!= DT_DIR
)
493 if (direntp
->d_type
== DT_UNKNOWN
)
495 // If the filesystem doesn't support d_type, we'll have to
498 int rc
= stat((mok_path
+ "/" + direntp
->d_name
).c_str (), &tmpstat
);
499 if (rc
|| !S_ISDIR(tmpstat
.st_mode
))
506 // We've got a directory. If the directory name isn't in the right
507 // format for a MOK fingerprint, skip it.
508 if ((regexec (&checkre
, direntp
->d_name
, (size_t) 0, NULL
, 0) != 0))
511 // OK, we've got a directory name in the right format, so save it.
512 temp
.push_back (string (direntp
->d_name
));
517 // At this point, we've got a list of directories with names in the
518 // proper format. Make sure each directory contains a x509
519 // certificate and private key file.
520 vector
<string
>::const_iterator it
;
521 for (it
= temp
.begin (); it
!= temp
.end (); it
++)
523 if (mok_dir_valid_p (*it
, true))
526 mok_fingerprints
.push_back (*it
);
528 server_error (_F("Found MOK with fingerprint '%s'", it
->c_str ()));
537 static AvahiEntryGroup
*avahi_group
= NULL
;
538 static AvahiThreadedPoll
*avahi_threaded_poll
= NULL
;
539 static char *avahi_service_name
= NULL
;
540 static const char * const avahi_service_tag
= "_stap._tcp";
541 static AvahiClient
*avahi_client
= 0;
542 static int avahi_collisions
= 0;
543 static int inotify_fd
= -1;
544 static AvahiWatch
*avahi_inotify_watch
= NULL
;
546 static void create_services (AvahiClient
*c
);
552 * Each service must have a unique name on the local network.
553 * When there is a collision, we try to rename the service.
554 * However, we need to limit the number of attempts, since the
555 * service namespace could be maliciously flooded with service
556 * names designed to maximize collisions.
557 * Arbitrarily choose a limit of 65535, which is the number of
561 if (avahi_collisions
>= 65535) {
562 server_error (_F("Too many service name collisions for Avahi service %s",
568 * Use the avahi-supplied function to generate a new service name.
570 char *n
= avahi_alternative_service_name(avahi_service_name
);
572 server_error (_F("Avahi service name collision, renaming service '%s' to '%s'",
573 avahi_service_name
, n
));
574 avahi_free(avahi_service_name
);
575 avahi_service_name
= n
;
581 entry_group_callback (
583 AvahiEntryGroupState state
,
584 AVAHI_GCC_UNUSED
void *userdata
586 assert(g
== avahi_group
|| avahi_group
== NULL
);
589 // Called whenever the entry group state changes.
592 case AVAHI_ENTRY_GROUP_ESTABLISHED
:
593 // The entry group has been established successfully.
594 log (_F("Avahi service '%s' successfully established.", avahi_service_name
));
597 case AVAHI_ENTRY_GROUP_COLLISION
:
598 // A service name collision with a remote service happened.
599 // Unfortunately, we don't know which entry collided.
600 // We need to rename them all and recreate the services.
601 if (rename_service () == 0)
602 create_services (avahi_entry_group_get_client (g
));
605 case AVAHI_ENTRY_GROUP_FAILURE
:
606 // Some kind of failure happened.
607 server_error (_F("Avahi entry group failure: %s",
608 avahi_strerror (avahi_client_errno (avahi_entry_group_get_client (g
)))));
611 case AVAHI_ENTRY_GROUP_UNCOMMITED
:
612 case AVAHI_ENTRY_GROUP_REGISTERING
:
618 create_services (AvahiClient
*c
)
622 // Create a new entry group, if necessary, or reset the existing one.
625 if (! (avahi_group
= avahi_entry_group_new (c
, entry_group_callback
, NULL
)))
627 server_error (_F("avahi_entry_group_new () failed: %s",
628 avahi_strerror (avahi_client_errno (c
))));
633 avahi_entry_group_reset(avahi_group
);
635 // Contruct the information needed for our service.
636 log (_F("Adding Avahi service '%s'", avahi_service_name
));
638 AvahiStringList
*strlst
= NULL
;
640 for (auto it
= kernel_build_tree
.cbegin(); it
!= kernel_build_tree
.cend(); ++it
)
642 // Create the txt tags that will be registered with our service.
643 string sysinfo
= "sysinfo=" + it
->first
+ " "+ arch
;
644 string certinfo
= "certinfo=" + cert_serial_number
;
645 string version
= string ("version=") + CURRENT_CS_PROTOCOL_VERSION
;;
646 string optinfo
= "optinfo=";
648 // These option strings already have a leading space.
649 if (! R_option
.empty ())
651 optinfo
+= R_option
.substr(1);
654 if (! B_options
.empty ())
656 optinfo
+= separator
+ B_options
.substr(1);
659 if (! D_options
.empty ())
661 optinfo
+= separator
+ D_options
.substr(1);
664 if (! I_options
.empty ())
665 optinfo
+= separator
+ I_options
.substr(1);
667 // Create an avahi string list with the info we have so far.
668 vector
<string
> mok_fingerprints
;
669 strlst
= avahi_string_list_new(sysinfo
.c_str (),
672 certinfo
.c_str (), NULL
);
675 server_error (_("Failed to allocate string list"));
679 // Add server MOK info, if available.
680 get_server_mok_fingerprints (mok_fingerprints
, true, false);
681 if (! mok_fingerprints
.empty())
683 for (auto it
= mok_fingerprints
.cbegin(); it
!= mok_fingerprints
.cend(); it
++)
685 string tmp
= "mok_info=" + *it
;
686 strlst
= avahi_string_list_add(strlst
, tmp
.c_str ());
689 server_error (_("Failed to add a string to the list"));
695 // We will now add our service to the entry group.
696 // Loop until no collisions.
698 ret
= avahi_entry_group_add_service_strlst (avahi_group
,
701 (AvahiPublishFlags
)0,
704 NULL
, NULL
, port
, strlst
);
708 if (ret
== AVAHI_ERR_COLLISION
)
710 // A service name collision with a local service happened.
712 if (rename_service () < 0) {
713 // Too many collisions. Message already issued.
716 continue; // try again.
719 server_error (_F("Failed to add %s service: %s",
720 avahi_service_tag
, avahi_strerror (ret
)));
724 avahi_string_list_free(strlst
);
728 // Tell the server to register the service.
729 if ((ret
= avahi_entry_group_commit (avahi_group
)) < 0)
731 server_error (_F("Failed to commit avahi entry group: %s", avahi_strerror (ret
)));
737 avahi_entry_group_reset (avahi_group
);
738 avahi_string_list_free(strlst
);
741 static void avahi_cleanup_client () {
742 // This also frees the entry group, if any
744 avahi_client_free (avahi_client
);
751 client_callback (AvahiClient
*c
, AvahiClientState state
, AVAHI_GCC_UNUSED
void * userdata
)
755 // Called whenever the client or server state changes.
758 case AVAHI_CLIENT_S_RUNNING
:
759 // The server has startup successfully and registered its host
760 // name on the network, so it's time to create our services.
764 case AVAHI_CLIENT_FAILURE
:
765 server_error (_F("Avahi client failure: %s", avahi_strerror (avahi_client_errno (c
))));
766 if (avahi_client_errno (c
) == AVAHI_ERR_DISCONNECTED
)
768 // The client has been disconnected; probably because the avahi daemon has been
769 // restarted. We can free the client here and try to reconnect using a new one.
770 // Passing AVAHI_CLIENT_NO_FAIL allows the new client to be
771 // created, even if the avahi daemon is not running. Our service will be advertised
772 // if/when the daemon is started.
773 avahi_cleanup_client ();
775 avahi_client
= avahi_client_new (avahi_threaded_poll_get (avahi_threaded_poll
),
776 (AvahiClientFlags
)AVAHI_CLIENT_NO_FAIL
,
777 client_callback
, NULL
, & error
);
781 case AVAHI_CLIENT_S_COLLISION
:
782 // Let's drop our registered services. When the server is back
783 // in AVAHI_SERVER_RUNNING state we will register them
784 // again with the new host name.
786 case AVAHI_CLIENT_S_REGISTERING
:
787 // The server records are now being established. This
788 // might be caused by a host name change. We need to wait
789 // for our own records to register until the host name is
790 // properly esatblished.
792 avahi_entry_group_reset (avahi_group
);
795 case AVAHI_CLIENT_CONNECTING
:
796 // The avahi-daemon is not currently running. Our service will be advertised
797 // if/when the deamon is started.
798 server_error (_F("The Avahi daemon is not running. Avahi service '%s' will be established when the deamon is started", avahi_service_name
));
804 inotify_callback (AvahiWatch
*, int fd
, AvahiWatchEvent
, void *)
806 struct inotify_event in_events
[10];
809 // Drain the inotify file. Notice we don't really care what changed,
810 // we just needed to know that something changed.
813 rc
= read (fd
, in_events
, sizeof (in_events
));
816 // Re-create the services.
817 if (avahi_client
&& (avahi_client_get_state (avahi_client
)
818 == AVAHI_CLIENT_S_RUNNING
))
819 create_services (avahi_client
);
825 if (avahi_service_name
)
826 log (_F("Removing Avahi service '%s'", avahi_service_name
));
828 // Stop the avahi client, if it's running
829 if (avahi_threaded_poll
)
830 avahi_threaded_poll_stop (avahi_threaded_poll
);
832 // Clean up the avahi objects. The order of freeing these is significant.
833 avahi_cleanup_client ();
834 if (avahi_inotify_watch
)
836 const AvahiPoll
*poll
= avahi_threaded_poll_get (avahi_threaded_poll
);
838 poll
->watch_free (avahi_inotify_watch
);
839 avahi_inotify_watch
= NULL
;
846 if (avahi_threaded_poll
) {
847 avahi_threaded_poll_free (avahi_threaded_poll
);
848 avahi_threaded_poll
= 0;
850 if (avahi_service_name
) {
851 avahi_free (avahi_service_name
);
852 avahi_service_name
= 0;
856 // The entry point for the avahi client thread.
858 avahi_publish_service (CERTCertificate
*cert
)
860 // Get the certificate serial number.
861 cert_serial_number
= get_cert_serial_number (cert
);
863 // Construct the Avahi service name.
864 char host
[HOST_NAME_MAX
+ 1];
865 gethostname (host
, sizeof(host
));
866 host
[sizeof(host
) - 1] = '\0';
868 buf
= string ("Systemtap Compile Server on ") + host
;
870 // Make sure the service name is valid
871 const char *initial_service_name
= buf
.c_str ();
872 if (! avahi_is_valid_service_name (initial_service_name
)) {
873 // The only restriction on service names is that the buffer must not exceed
874 // AVAHI_LABEL_MAX in size, which means that the name cannot be longer than
875 // AVAHI_LABEL_MAX-1 in length.
876 assert (strlen (initial_service_name
) >= AVAHI_LABEL_MAX
);
877 buf
= buf
.substr (0, AVAHI_LABEL_MAX
- 1);
878 initial_service_name
= buf
.c_str ();
879 assert (avahi_is_valid_service_name (initial_service_name
));
881 avahi_service_name
= avahi_strdup (initial_service_name
);
883 // Allocate main loop object.
884 if (! (avahi_threaded_poll
= avahi_threaded_poll_new ()))
886 server_error (_("Failed to create avahi threaded poll object."));
890 // Always allocate a new client. Passing AVAHI_CLIENT_NO_FAIL allows the client to be
891 // created, even if the avahi daemon is not running. Our service will be advertised
892 // if/when the daemon is started.
894 avahi_client
= avahi_client_new (avahi_threaded_poll_get (avahi_threaded_poll
),
895 (AvahiClientFlags
)AVAHI_CLIENT_NO_FAIL
,
896 client_callback
, NULL
, & error
);
897 // Check whether creating the client object succeeded.
900 server_error (_F("Failed to create avahi client: %s", avahi_strerror(error
)));
904 // Watch the server MOK directory for any changes.
905 #if defined(IN_CLOEXEC) && defined(IN_NONBLOCK)
906 inotify_fd
= inotify_init1 (IN_CLOEXEC
|IN_NONBLOCK
);
908 if ((inotify_fd
= inotify_init ()) >= 0)
910 fcntl(inotify_fd
, F_SETFD
, FD_CLOEXEC
);
911 fcntl(inotify_fd
, F_SETFL
, O_NONBLOCK
);
915 server_error (_F("Failed to initialize inotify: %s", strerror (errno
)));
918 // We want to watch for new or removed MOK directories
919 // underneath mok_path. But, to do that, mok_path must exist.
920 if (create_dir (mok_path
.c_str (), 0755) != 0)
921 server_error (_F("Unable to find or create the MOK directory %s: %s",
922 mok_path
.c_str (), strerror (errno
)));
923 // Watch mok_path for changes.
924 else if (inotify_add_watch (inotify_fd
, mok_path
.c_str (),
928 IN_CLOSE_WRITE
|IN_DELETE
|IN_DELETE_SELF
|IN_MOVE
)
930 server_error (_F("Failed to add inotify watch: %s", strerror (errno
)));
933 // When mok_path changes, call inotify_callback().
934 const AvahiPoll
*poll
= avahi_threaded_poll_get (avahi_threaded_poll
);
936 || ! (avahi_inotify_watch
= poll
->watch_new (poll
, inotify_fd
,
940 server_error (_("Failed to create inotify watcher"));
944 // Run the main loop.
945 avahi_threaded_poll_start (avahi_threaded_poll
);
952 advertise_presence (CERTCertificate
*cert
__attribute ((unused
)))
955 avahi_publish_service (cert
);
957 server_error (_("Unable to advertise presence on the network. Avahi is not available"));
962 unadvertise_presence ()
973 initialize (int argc
, char **argv
) {
974 pending_interrupts
= 0;
975 setup_signals (& handle_interrupt
);
977 // Seed the random number generator. Used to generate noise used during key generation.
981 use_db_password
= false;
983 max_threads
= thread::hardware_concurrency(); // Default to number of processors
984 max_uncompressed_req_size
= 50000; // 50 KB: default max uncompressed request size
985 max_compressed_req_size
= 5000; // 5 KB: default max compressed request size
987 struct utsname utsname
;
989 kernel_build_tree
.insert({utsname
.release
, "/lib/modules/" + string(utsname
.release
) + "/build"});
990 arch
= normalize_machine (utsname
.machine
);
992 // Parse the arguments. This also starts the server log, if any, and should be done before
993 // any messages are issued.
994 parse_options (argc
, argv
);
996 // PR11197: security prophylactics.
997 // Reject use as root, except via a special environment variable.
998 if (! getenv ("STAP_PR11197_OVERRIDE")) {
1000 fatal ("For security reasons, invocation of stap-serverd as root is not supported.");
1003 struct passwd
*pw
= getpwuid (geteuid ());
1005 fatal (_F("Unable to determine effective user name: %s", strerror (errno
)));
1006 string username
= pw
->pw_name
;
1007 pid_t pid
= getpid ();
1008 log (_F("===== compile server pid %d starting as %s =====", pid
, username
.c_str ()));
1010 // Where is the ssl certificate/key database?
1011 if (cert_db_path
.empty ())
1012 cert_db_path
= server_cert_db_path ();
1014 // Make sure NSPR is initialized. Must be done before NSS is initialized
1015 PR_Init (PR_SYSTEM_THREAD
, PR_PRIORITY_NORMAL
, 1);
1016 /* Set the cert database password callback. */
1017 PK11_SetPasswordFunc (nssPasswordCallback
);
1019 // Where are the optional machine owner keys (MOK) this server
1021 mok_path
= server_cert_db_path() + "/moks";
1027 unadvertise_presence ();
1031 /* Function: readDataFromSocket()
1033 * Purpose: Read data from the socket into a temporary file.
1037 readDataFromSocket(PRFileDesc
*sslSocket
, const char *requestFileName
)
1039 PRFileDesc
*local_file_fd
= 0;
1040 PRInt32 numBytesExpected
;
1041 PRInt32 numBytesRead
;
1042 PRInt32 numBytesWritten
;
1043 PRInt32 totalBytes
= 0;
1044 #define READ_BUFFER_SIZE 4096
1045 char buffer
[READ_BUFFER_SIZE
];
1047 // Read the number of bytes to be received.
1048 numBytesRead
= PR_Read_Complete (sslSocket
, & numBytesExpected
,
1049 (PRInt32
)sizeof (numBytesExpected
));
1050 if (numBytesRead
== 0) /* EOF */
1052 server_error (_("Error reading size of request file"));
1055 if (numBytesRead
< 0)
1057 server_error (_("Error in PR_Read"));
1062 /* Convert numBytesExpected from network byte order to host byte order. */
1063 numBytesExpected
= ntohl (numBytesExpected
);
1065 /* If 0 bytes are expected, then we were contacted only to obtain our certificate.
1066 There is no client request. */
1067 if (numBytesExpected
== 0)
1070 /* Impose a limit to prevent disk space consumption DoS */
1071 if (numBytesExpected
> (PRInt32
) max_compressed_req_size
)
1073 server_error (_("Error size of (compressed) request file is too large"));
1077 /* Open the output file. */
1078 local_file_fd
= PR_Open(requestFileName
, PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
,
1079 PR_IRUSR
| PR_IWUSR
);
1080 if (local_file_fd
== NULL
)
1082 server_error (_F("Could not open output file %s", requestFileName
));
1087 // Read until EOF or until the expected number of bytes has been read.
1088 for (totalBytes
= 0; totalBytes
< numBytesExpected
; totalBytes
+= numBytesRead
)
1090 // No need for PR_Read_Complete here, since we're already managing multiple
1091 // reads to a fixed size buffer.
1092 numBytesRead
= PR_Read (sslSocket
, buffer
, READ_BUFFER_SIZE
);
1093 if (numBytesRead
== 0)
1095 if (numBytesRead
< 0)
1097 server_error (_("Error in PR_Read"));
1102 /* Write to the request file. */
1103 numBytesWritten
= PR_Write(local_file_fd
, buffer
, numBytesRead
);
1104 if (numBytesWritten
< 0 || (numBytesWritten
!= numBytesRead
))
1106 server_error (_F("Could not write to output file %s", requestFileName
));
1112 if (totalBytes
!= numBytesExpected
)
1114 server_error (_F("Expected %d bytes, got %d while reading client request from socket",
1115 numBytesExpected
, totalBytes
));
1121 PR_Close (local_file_fd
);
1125 /* Function: setupSSLSocket()
1127 * Purpose: Configure a socket for SSL.
1128 * In case of failure, clean up the incoming tcpSocket and/or any partially setup sslSocket.
1132 setupSSLSocket (PRFileDesc
*tcpSocket
, CERTCertificate
*cert
, SECKEYPrivateKey
*privKey
)
1134 PRFileDesc
*sslSocket
;
1136 SECStatus secStatus
;
1138 /* Inport the socket into SSL. */
1139 sslSocket
= SSL_ImportFD (NULL
, tcpSocket
);
1140 if (sslSocket
== NULL
)
1142 server_error (_("Could not import socket into SSL"));
1146 /* Set the appropriate flags. */
1147 secStatus
= SSL_OptionSet (sslSocket
, SSL_SECURITY
, PR_TRUE
);
1148 if (secStatus
!= SECSuccess
)
1150 server_error (_("Error setting SSL security for socket"));
1154 secStatus
= SSL_OptionSet(sslSocket
, SSL_HANDSHAKE_AS_SERVER
, PR_TRUE
);
1155 if (secStatus
!= SECSuccess
)
1157 server_error (_("Error setting handshake as server for socket"));
1161 secStatus
= SSL_OptionSet(sslSocket
, SSL_REQUEST_CERTIFICATE
, PR_FALSE
);
1162 if (secStatus
!= SECSuccess
)
1164 server_error (_("Error setting SSL client authentication mode for socket"));
1168 secStatus
= SSL_OptionSet(sslSocket
, SSL_REQUIRE_CERTIFICATE
, PR_FALSE
);
1169 if (secStatus
!= SECSuccess
)
1171 server_error (_("Error setting SSL client authentication mode for socket"));
1175 /* Set the appropriate callback routines. */
1176 #if 0 /* use the default */
1177 secStatus
= SSL_AuthCertificateHook (sslSocket
, myAuthCertificate
, CERT_GetDefaultCertDB());
1178 if (secStatus
!= SECSuccess
)
1180 server_error (_("Error in SSL_AuthCertificateHook"));
1184 #if 0 /* Use the default */
1185 secStatus
= SSL_BadCertHook(sslSocket
, (SSLBadCertHandler
)myBadCertHandler
, &certErr
);
1186 if (secStatus
!= SECSuccess
)
1188 server_error (_("Error in SSL_BadCertHook"));
1192 #if 0 /* no handshake callback */
1193 secStatus
= SSL_HandshakeCallback(sslSocket
, myHandshakeCallback
, NULL
);
1194 if (secStatus
!= SECSuccess
)
1196 server_error (_("Error in SSL_HandshakeCallback"));
1201 certKEA
= NSS_FindCertKEAType (cert
);
1203 secStatus
= SSL_ConfigSecureServer (sslSocket
, cert
, privKey
, certKEA
);
1204 if (secStatus
!= SECSuccess
)
1206 server_error (_("Error configuring SSL server"));
1216 if (PR_Close (sslSocket
) != PR_SUCCESS
) {
1217 server_error (_("Error closing ssl socket"));
1221 if (PR_Close (tcpSocket
) != PR_SUCCESS
) {
1222 server_error (_("Error closing tcp/ssl socket"));
1230 #if 0 /* No client authentication (for now) and not authenticating after each transaction. */
1231 /* Function: authenticateSocket()
1233 * Purpose: Perform client authentication on the socket.
1237 authenticateSocket (PRFileDesc
*sslSocket
, PRBool requireCert
)
1239 CERTCertificate
*cert
;
1240 SECStatus secStatus
;
1242 /* Returns NULL if client authentication is not enabled or if the
1243 * client had no certificate. */
1244 cert
= SSL_PeerCertificate(sslSocket
);
1247 /* Client had a certificate, so authentication is through. */
1248 CERT_DestroyCertificate(cert
);
1252 /* Request client to authenticate itself. */
1253 secStatus
= SSL_OptionSet(sslSocket
, SSL_REQUEST_CERTIFICATE
, PR_TRUE
);
1254 if (secStatus
!= SECSuccess
)
1256 server_error (_("Error in SSL_OptionSet:SSL_REQUEST_CERTIFICATE"));
1261 /* If desired, require client to authenticate itself. Note
1262 * SSL_REQUEST_CERTIFICATE must also be on, as above. */
1263 secStatus
= SSL_OptionSet(sslSocket
, SSL_REQUIRE_CERTIFICATE
, requireCert
);
1264 if (secStatus
!= SECSuccess
)
1266 server_error (_("Error in SSL_OptionSet:SSL_REQUIRE_CERTIFICATE"));
1271 /* Having changed socket configuration parameters, redo handshake. */
1272 secStatus
= SSL_ReHandshake(sslSocket
, PR_TRUE
);
1273 if (secStatus
!= SECSuccess
)
1275 server_error (_("Error in SSL_ReHandshake"));
1280 /* Force the handshake to complete before moving on. */
1281 secStatus
= SSL_ForceHandshake(sslSocket
);
1282 if (secStatus
!= SECSuccess
)
1284 server_error (_("Error in SSL_ForceHandshake"));
1291 #endif /* No client authentication and not authenticating after each transaction. */
1293 /* Function: writeDataToSocket
1295 * Purpose: Write the server's response back to the socket.
1299 writeDataToSocket(PRFileDesc
*sslSocket
, const char *responseFileName
)
1301 PRFileDesc
*local_file_fd
= PR_Open (responseFileName
, PR_RDONLY
, 0);
1302 if (local_file_fd
== NULL
)
1304 server_error (_F("Could not open input file %s", responseFileName
));
1309 /* Transmit the local file across the socket.
1311 int numBytes
= PR_TransmitFile (sslSocket
, local_file_fd
,
1313 PR_TRANSMITFILE_KEEP_OPEN
,
1314 PR_INTERVAL_NO_TIMEOUT
);
1316 /* Error in transmission. */
1317 SECStatus secStatus
= SECSuccess
;
1320 server_error (_("Error writing response to socket"));
1322 secStatus
= SECFailure
;
1325 PR_Close (local_file_fd
);
1330 get_stap_locale (const string
&staplang
, vector
<string
> &envVec
, string stapstderr
, cs_protocol_version
*client_version
)
1332 // If the client version is < 1.6, then no file containing environment
1333 // variables defining the locale has been passed.
1334 if (*client_version
< "1.6")
1337 /* Go through each line of the file, verify it, then add it to the vector */
1339 langfile
.open(staplang
.c_str());
1340 if (!langfile
.is_open())
1342 // Not fatal. Proceed with the environment we have.
1343 server_error(_F("Unable to open file %s for reading: %s", staplang
.c_str(),
1348 /* Unpackage internationalization variables and verify their contents */
1349 map
<string
, string
> envMap
; /* To temporarily store the entire array of strings */
1351 const set
<string
> &locVars
= localization_variables();
1353 /* Copy the global environ variable into the map */
1356 for (unsigned i
=0; environ
[i
]; i
++)
1358 string line
= (string
)environ
[i
];
1360 /* Find the first '=' sign */
1361 size_t pos
= line
.find("=");
1363 /* Make sure it found an '=' sign */
1364 if(pos
!= string::npos
)
1365 /* Everything before the '=' sign is the key, and everything after is the value. */
1366 envMap
[line
.substr(0, pos
)] = line
.substr(pos
+1);
1370 /* Create regular expression objects to verify lines read from file. Should not allow
1371 spaces, ctrl characters, etc */
1373 if ((regcomp(&checkre
, "^[a-zA-Z0-9@_.=-]*$", REG_EXTENDED
| REG_NOSUB
) != 0))
1375 // Not fatal. Proceed with the environment we have.
1376 server_error(_F("Error in regcomp: %s", strerror (errno
)));
1382 getline(langfile
, line
);
1383 if (!langfile
.good())
1386 /* Extract key and value from the line. Note: value may contain "=". */
1390 pos
= line
.find("=");
1391 if (pos
== string::npos
)
1393 client_error(_F("Localization key=value line '%s' cannot be parsed", line
.c_str()), stapstderr
);
1396 key
= line
.substr(0, pos
);
1398 value
= line
.substr(pos
);
1400 /* Make sure the key is found in the localization variables global set */
1401 if (locVars
.find(key
) == locVars
.end())
1403 // Not fatal. Just ignore it.
1404 client_error(_F("Localization key '%s' not found in global list", key
.c_str()), stapstderr
);
1408 /* Make sure the value does not contain illegal characters */
1409 if ((regexec(&checkre
, value
.c_str(), (size_t) 0, NULL
, 0) != 0))
1411 // Not fatal. Just ignore it.
1412 client_error(_F("Localization value '%s' contains illegal characters", value
.c_str()), stapstderr
);
1416 /* All is good, copy line into envMap, replacing if already there */
1417 envMap
[key
] = value
;
1420 if (!langfile
.eof())
1422 // Not fatal. Proceed with what we have.
1423 server_error(_F("Error reading file %s: %s", staplang
.c_str(), strerror (errno
)));
1428 /* Copy map into vector */
1429 for (map
<string
, string
>::iterator it
= envMap
.begin(); it
!= envMap
.end(); it
++)
1430 envVec
.push_back(it
->first
+ "=" + it
->second
);
1434 get_client_mok_fingerprints (const string
&filename
,
1435 vector
<string
> &mok_fingerprints
,
1437 cs_protocol_version
*client_version
)
1439 // If the client version is < 1.6, then no file containing MOK
1440 // fingerprints could have been passed.
1441 if (*client_version
< "1.6") {
1445 // Go through each line of the file and add it to the vector.
1447 file
.open(filename
.c_str());
1448 if (! file
.is_open())
1449 // If the file isn't present, that's fine. It just means that the
1450 // module doesn't need to be signed.
1453 // Create a regular expression object to verify lines read from the
1456 if (regcomp(&checkre
, "^([0-9a-f]{2}(:[0-9a-f]{2})+)$", REG_EXTENDED
)
1459 // Not fatal, just ignore the MOK fingerprints.
1460 server_error(_F("Error in MOK fingerprint regcomp: %s",
1465 // Unpack the MOK fingerprints. Notice we make sure the fingerprint
1466 // is in the right format, but that's all we can do at this
1467 // point. Later we'll check this client list against our server
1470 regmatch_t matches
[3];
1471 while (getline (file
, line
))
1475 if ((regexec(&checkre
, line
.c_str(), 3, matches
, 0) != 0))
1477 // Not fatal. Just ignore it.
1478 client_error(_F("MOK fingerprint value '%s' isn't in the correct forma",
1479 line
.c_str()), stapstderr
);
1483 // Save the fingerprint:
1484 // matches[0] is the range of the entire match
1485 // matches[1] is the entire fingerprint
1486 // matches[2] is a portion of the fingerprint
1487 if (matches
[1].rm_so
>= 0)
1488 fingerprint
= line
.substr(matches
[1].rm_so
,
1489 matches
[1].rm_eo
- matches
[1].rm_so
);
1490 if (! fingerprint
.empty())
1491 mok_fingerprints
.push_back(fingerprint
);
1497 mok_sign_file (std::string
&mok_fingerprint
,
1498 const std::string
&kernel_build_tree
,
1499 const std::string
&name
,
1500 std::string stapstderr
)
1503 string mok_directory
= mok_path
+ "/" + mok_fingerprint
;
1507 kernel_build_tree
+ "/scripts/sign-file",
1509 mok_directory
+ MOK_PRIVATE_CERT_FILE
,
1510 mok_directory
+ MOK_PUBLIC_CERT_FILE
,
1514 rc
= stap_system (0, cmd
);
1517 client_error (_F("Running sign-file failed, rc = %d", rc
), stapstderr
);
1522 client_error (_F("Module signed with MOK, fingerprint \"%s\"",
1523 mok_fingerprint
.c_str()), stapstderr
);
1528 // Filter paths prefixed with the server's home directory from the given file.
1531 filter_response_file (const string
&file_name
, const string
&responseDirName
)
1533 // Filter the server's home directory name (unless it is "/")
1534 string dir
= get_home_directory();
1537 string swap
= string ("s,") + get_home_directory () + ",<server>,g";
1538 vector
<string
> cmd
{ "sed", "-i", swap
, file_name
};
1539 (void) stap_system (0, cmd
);
1542 // Filter the server's response directory name (unless it is "/")
1543 if (responseDirName
!= "/")
1545 string swap
= string ("s,") + responseDirName
+ ",<server>,g";
1546 vector
<string
> cmd
= { "sed", "-i", swap
, file_name
};
1547 (void) stap_system (0, cmd
);
1552 getRequestedPrivilege (const vector
<string
> &stapargv
)
1554 // The purpose of this function is to find the --privilege or --unprivileged option specified
1555 // by the user on the client side. We need to parse the command line completely, but we can
1556 // exit when we find the first --privilege or --unprivileged option, since stap does not allow
1557 // multiple privilege levels to specified on the same command line.
1559 // Note that we need not do any options consistency checking since our spawned stap instance
1562 // Create an argv/argc for use by getopt_long.
1563 int argc
= stapargv
.size();
1564 char ** argv
= new char *[argc
+ 1];
1565 for (unsigned i
= 0; i
< stapargv
.size(); ++i
)
1566 argv
[i
] = (char *)stapargv
[i
].c_str();
1569 privilege_t privilege
= pr_highest
; // Until specified otherwise.
1573 // We need only allow getopt to parse the options until we find a
1574 // --privilege or --unprivileged option.
1575 int grc
= getopt_long (argc
, argv
, STAP_SHORT_OPTIONS
, stap_long_options
, NULL
);
1581 // We can ignore all options other than --privilege and --unprivileged.
1583 case LONG_OPT_PRIVILEGE
:
1584 if (strcmp (optarg
, "stapdev") == 0)
1585 privilege
= pr_stapdev
;
1586 else if (strcmp (optarg
, "stapsys") == 0)
1587 privilege
= pr_stapsys
;
1588 else if (strcmp (optarg
, "stapusr") == 0)
1589 privilege
= pr_stapusr
;
1592 server_error (_F("Invalid argument '%s' for --privilege", optarg
));
1593 privilege
= pr_highest
;
1595 // We have discovered the client side --privilege option. We can exit now since
1596 // stap only tolerates one privilege setting option.
1597 goto done
; // break 2 switches and a loop
1598 case LONG_OPT_UNPRIVILEGED
:
1599 privilege
= pr_unprivileged
;
1600 // We have discovered the client side --unprivileged option. We can exit now since
1601 // stap only tolerates one privilege setting option.
1602 goto done
; // break 2 switches and a loop
1611 generate_mok(string
&mok_fingerprint
)
1615 char tmpdir
[PATH_MAX
] = { '\0' };
1616 string public_cert_path
, private_cert_path
, destdir
;
1620 mok_fingerprint
.clear ();
1622 // Set umask so that everything is private.
1623 old_umask
= umask(077);
1625 // Make sure the config file exists. If not, create it with default
1627 string config_path
= mok_path
+ MOK_CONFIG_FILE
;
1628 if (! file_exists (config_path
))
1630 ofstream config_stream
;
1631 config_stream
.open (config_path
.c_str ());
1632 if (! config_stream
.good ())
1634 server_error (_F("Could not open MOK config file %s: %s",
1635 config_path
.c_str (), strerror (errno
)));
1638 config_stream
<< MOK_CONFIG_TEXT
;
1639 config_stream
.close ();
1642 // Make a temporary directory to store results in.
1643 retlen
= snprintf (tmpdir
, PATH_MAX
, "%s/stap-server.XXXXXX", mok_path
.c_str ());
1644 if (retlen
< 0 || retlen
>= PATH_MAX
)
1646 server_error (_F("Could not create %s name", "temporary directory"));
1651 if (mkdtemp (tmpdir
) == NULL
)
1653 server_error (_F("Could not create temporary directory %s: %s", tmpdir
,
1659 // Actually generate key using openssl.
1660 public_cert_path
= tmpdir
+ string (MOK_PUBLIC_CERT_FILE
);
1661 private_cert_path
= tmpdir
+ string (MOK_PRIVATE_CERT_FILE
);
1665 "openssl", "req", "-new", "-nodes", "-utf8",
1666 "-sha256", "-days", "36500", "-batch", "-x509",
1667 "-config", config_path
,
1669 "-out", public_cert_path
,
1670 "-keyout", private_cert_path
1672 rc
= stap_system (0, cmd
);
1675 server_error (_F("Generating MOK failed, rc = %d", rc
));
1679 // Grab the fingerprint from the cert.
1680 if (read_cert_info_from_file (public_cert_path
, mok_fingerprint
)
1684 // Once we know the fingerprint, rename the temporary directory.
1685 destdir
= mok_path
+ "/" + mok_fingerprint
;
1686 if (rename (tmpdir
, destdir
.c_str ()) < 0)
1688 server_error (_F("Could not rename temporary directory %s to %s: %s",
1689 tmpdir
, destdir
.c_str (), strerror (errno
)));
1693 // Restore the old umask.
1699 // Remove the temporary directory.
1700 cmd
= { "rm", "-rf", tmpdir
};
1701 rc
= stap_system (0, cmd
);
1703 server_error (_("Error in tmpdir cleanup"));
1704 mok_fingerprint
.clear ();
1706 // Restore the old umask.
1711 /* Run the translator on the data in the request directory, and produce output
1712 in the given output directory. */
1714 handleRequest (const string
&requestDirName
, const string
&responseDirName
, string stapstderr
)
1716 vector
<string
> stapargv
;
1717 cs_protocol_version client_version
= "1.0"; // Assumed until discovered otherwise
1725 // Save the server version. Do this early, so the client knows what version of the server
1726 // it is dealing with, even if the request is not fully completed.
1727 string stapversion
= responseDirName
+ "/version";
1728 f
= fopen (stapversion
.c_str (), "w");
1731 fputs (CURRENT_CS_PROTOCOL_VERSION
, f
);
1735 server_error (_F("Unable to open client version file %s", stapversion
.c_str ()));
1737 // Get the client version. The default version is already set. Use it if we fail here.
1738 string filename
= requestDirName
+ "/version";
1739 if (file_exists (filename
))
1740 read_from_file (filename
, client_version
);
1741 log (_F("Client version is %s", client_version
.v
));
1743 // The name of the translator executable.
1744 stapargv
.push_back ((char *)(getenv ("SYSTEMTAP_STAP") ?: STAP_PREFIX
"/bin/stap"));
1746 // Fetch the target kernel version from request and pass flag to stap
1747 string kernel_version
;
1748 filename
= requestDirName
+ "/sysinfo";
1749 ifstream
versionfile(filename
.c_str());
1750 if (versionfile
>> kernel_version
>> kernel_version
) // Skip sysinfo: label
1752 if (kernel_build_tree
.find(kernel_version
) != kernel_build_tree
.end())
1754 stapargv
.push_back("-r" + kernel_version
);
1758 log(_F("Target kernel version %s is not supported by this server",
1759 kernel_version
.c_str()));
1765 server_error(_("Unable to read sysinfo"));
1769 /* Transcribe stap_options. We use plain wordexp(3), since these
1770 options are coming from the local trusted user, so malicious
1771 content is not a concern. */
1772 // TODO: Use tokenize here.
1773 rc
= wordexp (stap_options
.c_str (), & words
, WRDE_NOCMD
|WRDE_UNDEF
);
1776 server_error (_("Cannot parse stap options"));
1780 for (u
=0; u
<words
.we_wordc
; u
++)
1781 stapargv
.push_back (words
.we_wordv
[u
]);
1783 /* Process the saved command line arguments. Avoid quoting/unquoting errors by
1784 transcribing literally. */
1785 string new_staptmpdir
= responseDirName
+ "/stap000000";
1786 rc
= mkdir(new_staptmpdir
.c_str(), 0700);
1788 server_error(_F("Could not create temporary directory %s", new_staptmpdir
.c_str()));
1790 stapargv
.push_back("--tmpdir=" + new_staptmpdir
);
1792 stapargv
.push_back ("--client-options");
1794 string stap_opts
= "";
1797 char stapargfile
[PATH_MAX
];
1802 retlen
= snprintf (stapargfile
, PATH_MAX
, "%s/argv%d", requestDirName
.c_str (), i
);
1803 if (retlen
< 0 || retlen
>= PATH_MAX
)
1805 server_error (_F("Error creating %s name", "path"));
1809 rc
= stat(stapargfile
, & st
);
1812 arg
= (char *)malloc (st
.st_size
+1);
1815 server_error (_("Out of memory"));
1819 argfile
= fopen(stapargfile
, "r");
1823 server_error (_F("Error opening %s: %s", stapargfile
, strerror (errno
)));
1827 rc
= fread(arg
, 1, st
.st_size
, argfile
);
1828 if (rc
!= st
.st_size
)
1832 server_error (_F("Error reading %s: %s", stapargfile
, strerror (errno
)));
1836 arg
[st
.st_size
] = '\0';
1837 stapargv
.push_back (arg
);
1838 stap_opts
.append(arg
);
1839 stap_opts
.append(" ");
1843 log(_F("Options passed from the client: %s", stap_opts
.c_str()));
1845 string stapstdout
= responseDirName
+ "/stdout";
1847 // NB: Before, when we did not fully parse the client's command line using getopt_long,
1848 // we used to insert a --privilege=XXX option here in case some other argument was mistaken
1849 // for a --privilege or --unprivileged option by our spawned stap. Since we now parse
1850 // the client's command line using getopt_long and share the getopt_long options
1851 // string and table with stap, this is no longer necessary. stap will parse the
1852 // command line identically to the way we have parsed it and will discover the same
1853 // privilege-setting option.
1855 // Environment variables (possibly empty) to be passed to spawn_and_wait().
1856 string staplang
= requestDirName
+ "/locale";
1857 vector
<string
> envVec
;
1858 get_stap_locale (staplang
, envVec
, stapstderr
, &client_version
);
1860 // Machine owner keys (MOK) fingerprints (possibly nonexistent), to
1861 // be used as a list of valid keys that the module must be signed with.
1862 vector
<string
> client_mok_fingerprints
;
1863 get_client_mok_fingerprints(requestDirName
+ "/mok_fingerprints",
1864 client_mok_fingerprints
, stapstderr
,
1868 // If the client sent us MOK fingerprints, see if we have a matching
1869 // MOK on the server.
1870 string mok_fingerprint
;
1871 if (! client_mok_fingerprints
.empty())
1873 // See if any of the client MOK fingerprints exist on the server.
1874 vector
<string
>::const_iterator it
;
1875 for (it
= client_mok_fingerprints
.begin();
1876 it
!= client_mok_fingerprints
.end(); it
++)
1878 if (mok_dir_valid_p (*it
, false))
1880 mok_fingerprint
= *it
;
1885 // If the client requires signing, but we couldn't find a
1886 // matching machine owner key installed on the server, we can't
1887 // build a signed module. But, the client may not have asked us
1888 // to create a module (for instance, the user could have done
1889 // 'stap -L syscall.open'). So, keep going until we know we need
1890 // to sign a module.
1893 /* All ready, let's run the translator! */
1895 rc
= spawn_and_wait(stapargv
, &staprc
, "/dev/null", stapstdout
.c_str (),
1896 stapstderr
.c_str (), requestDirName
.c_str (), envVec
);
1897 if (rc
!= PR_SUCCESS
)
1899 server_error(_("Failed spawning translator"));
1903 // In unprivileged modes, if we have a module built, we need to sign
1904 // the sucker. We also might need to sign the module for secure
1906 privilege_t privilege
= getRequestedPrivilege (stapargv
);
1907 if (staprc
== 0 && (pr_contains (privilege
, pr_stapusr
)
1908 || pr_contains (privilege
, pr_stapsys
)
1909 || ! client_mok_fingerprints
.empty ()))
1912 char pattern
[PATH_MAX
];
1915 retlen
= snprintf (pattern
, PATH_MAX
, "%s/*.ko", new_staptmpdir
.c_str());
1916 if (retlen
< 0 || retlen
>= PATH_MAX
)
1918 server_error (_F("Error creating %s name", "pattern"));
1922 rc
= glob (pattern
, GLOB_ERR
, NULL
, &globber
);
1924 server_error (_F("Unable to find a module in %s", new_staptmpdir
.c_str()));
1925 else if (globber
.gl_pathc
!= 1)
1927 server_error (_F("Too many modules (%zu) in %s", globber
.gl_pathc
, new_staptmpdir
.c_str()));
1932 if (pr_contains (privilege
, pr_stapusr
)
1933 || pr_contains (privilege
, pr_stapsys
))
1934 sign_file (cert_db_path
, server_cert_nickname(),
1935 globber
.gl_pathv
[0],
1936 string(globber
.gl_pathv
[0]) + ".sgn");
1937 if (! mok_fingerprint
.empty ())
1939 // If we signing the module failed, change the staprc to
1940 // 1, so that the client won't try to run the resulting
1941 // module, which wouldn't work.
1942 if (! mok_sign_file (mok_fingerprint
, kernel_build_tree
[kernel_version
],
1943 globber
.gl_pathv
[0], stapstderr
))
1946 else if (! client_mok_fingerprints
.empty ())
1948 // If we're here, the client sent us MOK fingerprints
1949 // (since client_mok_fingerprints isn't empty), but we
1950 // don't have a matching MOK on the server (since
1951 // mok_fingerprint is empty). So, we can't sign the
1953 client_error (_("No matching machine owner key (MOK) available on the server to sign the\n module."), stapstderr
);
1955 // Since we can't sign the module, send the client one
1956 // of our MOKs. If we don't have any, create one.
1957 vector
<string
> mok_fingerprints
;
1958 get_server_mok_fingerprints(mok_fingerprints
, false, true);
1959 if (mok_fingerprints
.empty ())
1961 // Generate a new MOK.
1962 generate_mok(mok_fingerprint
);
1966 // At this point we have at least one MOK on the
1967 // server. Send the public key down to the
1969 mok_fingerprint
= *mok_fingerprints
.begin ();
1972 if (! mok_fingerprint
.empty ())
1974 // Copy the public cert file to the response directory.
1975 string mok_directory
= mok_path
+ "/" + mok_fingerprint
;
1976 string src
= mok_directory
+ MOK_PUBLIC_CERT_FILE
;
1977 string dst
= responseDirName
+ MOK_PUBLIC_CERT_FILE
;
1978 if (copy_file (src
, dst
, true))
1979 client_error ("The server has no machine owner key (MOK) in common with this\nsystem. Use the following command to import a server MOK into this\nsystem, then reboot:\n\n\tmokutil --import signing_key.x509", stapstderr
);
1981 client_error ("The server has no machine owner key (MOK) in common with this\nsystem. The server failed to return a certificate.", stapstderr
);
1985 client_error ("The server has no machine owner keys (MOK) in common with this\nsystem. The server could not generate a new MOK.", stapstderr
);
1988 // If we couldn't sign the module, let's change the
1989 // staprc to 1, so that the client won't try to run the
1990 // resulting module, which wouldn't work.
1997 // Save the RC (which might have gotten changed above).
1998 ofstream
ofs((responseDirName
+ "/rc").c_str());
2002 /* If uprobes.ko is required, it will have been built or cache-copied into
2003 * the temp directory. We need to pack it into the response where the client
2004 * can find it, and sign, if necessary, for unprivileged users.
2006 string uprobes_ko
= new_staptmpdir
+ "/uprobes/uprobes.ko";
2007 if (get_file_size(uprobes_ko
) > 0)
2009 /* uprobes.ko is required.
2011 * It's already underneath the stap tmpdir, but older stap clients
2012 * don't know to look for it there, so, for these clients, we end up packing uprobes twice
2013 * into the zip. We could move instead of symlink.
2015 string uprobes_response
;
2016 if (client_version
< "1.6")
2018 uprobes_response
= (string
)responseDirName
+ "/uprobes.ko";
2019 rc
= symlink(uprobes_ko
.c_str(), uprobes_response
.c_str());
2021 server_error (_F("Could not link to %s from %s",
2022 uprobes_ko
.c_str(), uprobes_response
.c_str()));
2025 uprobes_response
= uprobes_ko
;
2027 /* In unprivileged mode, we need a signature on uprobes as well. */
2028 if (! pr_contains (privilege
, pr_stapdev
))
2030 sign_file (cert_db_path
, server_cert_nickname(),
2031 uprobes_response
, uprobes_response
+ ".sgn");
2034 // Notice we're not giving an error message here if the client
2035 // requires signed modules. The error will have been generated
2036 // above on the systemtap module itself.
2037 if (! mok_fingerprint
.empty ())
2038 mok_sign_file (mok_fingerprint
, kernel_build_tree
[kernel_version
], uprobes_response
,
2042 /* Free up all the arg string copies. Note that the first few were alloc'd
2043 by wordexp(), which wordfree() frees; others were hand-set to literal strings. */
2046 // Filter paths prefixed with the server's home directory from the stdout and stderr
2047 // files in the response.
2048 filter_response_file (stapstdout
, responseDirName
);
2049 filter_response_file (stapstderr
, responseDirName
);
2051 /* Sorry about the inconvenience. C string/file processing is such a pleasure. */
2055 /* A front end for stap_spawn that handles stdin, stdout, stderr, switches to a working
2056 directory and returns overall success or failure. */
2058 spawn_and_wait (const vector
<string
> &argv
, int *spawnrc
,
2059 const char* fd0
, const char* fd1
, const char* fd2
,
2060 const char *pwd
, const vector
<string
>& envVec
)
2064 posix_spawn_file_actions_t actions
;
2067 #define CHECKRC(msg) do { if (rc) { server_error (_(msg)); return PR_FAILURE; } } while (0)
2069 rc
= posix_spawn_file_actions_init (& actions
);
2070 CHECKRC ("Error in spawn file actions ctor");
2072 rc
= posix_spawn_file_actions_addopen(& actions
, 0, fd0
, O_RDONLY
, 0600);
2073 CHECKRC ("Error in spawn file actions fd0");
2076 rc
= posix_spawn_file_actions_addopen(& actions
, 1, fd1
, O_WRONLY
|O_CREAT
, 0600);
2077 CHECKRC ("Error in spawn file actions fd1");
2080 // Use append mode for stderr because it gets written to in other places in the server.
2081 rc
= posix_spawn_file_actions_addopen(& actions
, 2, fd2
, O_WRONLY
|O_APPEND
|O_CREAT
, 0600);
2082 CHECKRC ("Error in spawn file actions fd2");
2085 /* change temporarily to a directory if requested */
2088 dotfd
= open (".", O_RDONLY
);
2091 server_error (_("Error in spawn getcwd"));
2099 server_error(_("Error in spawn chdir"));
2104 pid
= stap_spawn (0, argv
, & actions
, envVec
);
2105 /* NB: don't react to pid==-1 right away; need to chdir back first. */
2107 if (pwd
&& dotfd
>= 0)
2110 subrc
= fchdir (dotfd
);
2111 subrc
|= close (dotfd
);
2113 server_error (_("Error in spawn unchdir"));
2118 server_error (_F("Error in spawn: %s", strerror (errno
)));
2122 *spawnrc
= stap_waitpid (0, pid
);
2123 if (*spawnrc
== -1) // something wrong with waitpid() call itself
2125 server_error (_("Error in waitpid"));
2129 rc
= posix_spawn_file_actions_destroy (&actions
);
2130 CHECKRC ("Error in spawn file actions dtor");
2136 /* Given the path to the compressed request file, return 0 if the size of the
2137 * uncompressed request is within the determined limit. */
2139 check_uncompressed_request_size (const char * zip_file
)
2141 ostringstream result
;
2143 // Generate the command to heck the uncompressed size
2144 vector
<string
> args
{ "unzip", "-Zt", zip_file
};
2145 int rc
= stap_system_read (0, args
, result
);
2148 server_error (_F("Unable to check the zipefile size. Error code: %d .", rc
));
2152 // Parse the result from the unzip call, looking for the third token
2153 vector
<string
> toks
;
2154 tokenize(result
.str(), toks
, " ");
2155 if (toks
.size() < 3)
2157 // Something went wrong and the format is probably not what we expect.
2158 server_error("Unable to check the uncompressed zipfile size. Output came in an unexpected format.");
2162 long uncomp_size
= atol(toks
[2].c_str());
2163 if (uncomp_size
< 1 || (unsigned)uncomp_size
> max_uncompressed_req_size
)
2165 server_error(_F("Uncompressed request size of %ld bytes is not within the expected range of 1 to %zu bytes.",
2166 uncomp_size
,max_uncompressed_req_size
));
2170 return 0; // If it got to this point, everthing went well.
2173 /* Function: void *handle_connection()
2175 * Purpose: Handle a connection to a socket. Copy in request zip
2176 * file, process it, copy out response. Temporary directories are
2177 * created & destroyed here.
2181 handle_connection (void *arg
)
2183 PRFileDesc
* sslSocket
= NULL
;
2184 SECStatus secStatus
= SECFailure
;
2188 char tmpdir
[PATH_MAX
];
2189 char requestFileName
[PATH_MAX
];
2190 char requestDirName
[PATH_MAX
];
2191 char responseDirName
[PATH_MAX
];
2192 char responseFileName
[PATH_MAX
];
2193 string stapstderr
; /* Cannot be global since we need a unique
2194 copy for each connection.*/
2195 vector
<string
> argv
;
2199 /* Detatch to avoid a memory leak */
2201 pthread_detach(pthread_self());
2203 /* Unpack the arg */
2204 thread_arg
*t_arg
= (thread_arg
*) arg
;
2205 PRFileDesc
*tcpSocket
= t_arg
->tcpSocket
;
2206 CERTCertificate
*cert
= t_arg
->cert
;
2207 SECKEYPrivateKey
*privKey
= t_arg
->privKey
;
2208 PRNetAddr addr
= t_arg
->addr
;
2210 tmpdir
[0]='\0'; /* prevent cleanup-time /bin/rm of uninitialized directory */
2212 #if 0 // already done on the listenSocket
2213 /* Make sure the socket is blocking. */
2214 PRSocketOptionData socketOption
;
2215 socketOption
.option
= PR_SockOpt_Nonblocking
;
2216 socketOption
.value
.non_blocking
= PR_FALSE
;
2217 PR_SetSocketOption (tcpSocket
, &socketOption
);
2219 secStatus
= SECFailure
;
2220 sslSocket
= setupSSLSocket (tcpSocket
, cert
, privKey
);
2221 if (sslSocket
== NULL
)
2223 // Message already issued.
2227 secStatus
= SSL_ResetHandshake(sslSocket
, /* asServer */ PR_TRUE
);
2228 if (secStatus
!= SECSuccess
)
2230 server_error (_("Error resetting SSL handshake"));
2235 #if 0 // The client authenticates the server, so the client initiates the handshake
2236 /* Force the handshake to complete before moving on. */
2237 secStatus
= SSL_ForceHandshake(sslSocket
);
2238 if (secStatus
!= SECSuccess
)
2240 server_error (_("Error forcing SSL handshake"));
2246 secStatus
= SECFailure
;
2247 retlen
= snprintf(tmpdir
, PATH_MAX
, "%s/stap-server.XXXXXX", getenv("TMPDIR") ?: "/tmp");
2248 if (retlen
< 0 || retlen
>= PATH_MAX
)
2250 server_error (_F("Error creating %s name", "temporary directory"));
2251 tmpdir
[0]=0; /* prevent /bin/rm */
2254 rc1
= mkdtemp(tmpdir
);
2257 server_error (_F("Could not create temporary directory %s: %s", tmpdir
, strerror(errno
)));
2258 tmpdir
[0]=0; /* prevent /bin/rm */
2262 /* Create a temporary files names and directories. */
2263 retlen
= snprintf (requestFileName
, PATH_MAX
, "%s/request.zip", tmpdir
);
2264 if (retlen
< 0 || retlen
>= PATH_MAX
)
2266 server_error (_F("Error creating %s name", "request.zip path"));
2270 retlen
= snprintf (requestDirName
, PATH_MAX
, "%s/request", tmpdir
);
2271 if (retlen
< 0 || retlen
>= PATH_MAX
)
2273 server_error (_F("Error creating %s name", "request directory path"));
2277 rc
= mkdir(requestDirName
, 0700);
2280 server_error (_F("Could not create temporary directory %s: %s", requestDirName
, strerror (errno
)));
2284 retlen
= snprintf (responseDirName
, PATH_MAX
, "%s/response", tmpdir
);
2285 if (retlen
< 0 || retlen
>= PATH_MAX
)
2287 server_error (_F("Error creating %s name", "response directory path"));
2291 rc
= mkdir(responseDirName
, 0700);
2294 server_error (_F("Could not create temporary directory %s: %s", responseDirName
, strerror (errno
)));
2297 // Set this early, since it gets used for errors to be returned to the client.
2298 stapstderr
= string(responseDirName
) + "/stderr";
2300 retlen
= snprintf (responseFileName
, PATH_MAX
, "%s/response.zip", tmpdir
);
2301 if (retlen
< 0 || retlen
>= PATH_MAX
)
2303 server_error (_F("Error creating %s name", "response.zip path"));
2307 /* Read data from the socket.
2308 * If the user is requesting/requiring authentication, authenticate
2310 bytesRead
= readDataFromSocket(sslSocket
, requestFileName
);
2311 if (bytesRead
< 0) // Error
2313 if (bytesRead
== 0) // No request -- not an error
2315 secStatus
= SECSuccess
;
2319 #if 0 /* Don't authenticate after each transaction */
2320 if (REQUEST_CERT_ALL
)
2322 secStatus
= authenticateSocket(sslSocket
);
2323 if (secStatus
!= SECSuccess
)
2328 /* Just before we do any kind of processing, we want to check that the request there will
2329 * be enough memory to unzip the file. */
2330 if (check_uncompressed_request_size(requestFileName
))
2335 /* Unzip the request. */
2336 secStatus
= SECFailure
;
2337 argv
= { "unzip", "-q", "-d", requestDirName
, requestFileName
};
2338 rc
= stap_system (0, argv
);
2341 server_error (_("Unable to extract client request"));
2345 /* Handle the request zip file. An error therein should still result
2346 in a response zip file (containing stderr etc.) so we don't have to
2347 have a result code here. */
2348 handleRequest(requestDirName
, responseDirName
, stapstderr
);
2350 /* Zip the response. */
2352 argv
= { "zip", "-q", "-r", responseFileName
, "." };
2353 rc
= spawn_and_wait (argv
, &ziprc
, NULL
, NULL
, NULL
, responseDirName
);
2354 if (rc
!= PR_SUCCESS
|| ziprc
!= 0)
2356 server_error (_("Unable to compress server response"));
2360 secStatus
= writeDataToSocket (sslSocket
, responseFileName
);
2364 if (PR_Close (sslSocket
) != PR_SUCCESS
)
2366 server_error (_("Error closing ssl socket"));
2372 // Remove the whole tmpdir and all that lies beneath, unless -k was specified.
2374 log (_F("Keeping temporary directory %s", tmpdir
));
2377 argv
= { "rm", "-r", tmpdir
};
2378 rc
= stap_system (0, argv
);
2380 server_error (_("Error in tmpdir cleanup"));
2384 if (secStatus
!= SECSuccess
)
2385 server_error (_("Error processing client request"));
2387 // Log the end of the request.
2389 prStatus
= PR_NetAddrToString (& addr
, buf
, sizeof (buf
));
2390 if (prStatus
== PR_SUCCESS
)
2392 if (addr
.raw
.family
== PR_AF_INET
)
2393 log (_F("Request from %s:%d complete", buf
, addr
.inet
.port
));
2394 else if (addr
.raw
.family
== PR_AF_INET6
)
2395 log (_F("Request from [%s]:%d complete", buf
, addr
.ipv6
.port
));
2399 SECKEY_DestroyPrivateKey (privKey
); /* Destroy our copy of the private key. */
2401 /* Increment semephore to indicate this thread is finished. */
2403 if (max_threads
> 0)
2405 sem_post(&sem_client
);
2412 /* Function: int accept_connection()
2414 * Purpose: Accept a connection to the socket.
2418 accept_connections (PRFileDesc
*listenSocket
, CERTCertificate
*cert
)
2421 PRFileDesc
*tcpSocket
;
2423 SECStatus secStatus
;
2424 CERTCertDBHandle
*dbHandle
;
2429 dbHandle
= CERT_GetDefaultCertDB ();
2431 // cert_db_path gets passed to nssPasswordCallback.
2432 SECKEYPrivateKey
*privKey
= PK11_FindKeyByAnyCert (cert
, (void*)cert_db_path
.c_str ());
2433 if (privKey
== NULL
)
2435 server_error (_("Unable to obtain certificate private key"));
2440 while (pending_interrupts
== 0)
2442 /* Accept a connection to the socket. */
2443 tcpSocket
= PR_Accept (listenSocket
, &addr
, PR_INTERVAL_MIN
);
2444 if (tcpSocket
== NULL
)
2446 if(PR_GetError() == PR_IO_TIMEOUT_ERROR
)
2450 server_error (_("Error accepting client connection"));
2455 /* Log the accepted connection. */
2457 prStatus
= PR_NetAddrToString (&addr
, buf
, sizeof (buf
));
2458 if (prStatus
== PR_SUCCESS
)
2460 if (addr
.raw
.family
== PR_AF_INET
)
2461 log (_F("Accepted connection from %s:%d", buf
, addr
.inet
.port
));
2462 else if (addr
.raw
.family
== PR_AF_INET6
)
2463 log (_F("Accepted connection from [%s]:%d", buf
, addr
.ipv6
.port
));
2466 /* XXX: alarm() or somesuch to set a timeout. */
2468 /* Accepted the connection, now handle it. */
2470 /* Wait for a thread to finish if there are none available */
2474 sem_getvalue(&sem_client
, &idle_threads
);
2475 if(idle_threads
<= 0)
2476 log(_("Server is overloaded. Processing times may be longer than normal."));
2477 else if (idle_threads
== max_threads
)
2478 log(_("Processing 1 request..."));
2480 log(_F("Processing %d concurrent requests...", ((int)max_threads
- idle_threads
) + 1));
2482 sem_wait(&sem_client
);
2485 /* Create the argument structure to pass to pthread_create
2486 * (or directly to handle_connection if max_threads == 0 */
2487 t_arg
= (thread_arg
*)malloc(sizeof(*t_arg
));
2489 fatal(_("No memory available for new thread arg!"));
2490 t_arg
->tcpSocket
= tcpSocket
;
2492 t_arg
->privKey
= SECKEY_CopyPrivateKey(privKey
); /* pass by value */
2495 /* Handle the conncection */
2497 if (max_threads
> 0)
2498 /* Create the worker thread and handle the connection. */
2499 thread_rc
= pthread_create(&tid
, NULL
, handle_connection
, t_arg
);
2502 /* Since max_threads == 0, don't spawn a new thread,
2503 * just handle in the current thread. */
2504 handle_connection(t_arg
);
2506 // If our certificate is no longer valid (e.g. has expired), then exit.
2507 secStatus
= CERT_VerifyCertNow (dbHandle
, cert
, PR_TRUE
/*checkSig*/,
2508 certUsageSSLServer
, NULL
/*wincx*/);
2509 if (secStatus
!= SECSuccess
)
2511 // Not a serious error. Exit the loop so a new cert can be generated.
2517 SECKEY_DestroyPrivateKey (privKey
); /* Safe to destroy, even if thread still running. */
2521 /* Function: void server_main()
2523 * Purpose: This is the server's main function. It configures a socket
2524 * and listens to it.
2528 server_main (PRFileDesc
*listenSocket
)
2532 NSSInitContext
*context
;
2533 SECStatus secStatus
;
2536 context
= nssInitContext (cert_db_path
.c_str ());
2537 if (context
== NULL
)
2539 // Message already issued.
2543 // Preinitialized here due to jumps to the label 'done'.
2544 CERTCertificate
*cert
= NULL
;
2545 bool serverCacheConfigured
= false;
2547 // Enable all cipher suites.
2548 // NB: The NSS docs say that SSL_ClearSessionCache is required for the new settings to take
2549 // effect, however, calling it puts NSS in a state where it will not shut down cleanly.
2550 // We need to be able to shut down NSS cleanly if we are to generate a new certificate when
2551 // ours expires. It should be noted however, thet SSL_ClearSessionCache only clears the
2552 // client cache, and we are a server.
2553 /* Some NSS versions don't do this correctly in NSS_SetDomesticPolicy. */
2555 const PRUint16
*cipher
;
2556 for (cipher
= SSL_GetImplementedCiphers(); *cipher
!= 0; ++cipher
)
2557 SSL_CipherPolicySet(*cipher
, SSL_ALLOWED
);
2559 // SSL_ClearSessionCache ();
2561 // Configure the SSL session cache for a single process server with the default settings.
2562 secStatus
= SSL_ConfigServerSessionIDCache (0, 0, 0, NULL
);
2563 if (secStatus
!= SECSuccess
)
2565 server_error (_("Unable to configure SSL server session ID cache"));
2569 serverCacheConfigured
= true;
2571 /* Get own certificate. */
2572 cert
= PK11_FindCertFromNickname (server_cert_nickname (), NULL
);
2575 server_error (_F("Unable to find our certificate in the database at %s",
2576 cert_db_path
.c_str ()));
2581 // Tell the world that we're listening.
2582 advertise_presence (cert
);
2584 /* Handle connections to the socket. */
2585 secStatus
= accept_connections (listenSocket
, cert
);
2587 // Tell the world we're no longer listening.
2588 unadvertise_presence ();
2590 sem_getvalue(&sem_client
, &idle_threads
);
2592 /* Wait for requests to finish or the timeout to be reached.
2593 * If we got here from an interrupt, exit immediately if
2594 * the timeout is reached. Otherwise, wait indefinitiely
2595 * until the threads exit (or an interrupt is recieved).*/
2596 if(idle_threads
< max_threads
)
2597 log(_F("Waiting for %d outstanding requests to complete...", (int)max_threads
- idle_threads
));
2598 while(idle_threads
< max_threads
)
2600 if(pending_interrupts
&& timeout
++ > CONCURRENCY_TIMEOUT_S
)
2602 log(_("Timeout reached, exiting (forced)"));
2603 kill_stap_spawn (SIGTERM
);
2608 sem_getvalue(&sem_client
, &idle_threads
);
2614 CERT_DestroyCertificate (cert
);
2617 if (serverCacheConfigured
&& SSL_ShutdownServerSessionIDCache () != SECSuccess
)
2619 server_error (_("Unable to shut down server session ID cache"));
2622 nssCleanup (cert_db_path
.c_str (), context
);
2630 // Create a new socket.
2631 PRFileDesc
*listenSocket
= PR_OpenTCPSocket (PR_AF_INET6
); // Accepts IPv4 too
2632 if (listenSocket
== NULL
)
2634 server_error (_("Error creating socket"));
2639 // Set socket to be blocking - on some platforms the default is nonblocking.
2640 PRSocketOptionData socketOption
;
2641 socketOption
.option
= PR_SockOpt_Nonblocking
;
2642 socketOption
.value
.non_blocking
= PR_FALSE
;
2643 PRStatus prStatus
= PR_SetSocketOption (listenSocket
, & socketOption
);
2644 if (prStatus
!= PR_SUCCESS
)
2646 server_error (_("Error setting socket properties"));
2651 // Allow the socket address to be reused, in case we want the same port across a
2652 // 'service stap-server restart'
2653 socketOption
.option
= PR_SockOpt_Reuseaddr
;
2654 socketOption
.value
.reuse_addr
= PR_TRUE
;
2655 prStatus
= PR_SetSocketOption (listenSocket
, & socketOption
);
2656 if (prStatus
!= PR_SUCCESS
)
2658 server_error (_("Error setting socket properties"));
2663 // Configure the network connection.
2665 memset (& addr
, 0, sizeof(addr
));
2666 prStatus
= PR_InitializeNetAddr (PR_IpAddrAny
, port
, & addr
);
2667 addr
.ipv6
.family
= PR_AF_INET6
;
2669 // addr.inet.ip = PR_htonl(PR_INADDR_ANY);
2670 PR_StringToNetAddr ("::", & addr
);
2671 // PR_StringToNetAddr ("fe80::5eff:35ff:fe07:55ca", & addr);
2672 // PR_StringToNetAddr ("::1", & addr);
2673 addr
.ipv6
.port
= PR_htons (port
);
2676 // Bind the socket to an address. Retry if the selected port is busy, unless the port was
2677 // specified directly.
2680 /* Bind the address to the listener socket. */
2681 prStatus
= PR_Bind (listenSocket
, & addr
);
2682 if (prStatus
== PR_SUCCESS
)
2685 // If the selected port is busy. Try another, but only if a specific port was not specified.
2686 PRErrorCode errorNumber
= PR_GetError ();
2687 switch (errorNumber
)
2689 case PR_ADDRESS_NOT_AVAILABLE_ERROR
:
2692 server_error (_F("Network port %hu is unavailable. Trying another port", port
));
2696 case PR_ADDRESS_IN_USE_ERROR
:
2699 server_error (_F("Network port %hu is busy. Trying another port", port
));
2706 server_error (_("Error setting socket address"));
2711 // Query the socket for the port that was assigned.
2712 prStatus
= PR_GetSockName (listenSocket
, &addr
);
2713 if (prStatus
!= PR_SUCCESS
)
2715 server_error (_("Unable to obtain socket address"));
2720 prStatus
= PR_NetAddrToString (&addr
, buf
, sizeof (buf
));
2721 port
= PR_ntohs (addr
.ipv6
.port
);
2722 log (_F("Using network address [%s]:%hu", buf
, port
));
2724 if (max_threads
> 0)
2725 log (_F("Using a maximum of %ld threads", max_threads
));
2727 log (_("Concurrency disabled"));
2729 // Listen for connection on the socket. The second argument is the maximum size of the queue
2730 // for pending connections.
2731 prStatus
= PR_Listen (listenSocket
, 5);
2732 if (prStatus
!= PR_SUCCESS
)
2734 server_error (_("Error listening on socket"));
2739 /* Initialize semephore with the maximum number of threads
2740 * defined by --max-threads. If it is not defined, the
2741 * default is the number of processors */
2742 sem_init(&sem_client
, 0, max_threads
);
2744 // Loop forever. We check our certificate (and regenerate, if necessary) and then start the
2745 // server. The server will go down when our certificate is no longer valid (e.g. expired). We
2746 // then generate a new one and start the server again.
2747 while(!pending_interrupts
)
2749 // Ensure that our certificate is valid. Generate a new one if not.
2750 if (check_cert (cert_db_path
, server_cert_nickname (), use_db_password
) != 0)
2752 // Message already issued
2753 server_error (_("Cannot check/create certificate, giving up."));
2757 // Ensure that our certificate is trusted by our local client.
2758 // Construct the client database path relative to the server database path.
2759 SECStatus secStatus
= add_client_cert (server_cert_file (),
2760 local_client_cert_db_path (), db_nssinit
);
2761 if (secStatus
!= SECSuccess
)
2763 // Not fatal. Other clients may trust the server and trust can be added
2764 // for the local client in other ways.
2765 server_error (_("Unable to authorize certificate for the local client"));
2768 // Launch the server.
2769 secStatus
= server_main (listenSocket
);
2773 sem_destroy(&sem_client
); /*Not really necessary, as we are shutting down...but for correctness */
2774 if (PR_Close (listenSocket
) != PR_SUCCESS
)
2776 server_error (_("Error closing listen socket"));
2782 main (int argc
, char **argv
) {
2783 initialize (argc
, argv
);
2789 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */