2 Compile server client functions
3 Copyright (C) 2010-2011 Red Hat Inc.
5 This file is part of systemtap, and is free software. You can
6 redistribute it and/or modify it under the terms of the GNU General
7 Public License (GPL); either version 2, or (at your option) any
15 #include "stap-probe.h"
17 #include <sys/times.h>
27 #include <linux/limits.h>
31 #include <sys/socket.h>
34 #include <arpa/inet.h>
40 #include <avahi-client/client.h>
41 #include <avahi-client/lookup.h>
43 #include <avahi-common/simple-watch.h>
44 #include <avahi-common/malloc.h>
45 #include <avahi-common/error.h>
46 #include <avahi-common/timeval.h>
62 #include "nsscommon.h"
67 #define STAP_CSC_01 _("WARNING: The domain name, %s, does not match the DNS name(s) on the server certificate:\n")
68 #define STAP_CSC_02 _("could not find input file %s\n")
69 #define STAP_CSC_03 _("could not open input file %s\n")
70 #define STAP_CSC_04 _("Unable to open output file %s\n")
71 #define STAP_CSC_05 _("could not write to %s\n")
75 nsscommon_error (const char *msg
, int logit
__attribute ((unused
)))
77 clog
<< msg
<< endl
<< flush
;
80 // Information about compile servers.
81 struct compile_server_info
83 compile_server_info () : port (0) {}
94 return host_name
.empty () && ip_address
.empty ();
97 bool operator== (const compile_server_info
&that
) const
99 // If the ip address is not set, then the host names must match, otherwise
100 // the ip addresses must match.
101 if (this->ip_address
.empty () || that
.ip_address
.empty ())
103 if (this->host_name
!= that
.host_name
)
106 else if (this->ip_address
!= that
.ip_address
)
109 // Compare the other fields only if they have both been set.
110 if (this->port
!= 0 && that
.port
!= 0 && this->port
!= that
.port
)
112 if (! this->version
.empty () && ! that
.version
.empty () &&
113 this->version
!= that
.version
)
115 if (! this->sysinfo
.empty () && ! that
.sysinfo
.empty () &&
116 this->sysinfo
!= that
.sysinfo
)
118 if (! this->certinfo
.empty () && ! that
.certinfo
.empty () &&
119 this->certinfo
!= that
.certinfo
)
124 // Used to sort servers by preference for order of contact. The preferred server is
125 // "less" than the other one.
126 bool operator< (const compile_server_info
&that
) const
128 // Prefer servers with a later (higher) version number.
129 cs_protocol_version
this_version (this->version
.c_str ());
130 cs_protocol_version
that_version (that
.version
.c_str ());
131 return that_version
< this_version
;
135 ostream
&operator<< (ostream
&s
, const compile_server_info
&i
);
138 preferred_order (vector
<compile_server_info
> &servers
)
140 // Sort the given list of servers into the preferred order for contacting.
141 // Don't bother if there are less than 2 servers in the list.
142 if (servers
.size () < 2)
145 // Sort the list using compile_server_info::operator<
146 sort (servers
.begin (), servers
.end ());
149 struct compile_server_cache
151 vector
<compile_server_info
> default_servers
;
152 vector
<compile_server_info
> specified_servers
;
153 vector
<compile_server_info
> trusted_servers
;
154 vector
<compile_server_info
> signing_servers
;
155 vector
<compile_server_info
> online_servers
;
158 // For filtering queries.
159 enum compile_server_properties
{
160 compile_server_all
= 0x1,
161 compile_server_trusted
= 0x2,
162 compile_server_online
= 0x4,
163 compile_server_compatible
= 0x8,
164 compile_server_signer
= 0x10,
165 compile_server_specified
= 0x20
169 static compile_server_cache
* cscache(systemtap_session
& s
);
170 static void query_server_status (systemtap_session
&s
, const string
&status_string
);
172 static void get_server_info (systemtap_session
&s
, int pmask
, vector
<compile_server_info
> &servers
);
173 static void get_all_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
);
174 static void get_default_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
);
175 static void get_specified_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool no_default
= false);
176 static void get_or_keep_online_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
177 static void get_or_keep_trusted_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
178 static void get_or_keep_signing_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
179 static void get_or_keep_compatible_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
180 static void keep_common_server_info (const compile_server_info
&info_to_keep
, vector
<compile_server_info
> &filtered_info
);
181 static void keep_common_server_info (const vector
<compile_server_info
> &info_to_keep
, vector
<compile_server_info
> &filtered_info
);
182 static void keep_server_info_with_cert_and_port (systemtap_session
&s
, const compile_server_info
&server
, vector
<compile_server_info
> &servers
);
184 static void add_server_info (const compile_server_info
&info
, vector
<compile_server_info
>& list
);
185 static void add_server_info (const vector
<compile_server_info
> &source
, vector
<compile_server_info
> &target
);
186 static void merge_server_info (const compile_server_info
&source
, compile_server_info
&target
);
187 #if 0 // not used right now
188 static void merge_server_info (const compile_server_info
&source
, vector
<compile_server_info
> &target
);
189 static void merge_server_info (const vector
<compile_server_info
> &source
, vector
<compile_server_info
> &target
);
191 static void resolve_host (systemtap_session
& s
, compile_server_info
&server
, vector
<compile_server_info
> &servers
);
193 /* Exit error codes */
195 #define GENERAL_ERROR 1
196 #define CA_CERT_INVALID_ERROR 2
197 #define SERVER_CERT_EXPIRED_ERROR 3
199 // Convert the given string to an ip address in host byte order.
201 stringToIpAddress (const string
&s
)
206 vector
<string
>components
;
207 tokenize (s
, components
, ".");
208 assert (components
.size () >= 1);
212 for (i
= 0; i
< components
.size (); ++i
)
214 const char *ipstr
= components
[i
].c_str ();
217 unsigned a
= strtoul (ipstr
, & estr
, 10);
218 if (errno
== 0 && *estr
== '\0' && a
<= UCHAR_MAX
)
228 // -----------------------------------------------------
229 // NSS related code used by the compile server client
230 // -----------------------------------------------------
231 static void add_server_trust (systemtap_session
&s
, const string
&cert_db_path
, const vector
<compile_server_info
> &server_list
);
232 static void revoke_server_trust (systemtap_session
&s
, const string
&cert_db_path
, const vector
<compile_server_info
> &server_list
);
233 static void get_server_info_from_db (systemtap_session
&s
, vector
<compile_server_info
> &servers
, const string
&cert_db_path
);
235 static string
global_client_cert_db_path () {
236 return SYSCONFDIR
"/systemtap/ssl/client";
240 private_ssl_cert_db_path ()
242 return local_client_cert_db_path ();
246 global_ssl_cert_db_path ()
248 return global_client_cert_db_path ();
252 signing_cert_db_path ()
254 return SYSCONFDIR
"/systemtap/staprun";
257 /* Connection state. */
258 typedef struct connectionState_t
260 const char *hostName
;
263 const char *infileName
;
264 const char *outfileName
;
265 const char *trustNewServerMode
;
268 #if 0 /* No client authorization */
270 myPasswd(PK11SlotInfo
*info
, PRBool retry
, void *arg
)
272 char * passwd
= NULL
;
274 if ( (!retry
) && arg
)
275 passwd
= PORT_Strdup((char *)arg
);
281 /* Add the server's certificate to our database of trusted servers. */
283 trustNewServer (CERTCertificate
*serverCert
)
286 CERTCertTrust
*trust
= NULL
;
287 PK11SlotInfo
*slot
= NULL
;
289 /* Import the certificate. */
290 slot
= PK11_GetInternalKeySlot();
291 const char *nickname
= server_cert_nickname ();
292 secStatus
= PK11_ImportCert(slot
, serverCert
, CK_INVALID_HANDLE
, nickname
, PR_FALSE
);
293 if (secStatus
!= SECSuccess
)
296 /* Make it a trusted peer. */
297 trust
= (CERTCertTrust
*)PORT_ZAlloc(sizeof(CERTCertTrust
));
300 secStatus
= SECFailure
;
304 secStatus
= CERT_DecodeTrustString(trust
, "P,P,P");
305 if (secStatus
!= SECSuccess
)
308 secStatus
= CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), serverCert
, trust
);
312 PK11_FreeSlot (slot
);
318 /* Called when the server certificate verification fails. This gives us
319 the chance to trust the server anyway and add the certificate to the
322 badCertHandler(void *arg
, PRFileDesc
*sslSocket
)
325 PRErrorCode errorNumber
;
326 CERTCertificate
*serverCert
= NULL
;
328 PRArenaPool
*tmpArena
= NULL
;
329 CERTGeneralName
*nameList
, *current
;
330 char *expected
= NULL
;
331 const connectionState_t
*connectionState
= (connectionState_t
*)arg
;
333 errorNumber
= PR_GetError ();
336 case SSL_ERROR_BAD_CERT_DOMAIN
:
337 /* Since we administer our own client-side databases of trustworthy
338 certificates, we don't need the domain name(s) on the certificate to
339 match. If the cert is in our database, then we can trust it.
340 Issue a warning and accept the certificate. */
341 expected
= SSL_RevealURL (sslSocket
);
342 fprintf (stderr
, STAP_CSC_01
, expected
);
344 /* List the DNS names from the server cert as part of the warning.
345 First, find the alt-name extension on the certificate. */
346 subAltName
.data
= NULL
;
347 serverCert
= SSL_PeerCertificate (sslSocket
);
348 secStatus
= CERT_FindCertExtension (serverCert
,
349 SEC_OID_X509_SUBJECT_ALT_NAME
,
351 if (secStatus
!= SECSuccess
|| ! subAltName
.data
)
353 fprintf (stderr
, _("Unable to find alt name extension on the server certificate\n"));
354 secStatus
= SECSuccess
; /* Not a fatal error */
358 // Now, decode the extension.
359 tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
362 fprintf (stderr
, _("Out of memory\n"));
363 secStatus
= SECSuccess
; /* Not a fatal error here */
366 nameList
= CERT_DecodeAltNameExtension (tmpArena
, & subAltName
);
367 SECITEM_FreeItem(& subAltName
, PR_FALSE
);
370 fprintf (stderr
, _("Unable to decode alt name extension on server certificate\n"));
371 secStatus
= SECSuccess
; /* Not a fatal error */
375 /* List the DNS names from the server cert as part of the warning.
376 The names are in a circular list. */
380 /* Make sure this is a DNS name. */
381 if (current
->type
== certDNSName
)
383 fprintf (stderr
, " %.*s\n",
384 (int)current
->name
.other
.len
, current
->name
.other
.data
);
386 current
= CERT_GetNextGeneralName (current
);
388 while (current
!= nameList
);
390 /* Accept the certificate */
391 secStatus
= SECSuccess
;
394 case SEC_ERROR_CA_CERT_INVALID
:
395 /* The server's certificate is not trusted. Should we trust it? */
396 secStatus
= SECFailure
; /* Do not trust by default. */
397 if (! connectionState
->trustNewServerMode
)
400 /* Trust it for this session only? */
401 if (strcmp (connectionState
->trustNewServerMode
, "session") == 0)
403 secStatus
= SECSuccess
;
407 /* Trust it permanently? */
408 if (strcmp (connectionState
->trustNewServerMode
, "permanent") == 0)
410 /* The user wants to trust this server. Get the server's certificate so
411 and add it to our database. */
412 serverCert
= SSL_PeerCertificate (sslSocket
);
413 if (serverCert
!= NULL
)
415 secStatus
= trustNewServer (serverCert
);
420 secStatus
= SECFailure
; /* Do not trust this server */
425 PORT_Free (expected
);
427 PORT_FreeArena (tmpArena
, PR_FALSE
);
429 if (serverCert
!= NULL
)
431 CERT_DestroyCertificate (serverCert
);
438 setupSSLSocket (connectionState_t
*connectionState
)
440 PRFileDesc
*tcpSocket
;
441 PRFileDesc
*sslSocket
;
442 PRSocketOptionData socketOption
;
446 tcpSocket
= PR_NewTCPSocket();
447 if (tcpSocket
== NULL
)
450 /* Make the socket blocking. */
451 socketOption
.option
= PR_SockOpt_Nonblocking
;
452 socketOption
.value
.non_blocking
= PR_FALSE
;
454 prStatus
= PR_SetSocketOption(tcpSocket
, &socketOption
);
455 if (prStatus
!= PR_SUCCESS
)
458 /* Import the socket into the SSL layer. */
459 sslSocket
= SSL_ImportFD(NULL
, tcpSocket
);
463 /* Set configuration options. */
464 secStatus
= SSL_OptionSet(sslSocket
, SSL_SECURITY
, PR_TRUE
);
465 if (secStatus
!= SECSuccess
)
468 secStatus
= SSL_OptionSet(sslSocket
, SSL_HANDSHAKE_AS_CLIENT
, PR_TRUE
);
469 if (secStatus
!= SECSuccess
)
472 /* Set SSL callback routines. */
473 #if 0 /* no client authentication */
474 secStatus
= SSL_GetClientAuthDataHook(sslSocket
,
475 (SSLGetClientAuthData
)myGetClientAuthData
,
476 (void *)certNickname
);
477 if (secStatus
!= SECSuccess
)
480 #if 0 /* Use the default */
481 secStatus
= SSL_AuthCertificateHook(sslSocket
,
482 (SSLAuthCertificate
)myAuthCertificate
,
483 (void *)CERT_GetDefaultCertDB());
484 if (secStatus
!= SECSuccess
)
488 secStatus
= SSL_BadCertHook(sslSocket
, (SSLBadCertHandler
)badCertHandler
,
490 if (secStatus
!= SECSuccess
)
493 #if 0 /* No handshake callback */
494 secStatus
= SSL_HandshakeCallback(sslSocket
, myHandshakeCallback
, NULL
);
495 if (secStatus
!= SECSuccess
)
509 handle_connection (PRFileDesc
*sslSocket
, connectionState_t
*connectionState
)
514 PRFileDesc
*local_file_fd
;
516 SECStatus secStatus
= SECSuccess
;
518 #define READ_BUFFER_SIZE (60 * 1024)
520 /* If we don't have both the input and output file names, then we're
521 contacting this server only in order to establish trust. In this case send
522 0 as the file size and exit. */
523 if (! connectionState
->infileName
|| ! connectionState
->outfileName
)
525 numBytes
= htonl ((PRInt32
)0);
526 numBytes
= PR_Write (sslSocket
, & numBytes
, sizeof (numBytes
));
532 /* read and send the data. */
533 /* Try to open the local file named.
534 * If successful, then write it to the server
536 prStatus
= PR_GetFileInfo(connectionState
->infileName
, &info
);
537 if (prStatus
!= PR_SUCCESS
||
538 info
.type
!= PR_FILE_FILE
||
541 fprintf (stderr
, STAP_CSC_02
,
542 connectionState
->infileName
);
546 local_file_fd
= PR_Open(connectionState
->infileName
, PR_RDONLY
, 0);
547 if (local_file_fd
== NULL
)
549 fprintf (stderr
, STAP_CSC_03
, connectionState
->infileName
);
553 /* Send the file size first, so the server knows when it has the entire file. */
554 numBytes
= htonl ((PRInt32
)info
.size
);
555 numBytes
= PR_Write(sslSocket
, & numBytes
, sizeof (numBytes
));
558 PR_Close(local_file_fd
);
562 /* Transmit the local file across the socket. */
563 numBytes
= PR_TransmitFile(sslSocket
, local_file_fd
,
565 PR_TRANSMITFILE_KEEP_OPEN
,
566 PR_INTERVAL_NO_TIMEOUT
);
569 PR_Close(local_file_fd
);
573 PR_Close(local_file_fd
);
576 readBuffer
= (char *)PORT_Alloc(READ_BUFFER_SIZE
);
578 fprintf (stderr
, _("Out of memory\n"));
582 local_file_fd
= PR_Open(connectionState
->outfileName
, PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
,
583 PR_IRUSR
| PR_IWUSR
| PR_IRGRP
| PR_IWGRP
| PR_IROTH
);
584 if (local_file_fd
== NULL
)
586 fprintf (stderr
, STAP_CSC_04
, connectionState
->outfileName
);
591 numBytes
= PR_Read(sslSocket
, readBuffer
, READ_BUFFER_SIZE
);
597 secStatus
= SECFailure
;
601 /* Write to output file */
602 numBytes
= PR_Write(local_file_fd
, readBuffer
, numBytes
);
605 fprintf (stderr
, STAP_CSC_05
, connectionState
->outfileName
);
606 secStatus
= SECFailure
;
612 PR_Close(local_file_fd
);
614 /* Caller closes the socket. */
618 /* make the connection.
621 do_connect (connectionState_t
*connectionState
)
623 PRFileDesc
*sslSocket
;
627 secStatus
= SECSuccess
;
629 /* Set up SSL secure socket. */
630 sslSocket
= setupSSLSocket (connectionState
);
631 if (sslSocket
== NULL
)
634 #if 0 /* no client authentication */
635 secStatus
= SSL_SetPKCS11PinArg(sslSocket
, password
);
636 if (secStatus
!= SECSuccess
)
640 secStatus
= SSL_SetURL(sslSocket
, connectionState
->hostName
);
641 if (secStatus
!= SECSuccess
)
644 prStatus
= PR_Connect(sslSocket
, & connectionState
->addr
, PR_INTERVAL_NO_TIMEOUT
);
645 if (prStatus
!= PR_SUCCESS
)
647 secStatus
= SECFailure
;
651 /* Established SSL connection, ready to send data. */
652 secStatus
= SSL_ResetHandshake(sslSocket
, /* asServer */ PR_FALSE
);
653 if (secStatus
!= SECSuccess
)
656 /* This is normally done automatically on the first I/O operation,
657 but doing it here catches any authentication problems early. */
658 secStatus
= SSL_ForceHandshake(sslSocket
);
659 if (secStatus
!= SECSuccess
)
662 // Connect to the server and make the request.
663 secStatus
= handle_connection(sslSocket
, connectionState
);
666 prStatus
= PR_Close(sslSocket
);
671 client_connect (const char *hostName
, PRUint32 ip
,
673 const char* infileName
, const char* outfileName
,
674 const char* trustNewServer
)
680 PRErrorCode errorNumber
;
681 char buffer
[PR_NETDB_BUF_SIZE
];
683 int errCode
= GENERAL_ERROR
;
684 struct connectionState_t connectionState
;
686 connectionState
.hostName
= hostName
;
687 connectionState
.port
= port
;
688 connectionState
.infileName
= infileName
;
689 connectionState
.outfileName
= outfileName
;
690 connectionState
.trustNewServerMode
= trustNewServer
;
692 /* Setup network connection. If we have an ip address, then
693 simply use it, otherwise we need to resolve the host name. */
696 connectionState
.addr
.inet
.family
= PR_AF_INET
;
697 connectionState
.addr
.inet
.port
= htons (port
);
698 connectionState
.addr
.inet
.ip
= htonl (ip
);
702 prStatus
= PR_GetHostByName(hostName
, buffer
, sizeof (buffer
), &hostEntry
);
703 if (prStatus
!= PR_SUCCESS
) {
704 fprintf (stderr
, _("Unable to resolve server host name"));
708 rv
= PR_EnumerateHostEnt(0, &hostEntry
, port
, &connectionState
.addr
);
710 fprintf (stderr
, _("Unable to resolve server host address"));
715 /* Some errors (see below) represent a situation in which trying again
716 should succeed. However, don't try forever. */
717 for (attempt
= 0; attempt
< 5; ++attempt
)
719 secStatus
= do_connect (& connectionState
);
720 if (secStatus
== SECSuccess
)
723 errorNumber
= PR_GetError ();
726 case PR_CONNECT_RESET_ERROR
:
727 /* Server was not ready. */
729 break; /* Try again */
730 case SEC_ERROR_EXPIRED_CERTIFICATE
:
731 /* The server's certificate has expired. It should
732 generate a new certificate. Return now and we'll try again. */
733 errCode
= SERVER_CERT_EXPIRED_ERROR
;
735 case SEC_ERROR_CA_CERT_INVALID
:
736 /* The server's certificate is not trusted. The exit code must
738 errCode
= CA_CERT_INVALID_ERROR
;
741 /* This error is fatal. */
750 compile_server_client::passes_0_4 ()
752 PROBE1(stap
, client__start
, &s
);
754 // arguments parsed; get down to business
756 clog
<< _("Using a compile server.") << endl
;
758 struct tms tms_before
;
759 times (& tms_before
);
760 struct timeval tv_before
;
761 gettimeofday (&tv_before
, NULL
);
763 // Create the request package.
764 int rc
= initialize ();
765 if (rc
!= 0 || pending_interrupts
) goto done
;
766 rc
= create_request ();
767 if (rc
!= 0 || pending_interrupts
) goto done
;
768 rc
= package_request ();
769 if (rc
!= 0 || pending_interrupts
) goto done
;
771 // Submit it to the server.
772 rc
= find_and_connect_to_server ();
773 if (rc
!= 0 || pending_interrupts
) goto done
;
775 // Unpack and process the response.
776 rc
= unpack_response ();
777 if (rc
!= 0 || pending_interrupts
) goto done
;
778 rc
= process_response ();
780 if (rc
== 0 && s
.last_pass
== 4)
782 cout
<< s
.module_name
+ ".ko";
787 struct tms tms_after
;
789 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
790 struct timeval tv_after
;
791 gettimeofday (&tv_after
, NULL
);
793 #define TIMESPRINT "in " << \
794 (tms_after.tms_cutime + tms_after.tms_utime \
795 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
796 << (tms_after.tms_cstime + tms_after.tms_stime \
797 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
798 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
799 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
801 // syntax errors, if any, are already printed
804 string ws
= s
.winning_server
;
805 if (ws
== "") ws
= "?";
806 clog
<< _("Passes: via server ") << ws
<< " "
813 clog
<< _("Passes: via server failed. Try again with another '-v' option.") << endl
;
818 // Save the module, if necessary.
819 if (s
.last_pass
== 4)
820 s
.save_module
= true;
822 // Copy module to the current directory.
823 if (s
.save_module
&& ! pending_interrupts
)
825 string module_src_path
= s
.tmpdir
+ "/" + s
.module_name
+ ".ko";
826 string module_dest_path
= s
.module_name
+ ".ko";
827 copy_file (module_src_path
, module_dest_path
, s
.verbose
>= 3);
828 // Also copy the module signature, it it exists.
829 module_src_path
+= ".sgn";
830 if (file_exists (module_src_path
))
832 module_dest_path
+= ".sgn";
833 copy_file(module_src_path
, module_dest_path
, s
.verbose
>= 3);
838 PROBE1(stap
, client__end
, &s
);
843 // Initialize a client/server session.
845 compile_server_client::initialize ()
849 // Initialize session state
852 // Private location for server certificates.
853 private_ssl_dbs
.push_back (private_ssl_cert_db_path ());
855 // Additional public location.
856 public_ssl_dbs
.push_back (global_ssl_cert_db_path ());
858 // Create a temporary directory to package things in.
859 client_tmpdir
= s
.tmpdir
+ "/client";
860 rc
= create_dir (client_tmpdir
.c_str ());
863 const char* e
= strerror (errno
);
864 clog
<< _("ERROR: cannot create temporary directory (\"")
865 << client_tmpdir
<< "\"): " << e
872 // Create the request package.
874 compile_server_client::create_request ()
876 // Add the current protocol version.
877 int rc
= write_to_file (client_tmpdir
+ "/version", CURRENT_CS_PROTOCOL_VERSION
);
881 // Add the script file or script option
882 if (s
.script_file
!= "")
884 if (s
.script_file
== "-")
886 // Copy the script from stdin
887 string packaged_script_dir
= client_tmpdir
+ "/script";
888 rc
= create_dir (packaged_script_dir
.c_str ());
891 const char* e
= strerror (errno
);
892 clog
<< _("ERROR: cannot create temporary directory ")
893 << packaged_script_dir
<< ": " << e
897 rc
= ! copy_file("/dev/stdin", packaged_script_dir
+ "/-");
901 // Name the script in the packaged arguments.
902 rc
= add_package_arg ("script/-");
908 // Add the script to our package. This will also name the script
909 // in the packaged arguments.
910 rc
= include_file_or_directory ("script", s
.script_file
);
916 // Add -I paths. Skip the default directory.
917 if (s
.include_arg_start
!= -1)
919 unsigned limit
= s
.include_path
.size ();
920 for (unsigned i
= s
.include_arg_start
; i
< limit
; ++i
)
922 rc
= add_package_arg ("-I");
925 rc
= include_file_or_directory ("tapset", s
.include_path
[i
]);
931 // Add other options.
932 rc
= add_package_args ();
936 // Add the sysinfo file
937 string sysinfo
= "sysinfo: " + s
.kernel_release
+ " " + s
.architecture
;
938 rc
= write_to_file (client_tmpdir
+ "/sysinfo", sysinfo
);
942 // Add localization data
943 rc
= add_localization_variables();
948 // Add the arguments specified on the command line to the server request
949 // package, as appropriate.
951 compile_server_client::add_package_args ()
953 // stap arguments to be passed to the server.
955 unsigned limit
= s
.server_args
.size();
956 for (unsigned i
= 0; i
< limit
; ++i
)
958 rc
= add_package_arg (s
.server_args
[i
]);
964 limit
= s
.args
.size();
966 rc
= add_package_arg ("--");
969 for (unsigned i
= 0; i
< limit
; ++i
)
971 rc
= add_package_arg (s
.args
[i
]);
980 compile_server_client::add_package_arg (const string
&arg
)
984 fname
<< client_tmpdir
<< "/argv" << ++argc
;
985 write_to_file (fname
.str (), arg
); // NB: No terminating newline
989 // Symbolically link the given file or directory into the client's temp
990 // directory under the given subdirectory.
992 compile_server_client::include_file_or_directory (
993 const string
&subdir
, const string
&path
996 // Must predeclare these because we do use 'goto done' to
997 // exit from error situations.
998 vector
<string
> components
;
1002 // Canonicalize the given path and remove the leading /.
1004 char *cpath
= canonicalize_file_name (path
.c_str ());
1007 // It can not be canonicalized. Use the name relative to
1008 // the current working directory and let the server deal with it.
1010 if (getcwd (cwd
, sizeof (cwd
)) == NULL
)
1016 rpath
= string (cwd
) + "/" + path
;
1020 // It can be canonicalized. Use the canonicalized name and add this
1021 // file or directory to the request package.
1025 // Including / would require special handling in the code below and
1026 // is a bad idea anyway. Let's not allow it.
1030 clog
<< _F("%s resolves to %s\n", path
.c_str (), rpath
.c_str ());
1031 clog
<< _F("Unable to send %s to the server\n", path
.c_str ());
1035 // First create the requested subdirectory.
1036 name
= client_tmpdir
+ "/" + subdir
;
1037 rc
= create_dir (name
.c_str ());
1040 // Now create each component of the path within the sub directory.
1041 assert (rpath
[0] == '/');
1042 tokenize (rpath
.substr (1), components
, "/");
1043 assert (components
.size () >= 1);
1045 for (i
= 0; i
< components
.size() - 1; ++i
)
1047 if (components
[i
].empty ())
1048 continue; // embedded '//'
1049 name
+= "/" + components
[i
];
1050 rc
= create_dir (name
.c_str ());
1054 // Now make a symbolic link to the actual file or directory.
1055 assert (i
== components
.size () - 1);
1056 name
+= "/" + components
[i
];
1057 rc
= symlink (rpath
.c_str (), name
.c_str ());
1061 // Name this file or directory in the packaged arguments.
1062 rc
= add_package_arg (subdir
+ "/" + rpath
.substr (1));
1067 const char* e
= strerror (errno
);
1068 clog
<< "ERROR: unable to add "
1070 << " to temp directory as "
1071 << name
<< ": " << e
1077 // Add the localization variables to the server request
1080 compile_server_client::add_localization_variables()
1086 const set
<string
> &locVars
= localization_variables();
1087 set
<string
>::iterator it
;
1089 /* Note: We don't have to check for the contents of the environment
1090 * variables here, since they will be checked extensively on the
1093 for (it
= locVars
.begin(); it
!= locVars
.end(); it
++)
1095 char* var
= getenv((*it
).c_str());
1097 envVar
+= *it
+ "=" + (string
)var
+ "\n";
1099 fname
= client_tmpdir
+ "/locale";
1100 rc
= write_to_file(fname
, envVar
);
1104 // Package the client's temp directory into a form suitable for sending to the
1107 compile_server_client::package_request ()
1109 // Package up the temporary directory into a zip file.
1110 client_zipfile
= client_tmpdir
+ ".zip";
1111 string cmd
= "cd " + cmdstr_quoted(client_tmpdir
) + " && zip -qr "
1112 + cmdstr_quoted(client_zipfile
) + " *";
1113 vector
<string
> sh_cmd
;
1114 sh_cmd
.push_back("sh");
1115 sh_cmd
.push_back("-c");
1116 sh_cmd
.push_back(cmd
);
1117 int rc
= stap_system (s
.verbose
, sh_cmd
);
1122 compile_server_client::find_and_connect_to_server ()
1124 // Accumulate info on the specified servers.
1125 vector
<compile_server_info
> specified_servers
;
1126 get_specified_server_info (s
, specified_servers
);
1128 // Examine the specified servers to make sure that each has been resolved
1129 // with a host name, ip address and port. If not, try to obtain this
1130 // information by examining online servers.
1131 vector
<compile_server_info
> server_list
= specified_servers
;
1132 for (vector
<compile_server_info
>::const_iterator i
= specified_servers
.begin ();
1133 i
!= specified_servers
.end ();
1136 // If we have an ip address and port number, then just use the one we've
1137 // been given. Otherwise, check for matching online servers and try their
1138 // ip addresses and ports.
1139 if (! i
->host_name
.empty () && ! i
->ip_address
.empty () && i
->port
!= 0)
1140 add_server_info (*i
, server_list
);
1143 // Obtain a list of online servers.
1144 vector
<compile_server_info
> online_servers
;
1145 get_or_keep_online_server_info (s
, online_servers
, false/*keep*/);
1147 // If no specific server (port) has been specified,
1148 // then we'll need the servers to be
1149 // compatible and possible trusted as signers as well.
1152 get_or_keep_compatible_server_info (s
, online_servers
, true/*keep*/);
1153 if (! pr_contains (s
.privilege
, pr_stapdev
))
1154 get_or_keep_signing_server_info (s
, online_servers
, true/*keep*/);
1157 // Keep the ones (if any) which match our server.
1158 keep_common_server_info (*i
, online_servers
);
1160 // Add these servers (if any) to the server list.
1161 add_server_info (online_servers
, server_list
);
1165 // Did we identify any potential servers?
1166 unsigned limit
= server_list
.size ();
1169 clog
<< _("Unable to find a compile server.") << endl
;
1173 // Sort the list of servers into a preferred order.
1174 preferred_order (server_list
);
1176 // Now try each of the identified servers in turn.
1177 int rc
= compile_using_server (server_list
);
1179 return 0; // success!
1181 // If the error was that a server's cert was expired, try again. This is because the server
1182 // should generate a new cert which may be automatically trusted by us if it is our server.
1183 // Give the server a chance to do this before retrying.
1184 if (rc
== SERVER_CERT_EXPIRED_ERROR
)
1187 clog
<< _("The server's certificate was expired. Trying again") << endl
<< flush
;
1189 rc
= compile_using_server (server_list
);
1191 return 0; // success!
1194 // We were unable to use any available server
1195 clog
<< _("Unable to connect to a server.") << endl
;
1196 return 1; // Failure
1200 compile_server_client::compile_using_server (
1201 const vector
<compile_server_info
> &servers
1204 // Make sure NSPR is initialized. Must be done before NSS is initialized
1207 // Attempt connection using each of the available client certificate
1208 // databases. Assume the server certificate is invalid until proven otherwise.
1209 PR_SetError (SEC_ERROR_CA_CERT_INVALID
, 0);
1210 vector
<string
> dbs
= private_ssl_dbs
;
1211 vector
<string
>::iterator i
= dbs
.end();
1212 dbs
.insert (i
, public_ssl_dbs
.begin (), public_ssl_dbs
.end ());
1213 int rc
= GENERAL_ERROR
; // assume failure
1214 bool serverCertExpired
= false;
1215 for (i
= dbs
.begin (); i
!= dbs
.end (); ++i
)
1217 // Make sure the database directory exists. It is not an error if it
1219 if (! file_exists (*i
))
1222 #if 0 // no client authentication for now.
1223 // Set our password function callback.
1224 PK11_SetPasswordFunc (myPasswd
);
1227 // Initialize the NSS libraries.
1228 const char *cert_dir
= i
->c_str ();
1229 SECStatus secStatus
= nssInit (cert_dir
);
1230 if (secStatus
!= SECSuccess
)
1232 // Message already issued.
1233 continue; // try next database
1236 // Enable cipher suites which are allowed by U.S. export regulations.
1237 // SSL_ClearSessionCache is required for the new settings to take effect.
1238 secStatus
= NSS_SetExportPolicy ();
1239 SSL_ClearSessionCache ();
1240 if (secStatus
!= SECSuccess
)
1242 clog
<< _("Unable to set NSS export policy");
1244 nssCleanup (cert_dir
);
1245 continue; // try next database
1248 server_zipfile
= s
.tmpdir
+ "/server.zip";
1250 // Try each server in turn.
1251 for (vector
<compile_server_info
>::const_iterator j
= servers
.begin ();
1252 j
!= servers
.end ();
1256 clog
<< _F("Attempting SSL connection with %s\n"
1257 " using certificates from the database in %s\n",
1258 lex_cast(*j
).c_str(), cert_dir
);
1260 // The host name defaults to the ip address, if not specified.
1262 if (j
->host_name
.empty ())
1264 assert (! j
->ip_address
.empty ());
1265 hostName
= j
->ip_address
;
1268 hostName
= j
->host_name
;
1270 rc
= client_connect (hostName
.c_str (),
1271 stringToIpAddress (j
->ip_address
),
1273 client_zipfile
.c_str(), server_zipfile
.c_str (),
1274 NULL
/*trustNewServer_p*/);
1278 hostName
+ string(" [") +
1279 j
->ip_address
+ string(":") +
1280 lex_cast(j
->port
) + string("]");
1284 // Server cert has expired. Try other servers and/or databases, but take note because
1285 // server should generate a new certificate. If no other servers succeed, we'll try again
1286 // in case the new cert works.
1287 if (rc
== SERVER_CERT_EXPIRED_ERROR
)
1289 serverCertExpired
= true;
1295 clog
<< _(" Unable to connect: ");
1300 // SSL_ClearSessionCache is required before shutdown for client applications.
1301 SSL_ClearSessionCache ();
1302 nssCleanup (cert_dir
);
1304 if (rc
== SECSuccess
)
1308 // Indicate whether a server cert was expired, so we can try again, if desired.
1311 if (serverCertExpired
)
1312 rc
= SERVER_CERT_EXPIRED_ERROR
;
1319 compile_server_client::unpack_response ()
1321 // Unzip the response package.
1322 server_tmpdir
= s
.tmpdir
+ "/server";
1324 cmd
.push_back("unzip");
1325 cmd
.push_back("-qd");
1326 cmd
.push_back(server_tmpdir
);
1327 cmd
.push_back(server_zipfile
);
1328 int rc
= stap_system (s
.verbose
, cmd
);
1331 clog
<< _F("Unable to unzip the server response '%s'\n", server_zipfile
.c_str());
1335 // Determine the server protocol version.
1336 string filename
= server_tmpdir
+ "/version";
1337 if (file_exists (filename
))
1338 ::read_from_file (filename
, server_version
);
1340 // Warn about the shortcomings of this server, if it is down level.
1341 show_server_compatibility ();
1343 // If the server's response contains a systemtap temp directory, move
1344 // its contents to our temp directory.
1346 string filespec
= server_tmpdir
+ "/stap??????";
1348 clog
<< _F("Searching \"%s\"\n", filespec
.c_str());
1349 int r
= glob(filespec
.c_str (), 0, NULL
, & globbuf
);
1350 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1352 if (globbuf
.gl_pathc
> 1)
1354 clog
<< _("Incorrect number of files in server response") << endl
;
1359 assert (globbuf
.gl_pathc
== 1);
1360 string dirname
= globbuf
.gl_pathv
[0];
1362 clog
<< _(" found ") << dirname
<< endl
;
1364 filespec
= dirname
+ "/*";
1366 clog
<< _F("Searching \"%s\"\n", filespec
.c_str());
1367 int r
= glob(filespec
.c_str (), GLOB_PERIOD
, NULL
, & globbuf
);
1368 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1370 unsigned prefix_len
= dirname
.size () + 1;
1371 for (unsigned i
= 0; i
< globbuf
.gl_pathc
; ++i
)
1373 string oldname
= globbuf
.gl_pathv
[i
];
1374 if (oldname
.substr (oldname
.size () - 2) == "/." ||
1375 oldname
.substr (oldname
.size () - 3) == "/..")
1377 string newname
= s
.tmpdir
+ "/" + oldname
.substr (prefix_len
);
1379 clog
<< _F(" found %s -- linking from %s", oldname
.c_str(), newname
.c_str());
1380 rc
= symlink (oldname
.c_str (), newname
.c_str ());
1383 clog
<< _F("Unable to link '%s' to '%s':%s\n",
1384 oldname
.c_str(), newname
.c_str(), strerror(errno
));
1391 // If the server version is less that 1.6, remove the output line due to the synthetic
1392 // server-side -k. Look for a message containing the name of the temporary directory.
1393 // We can look for the English message since server versions before 1.1 do not support
1395 if (server_version
< "1.6")
1398 cmd
.push_back("sed");
1399 cmd
.push_back("-i");
1400 cmd
.push_back("/^Keeping temporary directory.*/ d");
1401 cmd
.push_back(server_tmpdir
+ "/stderr");
1402 stap_system (s
.verbose
, cmd
);
1405 // Remove the output line due to the synthetic server-side -p4
1407 cmd
.push_back("sed");
1408 cmd
.push_back("-i");
1409 cmd
.push_back("/^.*\\.ko$/ d");
1410 cmd
.push_back(server_tmpdir
+ "/stdout");
1411 stap_system (s
.verbose
, cmd
);
1414 globfree (& globbuf
);
1419 compile_server_client::process_response ()
1421 // Pick up the results of running stap on the server.
1422 string filename
= server_tmpdir
+ "/rc";
1424 int rc
= read_from_file (filename
, stap_rc
);
1429 if (s
.last_pass
>= 4)
1431 // The server should have returned a module.
1432 string filespec
= s
.tmpdir
+ "/*.ko";
1434 clog
<< _F("Searching \"%s\"\n", filespec
.c_str());
1437 int r
= glob(filespec
.c_str (), 0, NULL
, & globbuf
);
1438 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1440 if (globbuf
.gl_pathc
> 1)
1441 clog
<< _("Incorrect number of modules in server response") << endl
;
1444 assert (globbuf
.gl_pathc
== 1);
1445 string modname
= globbuf
.gl_pathv
[0];
1447 clog
<< _(" found ") << modname
<< endl
;
1449 // If a module name was not specified by the user, then set it to
1450 // be the one generated by the server.
1451 if (! s
.save_module
)
1453 vector
<string
> components
;
1454 tokenize (modname
, components
, "/");
1455 s
.module_name
= components
.back ();
1456 s
.module_name
.erase(s
.module_name
.size() - 3);
1459 // If a uprobes.ko module was returned, then make note of it.
1461 if (server_version
< "1.6")
1462 uprobes_ko
= s
.tmpdir
+ "/server/uprobes.ko";
1464 uprobes_ko
= s
.tmpdir
+ "/uprobes/uprobes.ko";
1466 if (file_exists (uprobes_ko
))
1468 s
.need_uprobes
= true;
1469 s
.uprobes_path
= uprobes_ko
;
1473 else if (s
.have_script
)
1477 clog
<< _("No module was returned by the server.") << endl
;
1481 globfree (& globbuf
);
1484 // Output stdout and stderr.
1485 filename
= server_tmpdir
+ "/stderr";
1486 flush_to_stream (filename
, clog
);
1488 filename
= server_tmpdir
+ "/stdout";
1489 flush_to_stream (filename
, cout
);
1495 compile_server_client::read_from_file (const string
&fname
, int &data
)
1497 // C++ streams may not set errno in the even of a failure. However if we
1498 // set it to 0 before each operation and it gets set during the operation,
1499 // then we can use its value in order to determine what happened.
1501 ifstream
f (fname
.c_str ());
1504 clog
<< _F("Unable to open file '%s' for reading: ", fname
.c_str());
1513 clog
<< _F("Unable to read from file '%s': ", fname
.c_str());
1517 // NB: not necessary to f.close ();
1518 return 0; // Success
1522 clog
<< strerror (errno
) << endl
;
1524 clog
<< _("unknown error") << endl
;
1525 return 1; // Failure
1530 compile_server_client::write_to_file (const string
&fname
, const T
&data
)
1532 // C++ streams may not set errno in the even of a failure. However if we
1533 // set it to 0 before each operation and it gets set during the operation,
1534 // then we can use its value in order to determine what happened.
1536 ofstream
f (fname
.c_str ());
1539 clog
<< _F("Unable to open file '%s' for writing: ", fname
.c_str());
1548 clog
<< _F("Unable to write to file '%s': ", fname
.c_str());
1552 // NB: not necessary to f.close ();
1553 return 0; // Success
1557 clog
<< strerror (errno
) << endl
;
1559 clog
<< _("unknown error") << endl
;
1560 return 1; // Failure
1564 compile_server_client::flush_to_stream (const string
&fname
, ostream
&o
)
1566 // C++ streams may not set errno in the even of a failure. However if we
1567 // set it to 0 before each operation and it gets set during the operation,
1568 // then we can use its value in order to determine what happened.
1570 ifstream
f (fname
.c_str ());
1573 clog
<< _F("Unable to open file '%s' for reading: ", fname
.c_str());
1579 // NB: o << f.rdbuf() misbehaves for some reason, appearing to close o,
1580 // which is unfortunate if o == clog or cout.
1585 if (f
.eof ()) return 0; // normal exit
1586 if (! f
.good()) break;
1588 if (! o
.good()) break;
1591 // NB: not necessary to f.close ();
1595 clog
<< strerror (errno
) << endl
;
1597 clog
<< _("unknown error") << endl
;
1598 return 1; // Failure
1602 compile_server_client::show_server_compatibility () const
1604 // Locale sensitivity was added in version 1.6
1605 if (server_version
< "1.6")
1607 clog
<< _F("Server protocol version is %s\n", server_version
.v
);
1608 clog
<< _("The server does not use localization information passed by the client\n");
1612 // Issue a status message for when a server's trust is already in place.
1614 trust_already_in_place (
1615 const compile_server_info
&server
,
1616 const vector
<compile_server_info
> &server_list
,
1617 const string cert_db_path
,
1621 // What level of trust?
1623 if (cert_db_path
== signing_cert_db_path ())
1624 purpose
= _("as a module signer for all users");
1627 purpose
= _("as an SSL peer");
1628 if (cert_db_path
== global_ssl_cert_db_path ())
1629 purpose
+= _(" for all users");
1631 purpose
+= _(" for the current user");
1634 // Issue a message for each server in the list with the same certificate.
1635 unsigned limit
= server_list
.size ();
1636 for (unsigned i
= 0; i
< limit
; ++i
)
1638 if (server
.certinfo
!= server_list
[i
].certinfo
)
1640 clog
<< server_list
[i
] << _(" is already ");
1642 clog
<< _("untrusted ") << purpose
<< endl
;
1644 clog
<< _("trusted ") << purpose
<< endl
;
1648 // Add the given servers to the given database of trusted servers.
1651 systemtap_session
&s
,
1652 const string
&cert_db_path
,
1653 const vector
<compile_server_info
> &server_list
1656 // Get a list of servers already trusted. This opens the database, so do it
1657 // before we open it for our own purposes.
1658 vector
<compile_server_info
> already_trusted
;
1659 get_server_info_from_db (s
, already_trusted
, cert_db_path
);
1661 // Make sure the given path exists.
1662 if (create_dir (cert_db_path
.c_str (), 0755) != 0)
1664 clog
<< _F("Unable to find or create the client certificate database directory %s: ", cert_db_path
.c_str());
1669 // Must predeclare this because of jumps to cleanup: below.
1670 vector
<string
> processed_certs
;
1672 // Make sure NSPR is initialized. Must be done before NSS is initialized
1675 // Initialize the NSS libraries -- read/write
1676 SECStatus secStatus
= nssInit (cert_db_path
.c_str (), 1/*readwrite*/);
1677 if (secStatus
!= SECSuccess
)
1679 // Message already issued.
1683 // Enable cipher suites which are allowed by U.S. export regulations.
1684 // SSL_ClearSessionCache is required for the new settings to take effect.
1685 secStatus
= NSS_SetExportPolicy ();
1686 SSL_ClearSessionCache ();
1687 if (secStatus
!= SECSuccess
)
1689 clog
<< _("Unable to set NSS export policy");
1694 // Iterate over the servers to become trusted. Contact each one and
1695 // add it to the list of trusted servers if it is not already trusted.
1696 // client_connect will issue any error messages.
1697 for (vector
<compile_server_info
>::const_iterator server
= server_list
.begin();
1698 server
!= server_list
.end ();
1701 // Trust is based on certificates. We need only add trust in the
1702 // same certificate once.
1703 if (find (processed_certs
.begin (), processed_certs
.end (),
1704 server
->certinfo
) != processed_certs
.end ())
1706 processed_certs
.push_back (server
->certinfo
);
1708 // We need not contact the server if it is already trusted.
1709 if (find (already_trusted
.begin (), already_trusted
.end (), *server
) !=
1710 already_trusted
.end ())
1713 trust_already_in_place (*server
, server_list
, cert_db_path
, false/*revoking*/);
1716 // At a minimum we need a host name or ip_address along with a port
1717 // number in order to contact the server.
1718 if (server
->empty () || server
->port
== 0)
1720 int rc
= client_connect (server
->host_name
.c_str (),
1721 stringToIpAddress (server
->ip_address
),
1723 NULL
, NULL
, "permanent");
1726 clog
<< _F("Unable to connect to %s", lex_cast(*server
).c_str()) << endl
;
1733 // SSL_ClearSessionCache is required before shutdown for client applications.
1734 SSL_ClearSessionCache ();
1735 nssCleanup (cert_db_path
.c_str ());
1737 // Make sure the database files are readable.
1739 string filespec
= cert_db_path
+ "/*.db";
1741 clog
<< _F("Searching \"%s\"\n", filespec
.c_str());
1742 int r
= glob (filespec
.c_str (), 0, NULL
, & globbuf
);
1743 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1745 for (unsigned i
= 0; i
< globbuf
.gl_pathc
; ++i
)
1747 string filename
= globbuf
.gl_pathv
[i
];
1749 clog
<< _(" found ") << filename
<< endl
;
1751 if (chmod (filename
.c_str (), 0644) != 0)
1753 clog
<< _F("Warning: Unable to change permissions on %s: ", filename
.c_str());
1760 // Remove the given servers from the given database of trusted servers.
1762 revoke_server_trust (
1763 systemtap_session
&s
,
1764 const string
&cert_db_path
,
1765 const vector
<compile_server_info
> &server_list
1768 // Make sure the given path exists.
1769 if (! file_exists (cert_db_path
))
1773 clog
<< _F("Certificate database '%s' does not exist",
1774 cert_db_path
.c_str()) << endl
;
1775 for (vector
<compile_server_info
>::const_iterator server
= server_list
.begin();
1776 server
!= server_list
.end ();
1778 trust_already_in_place (*server
, server_list
, cert_db_path
, true/*revoking*/);
1783 // Must predeclare these because of jumps to cleanup: below.
1784 CERTCertDBHandle
*handle
;
1785 PRArenaPool
*tmpArena
= NULL
;
1786 CERTCertList
*certs
= NULL
;
1787 CERTCertificate
*db_cert
;
1788 vector
<string
> processed_certs
;
1789 const char *nickname
;
1791 // Make sure NSPR is initialized. Must be done before NSS is initialized
1794 // Initialize the NSS libraries -- read/write
1795 SECStatus secStatus
= nssInit (cert_db_path
.c_str (), 1/*readwrite*/);
1796 if (secStatus
!= SECSuccess
)
1798 // Message already issued
1801 handle
= CERT_GetDefaultCertDB();
1803 // A memory pool to work in
1804 tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1807 clog
<< _("Out of memory:");
1812 // Iterate over the servers to become untrusted.
1813 nickname
= server_cert_nickname ();
1814 for (vector
<compile_server_info
>::const_iterator server
= server_list
.begin();
1815 server
!= server_list
.end ();
1818 // If the server's certificate serial number is unknown, then we can't
1819 // match it with one in the database.
1820 if (server
->certinfo
.empty ())
1823 // Trust is based on certificates. We need only revoke trust in the same
1824 // certificate once.
1825 if (find (processed_certs
.begin (), processed_certs
.end (),
1826 server
->certinfo
) != processed_certs
.end ())
1828 processed_certs
.push_back (server
->certinfo
);
1830 // Search the client-side database of trusted servers.
1831 db_cert
= PK11_FindCertFromNickname (nickname
, NULL
);
1834 // No trusted servers. Not an error, but issue a status message.
1836 trust_already_in_place (*server
, server_list
, cert_db_path
, true/*revoking*/);
1840 // Here, we have one cert with the desired nickname.
1841 // Now, we will attempt to get a list of ALL certs
1842 // with the same subject name as the cert we have. That list
1843 // should contain, at a minimum, the one cert we have already found.
1844 // If the list of certs is empty (NULL), the libraries have failed.
1845 certs
= CERT_CreateSubjectCertList (NULL
, handle
, & db_cert
->derSubject
,
1846 PR_Now (), PR_FALSE
);
1847 CERT_DestroyCertificate (db_cert
);
1850 clog
<< _F("Unable to query certificate database %s: ",
1851 cert_db_path
.c_str()) << endl
;
1852 PORT_SetError (SEC_ERROR_LIBRARY_FAILURE
);
1857 // Find the certificate matching the one belonging to our server.
1858 CERTCertListNode
*node
;
1859 for (node
= CERT_LIST_HEAD (certs
);
1860 ! CERT_LIST_END (node
, certs
);
1861 node
= CERT_LIST_NEXT (node
))
1863 // The certificate we're working with.
1864 db_cert
= node
->cert
;
1866 // Get the serial number.
1867 string serialNumber
= get_cert_serial_number (db_cert
);
1869 // Does the serial number match that of the current server?
1870 if (serialNumber
!= server
->certinfo
)
1871 continue; // goto next certificate
1873 // All is ok! Remove the certificate from the database.
1875 } // Loop over certificates in the database
1877 // Was a certificate matching the server found? */
1878 if (CERT_LIST_END (node
, certs
))
1880 // Not found. Server is already untrusted.
1882 trust_already_in_place (*server
, server_list
, cert_db_path
, true/*revoking*/);
1886 secStatus
= SEC_DeletePermCertificate (db_cert
);
1887 if (secStatus
!= SECSuccess
)
1889 clog
<< _F("Unable to remove certificate from %s: ",
1890 cert_db_path
.c_str()) << endl
;
1894 CERT_DestroyCertList (certs
);
1896 } // Loop over servers
1900 CERT_DestroyCertList (certs
);
1902 PORT_FreeArena (tmpArena
, PR_FALSE
);
1904 nssCleanup (cert_db_path
.c_str ());
1907 // Obtain information about servers from the certificates in the given database.
1909 get_server_info_from_db (
1910 systemtap_session
&s
,
1911 vector
<compile_server_info
> &servers
,
1912 const string
&cert_db_path
1915 // Make sure the given path exists.
1916 if (! file_exists (cert_db_path
))
1919 clog
<< _F("Certificate database '%s' does not exist.",
1920 cert_db_path
.c_str()) << endl
;
1924 // Make sure NSPR is initialized. Must be done before NSS is initialized
1927 // Initialize the NSS libraries -- readonly
1928 SECStatus secStatus
= nssInit (cert_db_path
.c_str ());
1929 if (secStatus
!= SECSuccess
)
1931 // Message already issued.
1935 // Must predeclare this because of jumps to cleanup: below.
1936 PRArenaPool
*tmpArena
= NULL
;
1937 CERTCertList
*certs
= get_cert_list_from_db (server_cert_nickname ());
1941 clog
<< _F("No certificate found in database %s", cert_db_path
.c_str ()) << endl
;
1945 // A memory pool to work in
1946 tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1949 clog
<< _("Out of memory:");
1953 for (CERTCertListNode
*node
= CERT_LIST_HEAD (certs
);
1954 ! CERT_LIST_END (node
, certs
);
1955 node
= CERT_LIST_NEXT (node
))
1957 compile_server_info server_info
;
1959 // The certificate we're working with.
1960 CERTCertificate
*db_cert
= node
->cert
;
1962 // Get the host name. It is in the alt-name extension of the
1965 subAltName
.data
= NULL
;
1966 secStatus
= CERT_FindCertExtension (db_cert
,
1967 SEC_OID_X509_SUBJECT_ALT_NAME
,
1969 if (secStatus
!= SECSuccess
|| ! subAltName
.data
)
1971 clog
<< _("Unable to find alt name extension on server certificate: ") << endl
;
1976 // Decode the extension.
1977 CERTGeneralName
*nameList
= CERT_DecodeAltNameExtension (tmpArena
, & subAltName
);
1978 SECITEM_FreeItem(& subAltName
, PR_FALSE
);
1981 clog
<< _("Unable to decode alt name extension on server certificate: ") << endl
;
1986 // We're interested in the first alternate name.
1987 assert (nameList
->type
== certDNSName
);
1988 server_info
.host_name
= string ((const char *)nameList
->name
.other
.data
,
1989 nameList
->name
.other
.len
);
1990 // Don't free nameList. It's part of the tmpArena.
1992 // Get the serial number.
1993 server_info
.certinfo
= get_cert_serial_number (db_cert
);
1995 // Our results will at a minimum contain this server.
1996 add_server_info (server_info
, servers
);
1998 // Augment the list by querying all online servers and keeping the ones
1999 // with the same cert serial number.
2000 vector
<compile_server_info
> online_servers
;
2001 get_or_keep_online_server_info (s
, online_servers
, false/*keep*/);
2002 keep_server_info_with_cert_and_port (s
, server_info
, online_servers
);
2003 add_server_info (online_servers
, servers
);
2008 CERT_DestroyCertList (certs
);
2010 PORT_FreeArena (tmpArena
, PR_FALSE
);
2012 nssCleanup (cert_db_path
.c_str ());
2016 // Utility Functions.
2017 //-----------------------------------------------------------------------
2018 ostream
&operator<< (ostream
&s
, const compile_server_info
&i
)
2021 if (! i
.host_name
.empty ())
2026 if (! i
.ip_address
.empty ())
2036 if (! i
.sysinfo
.empty ())
2037 s
<< i
.sysinfo
<< '"';
2041 if (! i
.version
.empty ())
2045 s
<< " certinfo=\"";
2046 if (! i
.certinfo
.empty ())
2047 s
<< i
.certinfo
<< '"';
2053 // Return the default server specification, used when none is given on the
2056 default_server_spec (const systemtap_session
&s
)
2058 // If the --use-server option has been used
2059 // the default is 'specified'
2060 // otherwise if --privilege=X has been used, where X is not stapdev,
2061 // the default is online,trusted,compatible,signer
2063 // the default is online,trusted,compatible
2065 // Having said that,
2066 // 'online' and 'compatible' will only succeed if we have avahi
2067 // 'trusted' and 'signer' will only succeed if we have NSS
2069 string working_string
= "online,trusted,compatible";
2070 if (! pr_contains (s
.privilege
, pr_stapdev
))
2071 working_string
+= ",signer";
2072 return working_string
;
2076 server_spec_to_pmask (const string
&server_spec
)
2078 // Construct a mask of the server properties that have been requested.
2079 // The available properties are:
2080 // trusted - servers which are trusted SSL peers.
2081 // online - online servers.
2082 // compatible - servers which compile for the current kernel release
2083 // and architecture.
2084 // signer - servers which are trusted module signers.
2085 // specified - servers which have been specified using --use-server=XXX.
2086 // If no servers have been specified, then this is
2087 // equivalent to --list-servers=trusted,online,compatible.
2088 // all - all trusted servers, trusted module signers,
2089 // servers currently online and specified servers.
2090 string working_spec
= server_spec
;
2091 vector
<string
> properties
;
2092 tokenize (working_spec
, properties
, ",");
2094 unsigned limit
= properties
.size ();
2095 for (unsigned i
= 0; i
< limit
; ++i
)
2097 const string
&property
= properties
[i
];
2098 // Tolerate (and ignore) empty properties.
2099 if (property
.empty ())
2101 if (property
== "all")
2103 pmask
|= compile_server_all
;
2105 else if (property
== "specified")
2107 pmask
|= compile_server_specified
;
2109 else if (property
== "trusted")
2111 pmask
|= compile_server_trusted
;
2113 else if (property
== "online")
2115 pmask
|= compile_server_online
;
2117 else if (property
== "compatible")
2119 pmask
|= compile_server_compatible
;
2121 else if (property
== "signer")
2123 pmask
|= compile_server_signer
;
2127 clog
<< _F("Warning: unsupported compile server property: %s", property
.c_str())
2135 query_server_status (systemtap_session
&s
)
2137 unsigned limit
= s
.server_status_strings
.size ();
2138 for (unsigned i
= 0; i
< limit
; ++i
)
2139 query_server_status (s
, s
.server_status_strings
[i
]);
2143 query_server_status (systemtap_session
&s
, const string
&status_string
)
2145 // If this string is empty, then the default is "specified"
2146 string working_string
= status_string
;
2147 if (working_string
.empty ())
2148 working_string
= "specified";
2150 // If the query is "specified" and no servers have been specified
2151 // (i.e. --use-server not used or used with no argument), then
2152 // use the default query.
2153 // TODO: This may not be necessary. The underlying queries should handle
2154 // "specified" properly.
2155 if (working_string
== "specified" &&
2156 (s
.specified_servers
.empty () ||
2157 (s
.specified_servers
.size () == 1 && s
.specified_servers
[0].empty ())))
2158 working_string
= default_server_spec (s
);
2160 int pmask
= server_spec_to_pmask (working_string
);
2162 // Now obtain a list of the servers which match the criteria.
2163 vector
<compile_server_info
> raw_servers
;
2164 get_server_info (s
, pmask
, raw_servers
);
2166 // Augment the listing with as much information as possible by adding
2167 // information from known servers.
2168 vector
<compile_server_info
> servers
;
2169 get_all_server_info (s
, servers
);
2170 keep_common_server_info (raw_servers
, servers
);
2172 // Sort the list of servers into a preferred order.
2173 preferred_order (servers
);
2175 // Print the server information. Skip the empty entry at the head of the list.
2176 clog
<< _F("Systemtap Compile Server Status for '%s'", working_string
.c_str()) << endl
;
2178 unsigned limit
= servers
.size ();
2179 for (unsigned i
= 0; i
< limit
; ++i
)
2181 assert (! servers
[i
].empty ());
2182 // Don't list servers with no cert information. They may not actually
2184 // TODO: Could try contacting the server and obtaining its cert
2185 if (servers
[i
].certinfo
.empty ())
2187 clog
<< servers
[i
] << endl
;
2191 clog
<< _("No servers found") << endl
;
2194 // Add or remove trust of the servers specified on the command line.
2196 manage_server_trust (systemtap_session
&s
)
2198 // This function should do nothing if we don't have NSS.
2200 // Nothing to do if --trust-servers was not specified.
2201 if (s
.server_trust_spec
.empty ())
2204 // Break up and analyze the trust specification. Recognized components are:
2205 // ssl - trust the specified servers as ssl peers
2206 // signer - trust the specified servers as module signers
2207 // revoke - revoke the requested trust
2208 // all-users - apply/revoke the requested trust for all users
2209 // no-prompt - don't prompt the user for confirmation
2210 vector
<string
>components
;
2211 tokenize (s
.server_trust_spec
, components
, ",");
2213 bool signer
= false;
2214 bool revoke
= false;
2215 bool all_users
= false;
2216 bool no_prompt
= false;
2218 for (vector
<string
>::const_iterator i
= components
.begin ();
2219 i
!= components
.end ();
2224 else if (*i
== "signer")
2226 if (geteuid () != 0)
2228 clog
<< _("Only root can specify 'signer' on --trust-servers") << endl
;
2234 else if (*i
== "revoke")
2236 else if (*i
== "all-users")
2238 if (geteuid () != 0)
2240 clog
<< _("Only root can specify 'all-users' on --trust-servers") << endl
;
2246 else if (*i
== "no-prompt")
2249 clog
<< _("Warning: Unrecognized server trust specification: ") << *i
2255 // Make sure NSPR is initialized
2258 // Now obtain the list of specified servers.
2259 vector
<compile_server_info
> server_list
;
2260 get_specified_server_info (s
, server_list
, true/*no_default*/);
2262 // Did we identify any potential servers?
2263 unsigned limit
= server_list
.size ();
2266 clog
<< _("No servers identified for trust") << endl
;
2270 // Create a string representing the request in English.
2271 // If neither 'ssl' or 'signer' was specified, the default is 'ssl'.
2272 if (! ssl
&& ! signer
)
2274 ostringstream trustString
;
2277 trustString
<< _("as an SSL peer");
2279 trustString
<< _(" for all users");
2281 trustString
<< _(" for the current user");
2286 trustString
<< _(" and ");
2287 trustString
<< _("as a module signer for all users");
2290 // Prompt the user to confirm what's about to happen.
2294 clog
<< _("Revoking trust ");
2296 clog
<< _("Adding trust ");
2301 clog
<< _("Revoke trust ");
2303 clog
<< _("Add trust ");
2305 clog
<< _F("in the following servers %s", trustString
.str().c_str());
2309 for (unsigned i
= 0; i
< limit
; ++i
)
2310 clog
<< " " << server_list
[i
] << endl
;
2313 clog
<< "[y/N] " << flush
;
2315 // Only carry out the operation if the response is "yes"
2318 if (response
[0] != 'y' && response
[0] != 'Y')
2320 clog
<< _("Server trust unchanged") << endl
;
2325 // Now add/revoke the requested trust.
2326 string cert_db_path
;
2330 cert_db_path
= global_ssl_cert_db_path ();
2332 cert_db_path
= private_ssl_cert_db_path ();
2334 revoke_server_trust (s
, cert_db_path
, server_list
);
2336 add_server_trust (s
, cert_db_path
, server_list
);
2340 cert_db_path
= signing_cert_db_path ();
2342 revoke_server_trust (s
, cert_db_path
, server_list
);
2344 add_server_trust (s
, cert_db_path
, server_list
);
2349 static compile_server_cache
*
2350 cscache(systemtap_session
& s
)
2352 if (!s
.server_cache
)
2353 s
.server_cache
= new compile_server_cache();
2354 return s
.server_cache
;
2359 systemtap_session
&s
,
2361 vector
<compile_server_info
> &servers
2364 // Get information on compile servers matching the requested criteria.
2365 // The order of queries is significant. Accumulating queries must go first
2366 // followed by accumulating/filtering queries.
2368 if (((pmask
& compile_server_all
)))
2370 get_all_server_info (s
, servers
);
2373 // Add the specified servers, if requested
2374 if ((pmask
& compile_server_specified
))
2376 get_specified_server_info (s
, servers
);
2379 // Now filter or accumulate the list depending on whether a query has
2380 // already been made.
2381 if ((pmask
& compile_server_online
))
2383 get_or_keep_online_server_info (s
, servers
, keep
);
2386 if ((pmask
& compile_server_trusted
))
2388 get_or_keep_trusted_server_info (s
, servers
, keep
);
2391 if ((pmask
& compile_server_signer
))
2393 get_or_keep_signing_server_info (s
, servers
, keep
);
2396 if ((pmask
& compile_server_compatible
))
2398 get_or_keep_compatible_server_info (s
, servers
, keep
);
2403 // Get information about all online servers as well as servers trusted
2404 // as SSL peers and servers trusted as signers.
2406 get_all_server_info (
2407 systemtap_session
&s
,
2408 vector
<compile_server_info
> &servers
2411 get_or_keep_online_server_info (s
, servers
, false/*keep*/);
2412 get_or_keep_trusted_server_info (s
, servers
, false/*keep*/);
2413 get_or_keep_signing_server_info (s
, servers
, false/*keep*/);
2417 get_default_server_info (
2418 systemtap_session
&s
,
2419 vector
<compile_server_info
> &servers
2422 // We only need to obtain this once per session. This is a good thing(tm)
2423 // since obtaining this information is expensive.
2424 vector
<compile_server_info
>& default_servers
= cscache(s
)->default_servers
;
2425 if (default_servers
.empty ())
2427 // Get the required information.
2428 // get_server_info will add an empty entry at the beginning to indicate
2429 // that the search has been performed, in case the search comes up empty.
2430 int pmask
= server_spec_to_pmask (default_server_spec (s
));
2431 get_server_info (s
, pmask
, default_servers
);
2434 // Add the information, but not duplicates.
2435 add_server_info (default_servers
, servers
);
2439 get_specified_server_info (
2440 systemtap_session
&s
,
2441 vector
<compile_server_info
> &servers
,
2445 // We only need to obtain this once per session. This is a good thing(tm)
2446 // since obtaining this information is expensive.
2447 vector
<compile_server_info
>& specified_servers
= cscache(s
)->specified_servers
;
2448 if (specified_servers
.empty ())
2450 // Maintain an empty entry to indicate that this search has been
2451 // performed, in case the search comes up empty.
2452 specified_servers
.push_back (compile_server_info ());
2454 // If --use-servers was not specified at all, then return info for the
2455 // default server list.
2456 if (s
.specified_servers
.empty ())
2459 get_default_server_info (s
, specified_servers
);
2463 // Iterate over the specified servers. For each specification, add to
2464 // the list of servers.
2465 unsigned num_specified_servers
= s
.specified_servers
.size ();
2466 for (unsigned i
= 0; i
< num_specified_servers
; ++i
)
2468 string
&server
= s
.specified_servers
[i
];
2469 if (server
.empty ())
2471 // No server specified. Use the default servers.
2473 get_default_server_info (s
, specified_servers
);
2477 // Work with the specified server
2478 compile_server_info server_info
;
2480 // See if a port was specified (:n suffix)
2481 vector
<string
> components
;
2482 tokenize (server
, components
, ":");
2483 if (components
.size () > 2)
2485 // Treat it as a certificate serial number. The final
2486 // component may still be a port number.
2487 if (components
.size () > 5)
2489 // Obtain the port number.
2490 const char *pstr
= components
.back ().c_str ();
2493 unsigned long port
= strtoul (pstr
, & estr
, 10);
2494 if (errno
== 0 && *estr
== '\0' && port
<= USHRT_MAX
)
2495 server_info
.port
= port
;
2498 clog
<< _F("Invalid port number specified: %s",
2499 components
.back().c_str()) << endl
;
2502 // Remove the port number from the spec
2503 server_info
.certinfo
= server
.substr (0, server
.find_last_of (':'));
2506 server_info
.certinfo
= server
;
2508 // Look for all known servers with this serial number and
2509 // (optional) port number.
2510 vector
<compile_server_info
> known_servers
;
2511 get_all_server_info (s
, known_servers
);
2512 keep_server_info_with_cert_and_port (s
, server_info
, known_servers
);
2514 if (known_servers
.empty ())
2517 clog
<< _F("No server matching %s found", server
.c_str()) << endl
;
2520 add_server_info (known_servers
, specified_servers
);
2521 } // specified by cert serial number
2523 // Not specified by serial number. Treat it as host name or
2524 // ip address and optional port number.
2525 if (components
.size () == 2)
2527 // Obtain the port number.
2528 const char *pstr
= components
.back ().c_str ();
2531 unsigned long port
= strtoul (pstr
, & estr
, 10);
2532 if (errno
== 0 && *estr
== '\0' && port
<= USHRT_MAX
)
2533 server_info
.port
= port
;
2536 clog
<< _F("Invalid port number specified: %s",
2537 components
.back().c_str()) << endl
;
2542 // Obtain the host name or ip address.
2543 if (stringToIpAddress (components
.front ()))
2544 server_info
.ip_address
= components
.front ();
2546 server_info
.host_name
= components
.front ();
2548 // Find known servers matching the specified information.
2549 vector
<compile_server_info
> known_servers
;
2550 get_all_server_info (s
, known_servers
);
2551 keep_common_server_info (server_info
, known_servers
);
2552 add_server_info (known_servers
, specified_servers
);
2554 // Resolve this host and add any information that is discovered.
2555 resolve_host (s
, server_info
, specified_servers
);
2556 } // Not specified by cert serial number
2557 } // Loop over --use-server options
2558 } // -- use-server specified
2559 } // Server information is not cached
2561 // Add the information, but not duplicates.
2562 add_server_info (specified_servers
, servers
);
2566 get_or_keep_trusted_server_info (
2567 systemtap_session
&s
,
2568 vector
<compile_server_info
> &servers
,
2572 // If we're filtering the list and it's already empty, then
2573 // there's nothing to do.
2574 if (keep
&& servers
.empty ())
2577 // We only need to obtain this once per session. This is a good thing(tm)
2578 // since obtaining this information is expensive.
2579 vector
<compile_server_info
>& trusted_servers
= cscache(s
)->trusted_servers
;
2580 if (trusted_servers
.empty ())
2582 // Maintain an empty entry to indicate that this search has been
2583 // performed, in case the search comes up empty.
2584 trusted_servers
.push_back (compile_server_info ());
2587 // Check the private database first.
2588 string cert_db_path
= private_ssl_cert_db_path ();
2589 get_server_info_from_db (s
, trusted_servers
, cert_db_path
);
2591 // Now check the global database.
2592 cert_db_path
= global_ssl_cert_db_path ();
2593 get_server_info_from_db (s
, trusted_servers
, cert_db_path
);
2595 // Without NSS, we can't determine whether a server is trusted.
2598 clog
<< _("Unable to determine server trust as an SSL peer without NSS") << endl
;
2599 #endif // ! HAVE_NSS
2600 } // Server information is not cached
2604 // Filter the existing vector by keeping the information in common with
2605 // the trusted_server vector.
2606 keep_common_server_info (trusted_servers
, servers
);
2610 // Add the information, but not duplicates.
2611 add_server_info (trusted_servers
, servers
);
2616 get_or_keep_signing_server_info (
2617 systemtap_session
&s
,
2618 vector
<compile_server_info
> &servers
,
2622 // If we're filtering the list and it's already empty, then
2623 // there's nothing to do.
2624 if (keep
&& servers
.empty ())
2627 // We only need to obtain this once per session. This is a good thing(tm)
2628 // since obtaining this information is expensive.
2629 vector
<compile_server_info
>& signing_servers
= cscache(s
)->signing_servers
;
2630 if (signing_servers
.empty ())
2632 // Maintain an empty entry to indicate that this search has been
2633 // performed, in case the search comes up empty.
2634 signing_servers
.push_back (compile_server_info ());
2637 // For all users, check the global database.
2638 string cert_db_path
= signing_cert_db_path ();
2639 get_server_info_from_db (s
, signing_servers
, cert_db_path
);
2641 // Without NSS, we can't determine whether a server is a trusted
2642 // signer. Issue a warning.
2644 clog
<< _("Unable to determine server trust as a module signer without NSS") << endl
;
2645 #endif // ! HAVE_NSS
2646 } // Server information is not cached
2650 // Filter the existing vector by keeping the information in common with
2651 // the signing_server vector.
2652 keep_common_server_info (signing_servers
, servers
);
2656 // Add the information, but not duplicates.
2657 add_server_info (signing_servers
, servers
);
2663 get_or_keep_compatible_server_info (
2664 systemtap_session
&s
,
2665 vector
<compile_server_info
> &servers
,
2670 // If we're filtering the list and it's already empty, then
2671 // there's nothing to do.
2672 if (keep
&& servers
.empty ())
2675 // Remove entries for servers incompatible with the host environment
2676 // from the given list of servers.
2677 // A compatible server compiles for the kernel release and architecture
2678 // of the host environment.
2680 // Compatibility can only be determined for online servers. So, augment
2681 // and filter the information we have with information for online servers.
2682 vector
<compile_server_info
> online_servers
;
2683 get_or_keep_online_server_info (s
, online_servers
, false/*keep*/);
2685 keep_common_server_info (online_servers
, servers
);
2687 add_server_info (online_servers
, servers
);
2689 // Now look to see which ones are compatible.
2690 // The vector can change size as we go, so be careful!!
2691 for (unsigned i
= 0; i
< servers
.size (); /**/)
2693 // Retain empty entries.
2694 assert (! servers
[i
].empty ());
2696 // Check the target of the server.
2697 if (servers
[i
].sysinfo
!= s
.kernel_release
+ " " + s
.architecture
)
2699 // Target platform mismatch.
2700 servers
.erase (servers
.begin () + i
);
2704 // The server is compatible. Leave it in the list.
2707 #else // ! HAVE_AVAHI
2708 // Without Avahi, we can't obtain the target platform of the server.
2711 clog
<< _("Unable to detect server compatibility without avahi") << endl
;
2718 keep_server_info_with_cert_and_port (
2719 systemtap_session
&,
2720 const compile_server_info
&server
,
2721 vector
<compile_server_info
> &servers
2724 assert (! server
.certinfo
.empty ());
2726 // Search the list of servers for ones matching the
2727 // serial number specified.
2728 // The vector can change size as we go, so be careful!!
2729 for (unsigned i
= 0; i
< servers
.size (); /**/)
2731 // Retain empty entries.
2732 if (servers
[i
].empty ())
2737 if (servers
[i
].certinfo
== server
.certinfo
&&
2738 (servers
[i
].port
== 0 || server
.port
== 0 ||
2739 servers
[i
].port
== server
.port
))
2741 // If the server is not online, then use the specified
2743 if (servers
[i
].port
== 0)
2744 servers
[i
].port
= server
.port
;
2748 // The item does not match. Delete it.
2749 servers
.erase (servers
.begin () + i
);
2753 // Obtain missing host name or ip address, if any.
2757 compile_server_info
&server
,
2758 vector
<compile_server_info
> &resolved_servers
2761 // Either the host name or the ip address or both are already set.
2762 const char *lookup_name
;
2763 if (! server
.host_name
.empty ())
2765 // Use the host name to do the lookup.
2766 lookup_name
= server
.host_name
.c_str ();
2770 // Use the ip address to do the lookup.
2771 // getaddrinfo works on both host names and ip addresses.
2772 assert (! server
.ip_address
.empty ());
2773 lookup_name
= server
.ip_address
.c_str ();
2776 // Resolve the server.
2777 struct addrinfo hints
;
2778 memset(& hints
, 0, sizeof (hints
));
2779 hints
.ai_family
= AF_INET
; // AF_UNSPEC or AF_INET6 to force version
2780 struct addrinfo
*addr_info
= NULL
;
2781 int status
= getaddrinfo (lookup_name
, NULL
, & hints
, & addr_info
);
2783 // Failure to resolve will result in an appropriate error later if other
2789 // Loop over the results collecting information.
2790 for (const struct addrinfo
*ai
= addr_info
; ai
!= NULL
; ai
= ai
->ai_next
)
2792 if (ai
->ai_family
!= AF_INET
)
2793 continue; // Not an IPv4 address
2795 // Start with the info we were given.
2796 compile_server_info new_server
= server
;
2798 // Obtain the ip address.
2799 // Start with the pointer to the address itself,
2800 struct sockaddr_in
*ipv4
= (struct sockaddr_in
*)ai
->ai_addr
;
2801 void *addr
= & ipv4
->sin_addr
;
2803 // convert the IP to a string.
2804 char ipstr
[INET_ADDRSTRLEN
];
2805 inet_ntop (ai
->ai_family
, addr
, ipstr
, sizeof (ipstr
));
2806 new_server
.ip_address
= ipstr
;
2808 // Try to obtain a host name.
2809 char hbuf
[NI_MAXHOST
];
2810 status
= getnameinfo (ai
->ai_addr
, sizeof (*ai
->ai_addr
),
2811 hbuf
, sizeof (hbuf
), NULL
, 0,
2812 NI_NAMEREQD
| NI_IDN
);
2814 new_server
.host_name
= hbuf
;
2816 // Add the new resolved server to the list.
2817 add_server_info (new_server
, resolved_servers
);
2822 freeaddrinfo (addr_info
); // free the linked list
2825 // At a minimum, return the information we were given.
2826 add_server_info (server
, resolved_servers
);
2833 // Avahi API Callbacks.
2834 //-----------------------------------------------------------------------
2835 struct browsing_context
{
2836 AvahiSimplePoll
*simple_poll
;
2837 AvahiClient
*client
;
2838 vector
<compile_server_info
> *servers
;
2842 extract_field_from_avahi_txt (const string
&label
, const string
&txt
)
2844 // Extract the requested field from the Avahi TXT.
2845 string prefix
= "\"" + label
;
2846 size_t ix
= txt
.find (prefix
);
2847 if (ix
== string::npos
)
2853 // This is the start of the field.
2854 string field
= txt
.substr (ix
+ prefix
.size ());
2856 // Find the end of the field.
2857 ix
= field
.find('"');
2858 if (ix
!= string::npos
)
2859 field
= field
.substr (0, ix
);
2865 void resolve_callback(
2866 AvahiServiceResolver
*r
,
2867 AVAHI_GCC_UNUSED AvahiIfIndex interface
,
2868 AVAHI_GCC_UNUSED AvahiProtocol protocol
,
2869 AvahiResolverEvent event
,
2873 const char *host_name
,
2874 const AvahiAddress
*address
,
2876 AvahiStringList
*txt
,
2877 AvahiLookupResultFlags
/*flags*/,
2878 AVAHI_GCC_UNUSED
void* userdata
) {
2881 const browsing_context
*context
= (browsing_context
*)userdata
;
2882 vector
<compile_server_info
> *servers
= context
->servers
;
2884 // Called whenever a service has been resolved successfully or timed out.
2887 case AVAHI_RESOLVER_FAILURE
:
2888 clog
<< _F("Failed to resolve service '%s' of type '%s' in domain '%s': %s",
2890 avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r
)))) << endl
;
2893 case AVAHI_RESOLVER_FOUND
: {
2894 char a
[AVAHI_ADDRESS_STR_MAX
], *t
;
2895 avahi_address_snprint(a
, sizeof(a
), address
);
2897 // Ignore entries using IPv6 addresses for now
2898 vector
<string
> parts
;
2899 tokenize (a
, parts
, ".");
2900 if (parts
.size () == 4)
2902 // Save the information of interest.
2903 compile_server_info info
;
2904 info
.host_name
= host_name
;
2905 info
.ip_address
= strdup (a
);
2907 t
= avahi_string_list_to_string(txt
);
2908 info
.sysinfo
= extract_field_from_avahi_txt ("sysinfo=", t
);
2909 info
.certinfo
= extract_field_from_avahi_txt ("certinfo=", t
);
2910 info
.version
= extract_field_from_avahi_txt ("version=", t
);
2911 if (info
.version
.empty ())
2912 info
.version
= "1.0"; // default version is 1.0
2915 // Add this server to the list of discovered servers.
2916 add_server_info (info
, *servers
);
2921 avahi_service_resolver_free(r
);
2925 void browse_callback(
2926 AvahiServiceBrowser
*b
,
2927 AvahiIfIndex interface
,
2928 AvahiProtocol protocol
,
2929 AvahiBrowserEvent event
,
2933 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags
,
2936 browsing_context
*context
= (browsing_context
*)userdata
;
2937 AvahiClient
*c
= context
->client
;
2938 AvahiSimplePoll
*simple_poll
= context
->simple_poll
;
2941 // Called whenever a new services becomes available on the LAN or is removed from the LAN.
2944 case AVAHI_BROWSER_FAILURE
:
2945 clog
<< _F("Avahi browse failed: %s",
2946 avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b
))))
2948 avahi_simple_poll_quit(simple_poll
);
2951 case AVAHI_BROWSER_NEW
:
2952 // We ignore the returned resolver object. In the callback
2953 // function we free it. If the server is terminated before
2954 // the callback function is called the server will free
2955 // the resolver for us.
2956 if (!(avahi_service_resolver_new(c
, interface
, protocol
, name
, type
, domain
,
2957 AVAHI_PROTO_UNSPEC
, (AvahiLookupFlags
)0, resolve_callback
, context
))) {
2958 clog
<< _F("Failed to resolve service '%s': %s",
2959 name
, avahi_strerror(avahi_client_errno(c
))) << endl
;
2963 case AVAHI_BROWSER_REMOVE
:
2964 case AVAHI_BROWSER_ALL_FOR_NOW
:
2965 case AVAHI_BROWSER_CACHE_EXHAUSTED
:
2971 void client_callback(AvahiClient
*c
, AvahiClientState state
, AVAHI_GCC_UNUSED
void * userdata
) {
2973 browsing_context
*context
= (browsing_context
*)userdata
;
2974 AvahiSimplePoll
*simple_poll
= context
->simple_poll
;
2976 // Called whenever the client or server state changes.
2978 if (state
== AVAHI_CLIENT_FAILURE
) {
2979 clog
<< _F("Avahi Server connection failure: %s", avahi_strerror(avahi_client_errno(c
))) << endl
;
2980 avahi_simple_poll_quit(simple_poll
);
2985 void timeout_callback(AVAHI_GCC_UNUSED AvahiTimeout
*e
, AVAHI_GCC_UNUSED
void *userdata
) {
2986 browsing_context
*context
= (browsing_context
*)userdata
;
2987 AvahiSimplePoll
*simple_poll
= context
->simple_poll
;
2988 avahi_simple_poll_quit(simple_poll
);
2990 #endif // HAVE_AVAHI
2993 get_or_keep_online_server_info (
2994 systemtap_session
&s
,
2995 vector
<compile_server_info
> &servers
,
2999 // If we're filtering the list and it's already empty, then
3000 // there's nothing to do.
3001 if (keep
&& servers
.empty ())
3004 // We only need to obtain this once per session. This is a good thing(tm)
3005 // since obtaining this information is expensive.
3006 vector
<compile_server_info
>& online_servers
= cscache(s
)->online_servers
;
3007 if (online_servers
.empty ())
3009 // Maintain an empty entry to indicate that this search has been
3010 // performed, in case the search comes up empty.
3011 online_servers
.push_back (compile_server_info ());
3013 // Must predeclare these due to jumping on error to fail:
3015 vector
<compile_server_info
> raw_servers
;
3018 AvahiClient
*client
= NULL
;
3019 AvahiServiceBrowser
*sb
= NULL
;
3021 // Allocate main loop object.
3022 AvahiSimplePoll
*simple_poll
;
3023 if (!(simple_poll
= avahi_simple_poll_new()))
3025 clog
<< _("Failed to create Avahi simple poll object") << endl
;
3028 browsing_context context
;
3029 context
.simple_poll
= simple_poll
;
3030 context
.servers
= & raw_servers
;
3032 // Allocate a new Avahi client
3034 client
= avahi_client_new (avahi_simple_poll_get (simple_poll
),
3035 (AvahiClientFlags
)0,
3036 client_callback
, & context
, & error
);
3038 // Check whether creating the client object succeeded.
3041 clog
<< _F("Failed to create Avahi client: %s",
3042 avahi_strerror(error
)) << endl
;
3045 context
.client
= client
;
3047 // Create the service browser.
3048 if (!(sb
= avahi_service_browser_new (client
, AVAHI_IF_UNSPEC
,
3049 AVAHI_PROTO_UNSPEC
, "_stap._tcp",
3050 NULL
, (AvahiLookupFlags
)0,
3051 browse_callback
, & context
)))
3053 clog
<< _F("Failed to create Avahi service browser: %s",
3054 avahi_strerror(avahi_client_errno(client
))) << endl
;
3058 // Timeout after 2 seconds.
3060 avahi_simple_poll_get(simple_poll
)->timeout_new(
3061 avahi_simple_poll_get(simple_poll
),
3062 avahi_elapse_time(&tv
, 1000*2, 0),
3066 // Run the main loop.
3067 avahi_simple_poll_loop(simple_poll
);
3069 // Resolve each server discovered and eliminate duplicates.
3070 limit
= raw_servers
.size ();
3071 for (unsigned i
= 0; i
< limit
; ++i
)
3073 compile_server_info
&raw_server
= raw_servers
[i
];
3075 // Delete the domain, if it is '.local'
3076 string
&host_name
= raw_server
.host_name
;
3077 string::size_type dot_index
= host_name
.find ('.');
3078 assert (dot_index
!= 0);
3079 string domain
= host_name
.substr (dot_index
+ 1);
3080 if (domain
== "local")
3081 host_name
= host_name
.substr (0, dot_index
);
3083 // Add it to the list of servers, unless it is duplicate.
3084 resolve_host (s
, raw_server
, online_servers
);
3090 avahi_service_browser_free(sb
);
3093 avahi_client_free(client
);
3096 avahi_simple_poll_free(simple_poll
);
3097 #else // ! HAVE_AVAHI
3098 // Without Avahi, we can't detect online servers. Issue a warning.
3100 clog
<< _("Unable to detect online servers without avahi") << endl
;
3101 #endif // ! HAVE_AVAHI
3102 } // Server information is not cached.
3106 // Filter the existing vector by keeping the information in common with
3107 // the online_server vector.
3108 keep_common_server_info (online_servers
, servers
);
3112 // Add the information, but not duplicates.
3113 add_server_info (online_servers
, servers
);
3117 // Add server info to a list, avoiding duplicates. Merge information from
3118 // two duplicate items.
3121 const compile_server_info
&info
, vector
<compile_server_info
>& target
3128 for (vector
<compile_server_info
>::iterator i
= target
.begin ();
3134 // Duplicate. Merge the two items.
3135 merge_server_info (info
, *i
);
3140 target
.push_back (info
);
3143 // Add server info from one vector to another.
3146 const vector
<compile_server_info
> &source
,
3147 vector
<compile_server_info
> &target
3150 for (vector
<compile_server_info
>::const_iterator i
= source
.begin ();
3154 add_server_info (*i
, target
);
3158 // Filter the vector by keeping information in common with the item.
3160 keep_common_server_info (
3161 const compile_server_info
&info_to_keep
,
3162 vector
<compile_server_info
> &filtered_info
3165 assert (! info_to_keep
.empty ());
3167 // The vector may change size as we go. Be careful!!
3168 for (unsigned i
= 0; i
< filtered_info
.size (); /**/)
3170 // Retain empty entries.
3171 if (filtered_info
[i
].empty ())
3176 if (info_to_keep
== filtered_info
[i
])
3178 merge_server_info (info_to_keep
, filtered_info
[i
]);
3182 // The item does not match. Delete it.
3183 filtered_info
.erase (filtered_info
.begin () + i
);
3188 // Filter the second vector by keeping information in common with the first
3191 keep_common_server_info (
3192 const vector
<compile_server_info
> &info_to_keep
,
3193 vector
<compile_server_info
> &filtered_info
3196 // The vector may change size as we go. Be careful!!
3197 for (unsigned i
= 0; i
< filtered_info
.size (); /**/)
3199 // Retain empty entries.
3200 if (filtered_info
[i
].empty ())
3206 for (unsigned j
= 0; j
< info_to_keep
.size (); ++j
)
3208 if (filtered_info
[i
] == info_to_keep
[j
])
3210 merge_server_info (info_to_keep
[j
], filtered_info
[i
]);
3215 // If the item was not found. Delete it. Otherwise, advance to the next
3220 filtered_info
.erase (filtered_info
.begin () + i
);
3224 // Merge two compile server info items.
3227 const compile_server_info
&source
,
3228 compile_server_info
&target
3231 if (target
.host_name
.empty ())
3232 target
.host_name
= source
.host_name
;
3233 if (target
.ip_address
.empty ())
3234 target
.ip_address
= source
.ip_address
;
3235 if (target
.port
== 0)
3236 target
.port
= source
.port
;
3237 if (target
.sysinfo
.empty ())
3238 target
.sysinfo
= source
.sysinfo
;
3239 if (target
.version
.empty ())
3240 target
.version
= source
.version
;
3241 if (target
.certinfo
.empty ())
3242 target
.certinfo
= source
.certinfo
;
3245 #if 0 // not used right now
3246 // Merge compile server info from one item into a vector.
3249 const compile_server_info
&source
,
3250 vector
<compile_server_info
> &target
3253 for (vector
<compile_server_info
>::iterator i
= target
.begin ();
3258 merge_server_info (source
, *i
);
3262 // Merge compile server from one vector into another.
3265 const vector
<compile_server_info
> &source
,
3266 vector
<compile_server_info
> &target
3269 for (vector
<compile_server_info
>::const_iterator i
= source
.begin ();
3272 merge_server_info (*i
, target
);
3276 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */