2 Compile server client functions
3 Copyright (C) 2010-2014 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
11 // Completely disable the client if NSS is not available.
18 #include "stap-probe.h"
20 #include <sys/times.h>
31 #include <linux/limits.h>
35 #include <sys/socket.h>
39 #include <arpa/inet.h>
45 #include <avahi-client/client.h>
46 #include <avahi-client/lookup.h>
48 #include <avahi-common/simple-watch.h>
49 #include <avahi-common/malloc.h>
50 #include <avahi-common/error.h>
51 #include <avahi-common/timeval.h>
66 #include "nsscommon.h"
70 #define STAP_CSC_01 _("WARNING: The domain name, %s, does not match the DNS name(s) on the server certificate:\n")
71 #define STAP_CSC_02 _("could not find input file %s\n")
72 #define STAP_CSC_03 _("could not open input file %s\n")
73 #define STAP_CSC_04 _("Unable to open output file %s\n")
74 #define STAP_CSC_05 _("could not write to %s\n")
76 #define MOK_PUBLIC_CERT_NAME "signing_key.x509"
78 static PRIPv6Addr
©Address (PRIPv6Addr
&PRin6
, const in6_addr
&in6
);
79 static PRNetAddr
©NetAddr (PRNetAddr
&x
, const PRNetAddr
&y
);
80 bool operator!= (const PRNetAddr
&x
, const PRNetAddr
&y
);
81 bool operator== (const PRNetAddr
&x
, const PRNetAddr
&y
);
85 nsscommon_error (const char *msg
, int logit
__attribute ((unused
)))
87 clog
<< msg
<< endl
<< flush
;
90 // Information about compile servers.
91 struct compile_server_info
93 compile_server_info () : port(0), fully_specified(false)
95 memset (& address
, 0, sizeof (address
));
101 bool fully_specified
;
105 vector
<string
> mok_fingerprints
;
109 return this->host_name
.empty () && ! this->hasAddress () && certinfo
.empty ();
111 bool hasAddress () const
113 return this->address
.raw
.family
!= 0;
115 unsigned short setAddressPort (unsigned short port
)
117 if (this->address
.raw
.family
== PR_AF_INET
)
118 return this->address
.inet
.port
= htons (port
);
119 if (this->address
.raw
.family
== PR_AF_INET6
)
120 return this->address
.ipv6
.port
= htons (port
);
124 bool isComplete () const
126 return this->hasAddress () && port
!= 0;
129 bool operator== (const compile_server_info
&that
) const
131 // If one item or the other has only a name, and possibly a port specified,
132 // then allow a match by name and port only. This is so that the user can specify
133 // names which are returned by avahi, but are not dns resolvable.
134 // Otherwise, we will ignore the host_name.
135 if ((! this->hasAddress() && this->version
.empty () &&
136 this->sysinfo
.empty () && this->certinfo
.empty ()) ||
137 (! that
.hasAddress() && that
.version
.empty () &&
138 that
.sysinfo
.empty () && that
.certinfo
.empty ()))
140 if (this->host_name
!= that
.host_name
)
144 // Compare the other fields only if they have both been set.
145 if (this->hasAddress() && that
.hasAddress() &&
146 this->address
!= that
.address
)
148 if (this->port
!= 0 && that
.port
!= 0 &&
149 this->port
!= that
.port
)
151 if (! this->version
.empty () && ! that
.version
.empty () &&
152 this->version
!= that
.version
)
154 if (! this->sysinfo
.empty () && ! that
.sysinfo
.empty () &&
155 this->sysinfo
!= that
.sysinfo
)
157 if (! this->certinfo
.empty () && ! that
.certinfo
.empty () &&
158 this->certinfo
!= that
.certinfo
)
160 if (! this->mok_fingerprints
.empty () && ! that
.mok_fingerprints
.empty ()
161 && this->mok_fingerprints
!= that
.mok_fingerprints
)
164 return true; // They are equal
167 // Used to sort servers by preference for order of contact. The preferred server is
168 // "less" than the other one.
169 bool operator< (const compile_server_info
&that
) const
171 // Prefer servers with a later (higher) version number.
172 cs_protocol_version
this_version (this->version
.c_str ());
173 cs_protocol_version
that_version (that
.version
.c_str ());
174 return that_version
< this_version
;
178 ostream
&operator<< (ostream
&s
, const compile_server_info
&i
);
179 ostream
&operator<< (ostream
&s
, const vector
<compile_server_info
> &v
);
182 preferred_order (vector
<compile_server_info
> &servers
)
184 // Sort the given list of servers into the preferred order for contacting.
185 // Don't bother if there are less than 2 servers in the list.
186 if (servers
.size () < 2)
189 // Sort the list using compile_server_info::operator<
190 sort (servers
.begin (), servers
.end ());
193 struct resolved_host
// see also PR16326, PR16342
197 resolved_host(string chost_name
, PRNetAddr caddress
):
198 host_name(chost_name
), address(caddress
) {}
201 struct compile_server_cache
203 vector
<compile_server_info
> default_servers
;
204 vector
<compile_server_info
> specified_servers
;
205 vector
<compile_server_info
> trusted_servers
;
206 vector
<compile_server_info
> signing_servers
;
207 vector
<compile_server_info
> online_servers
;
208 vector
<compile_server_info
> all_servers
;
209 map
<string
,vector
<resolved_host
> > resolved_hosts
;
212 // For filtering queries.
213 enum compile_server_properties
{
214 compile_server_all
= 0x1,
215 compile_server_trusted
= 0x2,
216 compile_server_online
= 0x4,
217 compile_server_compatible
= 0x8,
218 compile_server_signer
= 0x10,
219 compile_server_specified
= 0x20
223 static compile_server_cache
* cscache(systemtap_session
& s
);
224 static void query_server_status (systemtap_session
&s
, const string
&status_string
);
226 static void get_server_info (systemtap_session
&s
, int pmask
, vector
<compile_server_info
> &servers
);
227 static void get_all_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
);
228 static void get_default_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
);
229 static void get_specified_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool no_default
= false);
230 static void get_or_keep_online_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
231 static void get_or_keep_trusted_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
232 static void get_or_keep_signing_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
233 static void get_or_keep_compatible_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
234 static void keep_common_server_info (const compile_server_info
&info_to_keep
, vector
<compile_server_info
> &filtered_info
);
235 static void keep_common_server_info (const vector
<compile_server_info
> &info_to_keep
, vector
<compile_server_info
> &filtered_info
);
236 static void keep_server_info_with_cert_and_port (systemtap_session
&s
, const compile_server_info
&server
, vector
<compile_server_info
> &servers
);
238 static void add_server_info (const compile_server_info
&info
, vector
<compile_server_info
>& list
);
239 static void add_server_info (const vector
<compile_server_info
> &source
, vector
<compile_server_info
> &target
);
240 static void merge_server_info (const compile_server_info
&source
, compile_server_info
&target
);
241 #if 0 // not used right now
242 static void merge_server_info (const compile_server_info
&source
, vector
<compile_server_info
> &target
);
243 static void merge_server_info (const vector
<compile_server_info
> &source
, vector
<compile_server_info
> &target
);
245 static void resolve_host (systemtap_session
& s
, compile_server_info
&server
, vector
<compile_server_info
> &servers
);
247 /* Exit error codes */
249 #define GENERAL_ERROR 1
250 #define CA_CERT_INVALID_ERROR 2
251 #define SERVER_CERT_EXPIRED_ERROR 3
253 // -----------------------------------------------------
254 // NSS related code used by the compile server client
255 // -----------------------------------------------------
256 static void add_server_trust (systemtap_session
&s
, const string
&cert_db_path
, vector
<compile_server_info
> &server_list
);
257 static void revoke_server_trust (systemtap_session
&s
, const string
&cert_db_path
, const vector
<compile_server_info
> &server_list
);
258 static void get_server_info_from_db (systemtap_session
&s
, vector
<compile_server_info
> &servers
, const string
&cert_db_path
);
260 static string
global_client_cert_db_path () {
261 return SYSCONFDIR
"/systemtap/ssl/client";
265 private_ssl_cert_db_path ()
267 return local_client_cert_db_path ();
271 global_ssl_cert_db_path ()
273 return global_client_cert_db_path ();
277 signing_cert_db_path ()
279 return SYSCONFDIR
"/systemtap/staprun";
282 /* Connection state. */
283 typedef struct connectionState_t
285 const char *hostName
;
287 const char *infileName
;
288 const char *outfileName
;
289 const char *trustNewServerMode
;
292 #if 0 /* No client authorization */
294 myPasswd(PK11SlotInfo
*info
, PRBool retry
, void *arg
)
296 char * passwd
= NULL
;
298 if ( (!retry
) && arg
)
299 passwd
= PORT_Strdup((char *)arg
);
305 /* Add the server's certificate to our database of trusted servers. */
307 trustNewServer (CERTCertificate
*serverCert
)
310 CERTCertTrust
*trust
= NULL
;
311 PK11SlotInfo
*slot
= NULL
;
313 /* Import the certificate. */
314 slot
= PK11_GetInternalKeySlot();
315 const char *nickname
= server_cert_nickname ();
316 secStatus
= PK11_ImportCert(slot
, serverCert
, CK_INVALID_HANDLE
, nickname
, PR_FALSE
);
317 if (secStatus
!= SECSuccess
)
320 /* Make it a trusted peer. */
321 trust
= (CERTCertTrust
*)PORT_ZAlloc(sizeof(CERTCertTrust
));
324 secStatus
= SECFailure
;
328 secStatus
= CERT_DecodeTrustString(trust
, "P,P,P");
329 if (secStatus
!= SECSuccess
)
332 secStatus
= CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), serverCert
, trust
);
336 PK11_FreeSlot (slot
);
342 /* Called when the server certificate verification fails. This gives us
343 the chance to trust the server anyway and add the certificate to the
346 badCertHandler(void *arg
, PRFileDesc
*sslSocket
)
349 PRErrorCode errorNumber
;
350 CERTCertificate
*serverCert
= NULL
;
352 PRArenaPool
*tmpArena
= NULL
;
353 CERTGeneralName
*nameList
, *current
;
354 char *expected
= NULL
;
355 const connectionState_t
*connectionState
= (connectionState_t
*)arg
;
357 errorNumber
= PR_GetError ();
360 case SSL_ERROR_BAD_CERT_DOMAIN
:
361 /* Since we administer our own client-side databases of trustworthy
362 certificates, we don't need the domain name(s) on the certificate to
363 match. If the cert is in our database, then we can trust it.
364 If we know the expected domain name, then issue a warning but,
365 in any case, accept the certificate. */
366 secStatus
= SECSuccess
;
368 expected
= SSL_RevealURL (sslSocket
);
369 if (expected
== NULL
|| *expected
== '\0')
372 fprintf (stderr
, STAP_CSC_01
, expected
);
374 /* List the DNS names from the server cert as part of the warning.
375 First, find the alt-name extension on the certificate. */
376 subAltName
.data
= NULL
;
377 serverCert
= SSL_PeerCertificate (sslSocket
);
378 secStatus
= CERT_FindCertExtension (serverCert
,
379 SEC_OID_X509_SUBJECT_ALT_NAME
,
381 if (secStatus
!= SECSuccess
|| ! subAltName
.data
)
383 fprintf (stderr
, _("Unable to find alt name extension on the server certificate\n"));
384 secStatus
= SECSuccess
; /* Not a fatal error */
388 // Now, decode the extension.
389 tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
392 fprintf (stderr
, _("Out of memory\n"));
393 SECITEM_FreeItem(& subAltName
, PR_FALSE
);
394 secStatus
= SECSuccess
; /* Not a fatal error here */
397 nameList
= CERT_DecodeAltNameExtension (tmpArena
, & subAltName
);
398 SECITEM_FreeItem(& subAltName
, PR_FALSE
);
401 fprintf (stderr
, _("Unable to decode alt name extension on server certificate\n"));
402 secStatus
= SECSuccess
; /* Not a fatal error */
406 /* List the DNS names from the server cert as part of the warning.
407 The names are in a circular list. */
411 /* Make sure this is a DNS name. */
412 if (current
->type
== certDNSName
)
414 fprintf (stderr
, " %.*s\n",
415 (int)current
->name
.other
.len
, current
->name
.other
.data
);
417 current
= CERT_GetNextGeneralName (current
);
419 while (current
!= nameList
);
423 case SEC_ERROR_CA_CERT_INVALID
:
424 /* The server's certificate is not trusted. Should we trust it? */
425 secStatus
= SECFailure
; /* Do not trust by default. */
426 if (! connectionState
->trustNewServerMode
)
429 /* Trust it for this session only? */
430 if (strcmp (connectionState
->trustNewServerMode
, "session") == 0)
432 secStatus
= SECSuccess
;
436 /* Trust it permanently? */
437 if (strcmp (connectionState
->trustNewServerMode
, "permanent") == 0)
439 /* The user wants to trust this server. Get the server's certificate so
440 and add it to our database. */
441 serverCert
= SSL_PeerCertificate (sslSocket
);
442 if (serverCert
!= NULL
)
444 secStatus
= trustNewServer (serverCert
);
449 secStatus
= SECFailure
; /* Do not trust this server */
454 PORT_Free (expected
);
456 PORT_FreeArena (tmpArena
, PR_FALSE
);
458 if (serverCert
!= NULL
)
460 CERT_DestroyCertificate (serverCert
);
467 setupSSLSocket (connectionState_t
*connectionState
)
469 PRFileDesc
*tcpSocket
;
470 PRFileDesc
*sslSocket
;
471 PRSocketOptionData socketOption
;
475 tcpSocket
= PR_OpenTCPSocket(connectionState
->addr
.raw
.family
);
476 if (tcpSocket
== NULL
)
479 /* Make the socket blocking. */
480 socketOption
.option
= PR_SockOpt_Nonblocking
;
481 socketOption
.value
.non_blocking
= PR_FALSE
;
483 prStatus
= PR_SetSocketOption(tcpSocket
, &socketOption
);
484 if (prStatus
!= PR_SUCCESS
)
487 /* Import the socket into the SSL layer. */
488 sslSocket
= SSL_ImportFD(NULL
, tcpSocket
);
492 /* Set configuration options. */
493 secStatus
= SSL_OptionSet(sslSocket
, SSL_SECURITY
, PR_TRUE
);
494 if (secStatus
!= SECSuccess
)
497 secStatus
= SSL_OptionSet(sslSocket
, SSL_HANDSHAKE_AS_CLIENT
, PR_TRUE
);
498 if (secStatus
!= SECSuccess
)
501 /* Set SSL callback routines. */
502 #if 0 /* no client authentication */
503 secStatus
= SSL_GetClientAuthDataHook(sslSocket
,
504 (SSLGetClientAuthData
)myGetClientAuthData
,
505 (void *)certNickname
);
506 if (secStatus
!= SECSuccess
)
509 #if 0 /* Use the default */
510 secStatus
= SSL_AuthCertificateHook(sslSocket
,
511 (SSLAuthCertificate
)myAuthCertificate
,
512 (void *)CERT_GetDefaultCertDB());
513 if (secStatus
!= SECSuccess
)
517 secStatus
= SSL_BadCertHook(sslSocket
, (SSLBadCertHandler
)badCertHandler
,
519 if (secStatus
!= SECSuccess
)
522 #if 0 /* No handshake callback */
523 secStatus
= SSL_HandshakeCallback(sslSocket
, myHandshakeCallback
, NULL
);
524 if (secStatus
!= SECSuccess
)
538 handle_connection (PRFileDesc
*sslSocket
, connectionState_t
*connectionState
)
543 PRFileDesc
*local_file_fd
;
545 SECStatus secStatus
= SECSuccess
;
547 #define READ_BUFFER_SIZE (60 * 1024)
549 /* If we don't have both the input and output file names, then we're
550 contacting this server only in order to establish trust. In this case send
551 0 as the file size and exit. */
552 if (! connectionState
->infileName
|| ! connectionState
->outfileName
)
554 numBytes
= htonl ((PRInt32
)0);
555 numBytes
= PR_Write (sslSocket
, & numBytes
, sizeof (numBytes
));
561 /* read and send the data. */
562 /* Try to open the local file named.
563 * If successful, then write it to the server
565 prStatus
= PR_GetFileInfo(connectionState
->infileName
, &info
);
566 if (prStatus
!= PR_SUCCESS
||
567 info
.type
!= PR_FILE_FILE
||
570 fprintf (stderr
, STAP_CSC_02
,
571 connectionState
->infileName
);
575 local_file_fd
= PR_Open(connectionState
->infileName
, PR_RDONLY
, 0);
576 if (local_file_fd
== NULL
)
578 fprintf (stderr
, STAP_CSC_03
, connectionState
->infileName
);
582 /* Send the file size first, so the server knows when it has the entire file. */
583 numBytes
= htonl ((PRInt32
)info
.size
);
584 numBytes
= PR_Write(sslSocket
, & numBytes
, sizeof (numBytes
));
587 PR_Close(local_file_fd
);
591 /* Transmit the local file across the socket. */
592 numBytes
= PR_TransmitFile(sslSocket
, local_file_fd
,
594 PR_TRANSMITFILE_KEEP_OPEN
,
595 PR_INTERVAL_NO_TIMEOUT
);
598 PR_Close(local_file_fd
);
602 PR_Close(local_file_fd
);
605 readBuffer
= (char *)PORT_Alloc(READ_BUFFER_SIZE
);
607 fprintf (stderr
, _("Out of memory\n"));
611 local_file_fd
= PR_Open(connectionState
->outfileName
, PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
,
612 PR_IRUSR
| PR_IWUSR
| PR_IRGRP
| PR_IWGRP
| PR_IROTH
);
613 if (local_file_fd
== NULL
)
615 fprintf (stderr
, STAP_CSC_04
, connectionState
->outfileName
);
620 // No need for PR_Read_Complete here, since we're already managing multiple
621 // reads to a fixed size buffer.
622 numBytes
= PR_Read (sslSocket
, readBuffer
, READ_BUFFER_SIZE
);
628 secStatus
= SECFailure
;
632 /* Write to output file */
633 numBytes
= PR_Write(local_file_fd
, readBuffer
, numBytes
);
636 fprintf (stderr
, STAP_CSC_05
, connectionState
->outfileName
);
637 secStatus
= SECFailure
;
643 PR_Close(local_file_fd
);
645 /* Caller closes the socket. */
649 /* make the connection.
652 do_connect (connectionState_t
*connectionState
)
654 PRFileDesc
*sslSocket
;
658 secStatus
= SECSuccess
;
660 /* Set up SSL secure socket. */
661 sslSocket
= setupSSLSocket (connectionState
);
662 if (sslSocket
== NULL
)
665 #if 0 /* no client authentication */
666 secStatus
= SSL_SetPKCS11PinArg(sslSocket
, password
);
667 if (secStatus
!= SECSuccess
)
671 secStatus
= SSL_SetURL(sslSocket
, connectionState
->hostName
);
672 if (secStatus
!= SECSuccess
)
675 prStatus
= PR_Connect(sslSocket
, & connectionState
->addr
, PR_INTERVAL_NO_TIMEOUT
);
676 if (prStatus
!= PR_SUCCESS
)
678 secStatus
= SECFailure
;
682 /* Established SSL connection, ready to send data. */
683 secStatus
= SSL_ResetHandshake(sslSocket
, /* asServer */ PR_FALSE
);
684 if (secStatus
!= SECSuccess
)
687 /* This is normally done automatically on the first I/O operation,
688 but doing it here catches any authentication problems early. */
689 secStatus
= SSL_ForceHandshake(sslSocket
);
690 if (secStatus
!= SECSuccess
)
693 // Connect to the server and make the request.
694 secStatus
= handle_connection(sslSocket
, connectionState
);
697 prStatus
= PR_Close(sslSocket
);
702 isIPv6LinkLocal (const PRNetAddr
&address
)
704 // Link-local addresses are members of the address block fe80::
705 if (address
.raw
.family
== PR_AF_INET6
&&
706 address
.ipv6
.ip
.pr_s6_addr
[0] == 0xfe && address
.ipv6
.ip
.pr_s6_addr
[1] == 0x80)
712 client_connect (const compile_server_info
&server
,
713 const char* infileName
, const char* outfileName
,
714 const char* trustNewServer
)
717 PRErrorCode errorNumber
;
719 int errCode
= GENERAL_ERROR
;
720 struct connectionState_t connectionState
;
722 // Set up a connection state for use by NSS error callbacks.
723 memset (& connectionState
, 0, sizeof (connectionState
));
724 connectionState
.hostName
= server
.host_name
.c_str ();
725 connectionState
.addr
= server
.address
;
726 connectionState
.infileName
= infileName
;
727 connectionState
.outfileName
= outfileName
;
728 connectionState
.trustNewServerMode
= trustNewServer
;
730 /* Some errors (see below) represent a situation in which trying again
731 should succeed. However, don't try forever. */
732 for (attempt
= 0; attempt
< 5; ++attempt
)
734 secStatus
= do_connect (& connectionState
);
735 if (secStatus
== SECSuccess
)
738 errorNumber
= PR_GetError ();
741 case PR_CONNECT_RESET_ERROR
:
742 /* Server was not ready. */
744 break; /* Try again */
745 case SEC_ERROR_EXPIRED_CERTIFICATE
:
746 /* The server's certificate has expired. It should
747 generate a new certificate. Return now and we'll try again. */
748 errCode
= SERVER_CERT_EXPIRED_ERROR
;
750 case SEC_ERROR_CA_CERT_INVALID
:
751 /* The server's certificate is not trusted. The exit code must
753 errCode
= CA_CERT_INVALID_ERROR
;
756 /* This error is fatal. */
765 compile_server_client::passes_0_4 ()
767 PROBE1(stap
, client__start
, &s
);
769 // arguments parsed; get down to business
770 if (s
.verbose
|| ! s
.auto_server_msgs
.empty ())
771 clog
<< _("Using a compile server.") << endl
;
773 struct tms tms_before
;
774 times (& tms_before
);
775 struct timeval tv_before
;
776 gettimeofday (&tv_before
, NULL
);
778 // Create the request package.
779 int rc
= initialize ();
780 assert_no_interrupts();
781 if (rc
!= 0) goto done
;
782 rc
= create_request ();
783 assert_no_interrupts();
784 if (rc
!= 0) goto done
;
785 rc
= package_request ();
786 assert_no_interrupts();
787 if (rc
!= 0) goto done
;
789 // Submit it to the server.
790 rc
= find_and_connect_to_server ();
791 assert_no_interrupts();
792 if (rc
!= 0) goto done
;
794 // Unpack and process the response.
795 rc
= unpack_response ();
796 assert_no_interrupts();
797 if (rc
!= 0) goto done
;
798 rc
= process_response ();
801 struct tms tms_after
;
803 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
804 struct timeval tv_after
;
805 gettimeofday (&tv_after
, NULL
);
807 #define TIMESPRINT "in " << \
808 (tms_after.tms_cutime + tms_after.tms_utime \
809 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
810 << (tms_after.tms_cstime + tms_after.tms_stime \
811 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
812 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
813 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
817 // Save the module, if necessary.
818 if (s
.last_pass
== 4)
819 s
.save_module
= true;
821 // Copy module to the current directory.
822 if (! pending_interrupts
)
826 string module_src_path
= s
.tmpdir
+ "/" + s
.module_filename();
827 string module_dest_path
= s
.module_filename();
828 copy_file (module_src_path
, module_dest_path
, s
.verbose
>= 3);
829 // Also copy the module signature, it it exists.
830 module_src_path
+= ".sgn";
831 if (file_exists (module_src_path
))
833 module_dest_path
+= ".sgn";
834 copy_file(module_src_path
, module_dest_path
, s
.verbose
>= 3);
837 // Print the name of the module
838 if (s
.last_pass
== 4)
840 cout
<< s
.module_filename() << endl
;
845 // syntax errors, if any, are already printed
848 string ws
= s
.winning_server
;
849 if (ws
== "") ws
= "?";
850 clog
<< _("Passes: via server ") << ws
<< " "
855 if (rc
&& !s
.dump_mode
)
857 clog
<< _("Passes: via server failed. Try again with another '-v' option.") << endl
;
860 PROBE1(stap
, client__end
, &s
);
865 // Initialize a client/server session.
867 compile_server_client::initialize ()
871 // Initialize session state
874 // Private location for server certificates.
875 private_ssl_dbs
.push_back (private_ssl_cert_db_path ());
877 // Additional public location.
878 public_ssl_dbs
.push_back (global_ssl_cert_db_path ());
880 // Create a temporary directory to package things in.
881 client_tmpdir
= s
.tmpdir
+ "/client";
882 rc
= create_dir (client_tmpdir
.c_str ());
885 const char* e
= strerror (errno
);
886 clog
<< _("ERROR: cannot create temporary directory (\"")
887 << client_tmpdir
<< "\"): " << e
894 // Create the request package.
896 compile_server_client::create_request ()
898 // Add the current protocol version.
899 int rc
= write_to_file (client_tmpdir
+ "/version", CURRENT_CS_PROTOCOL_VERSION
);
903 // Add the script file or script option
904 if (s
.script_file
!= "")
906 if (s
.script_file
== "-")
908 // Copy the script from stdin
909 string packaged_script_dir
= client_tmpdir
+ "/script";
910 rc
= create_dir (packaged_script_dir
.c_str ());
913 const char* e
= strerror (errno
);
914 clog
<< _("ERROR: cannot create temporary directory ")
915 << packaged_script_dir
<< ": " << e
919 rc
= ! copy_file("/dev/stdin", packaged_script_dir
+ "/-");
923 // Name the script in the packaged arguments.
924 rc
= add_package_arg ("script/-");
930 // Add the script to our package. This will also name the script
931 // in the packaged arguments.
932 rc
= include_file_or_directory ("script", s
.script_file
);
938 // Add -I paths. Skip the default directory.
939 if (s
.include_arg_start
!= -1)
941 unsigned limit
= s
.include_path
.size ();
942 for (unsigned i
= s
.include_arg_start
; i
< limit
; ++i
)
944 rc
= add_package_arg ("-I");
947 rc
= include_file_or_directory ("tapset", s
.include_path
[i
]);
953 // Add other options.
954 rc
= add_package_args ();
958 // Add the sysinfo file
959 string sysinfo
= "sysinfo: " + s
.kernel_release
+ " " + s
.architecture
;
960 rc
= write_to_file (client_tmpdir
+ "/sysinfo", sysinfo
);
964 // Add localization data
965 rc
= add_localization_variables();
967 // Add the machine owner key (MOK) fingerprints file, if needed.
968 if (! s
.mok_fingerprints
.empty())
970 ostringstream fingerprints
;
971 vector
<string
>::const_iterator it
;
972 for (it
= s
.mok_fingerprints
.begin(); it
!= s
.mok_fingerprints
.end();
974 fingerprints
<< *it
<< endl
;
976 rc
= write_to_file(client_tmpdir
+ "/mok_fingerprints",
985 // Add the arguments specified on the command line to the server request
986 // package, as appropriate.
988 compile_server_client::add_package_args ()
990 // stap arguments to be passed to the server.
992 unsigned limit
= s
.server_args
.size();
993 for (unsigned i
= 0; i
< limit
; ++i
)
995 rc
= add_package_arg (s
.server_args
[i
]);
1000 // Script arguments.
1001 limit
= s
.args
.size();
1003 rc
= add_package_arg ("--");
1006 for (unsigned i
= 0; i
< limit
; ++i
)
1008 rc
= add_package_arg (s
.args
[i
]);
1017 compile_server_client::add_package_arg (const string
&arg
)
1020 ostringstream fname
;
1021 fname
<< client_tmpdir
<< "/argv" << ++argc
;
1022 write_to_file (fname
.str (), arg
); // NB: No terminating newline
1026 // Symbolically link the given file or directory into the client's temp
1027 // directory under the given subdirectory.
1029 compile_server_client::include_file_or_directory (
1030 const string
&subdir
, const string
&path
1033 // Must predeclare these because we do use 'goto done' to
1034 // exit from error situations.
1035 vector
<string
> components
;
1039 // Canonicalize the given path and remove the leading /.
1041 char *cpath
= canonicalize_file_name (path
.c_str ());
1044 // It can not be canonicalized. Use the name relative to
1045 // the current working directory and let the server deal with it.
1047 if (getcwd (cwd
, sizeof (cwd
)) == NULL
)
1053 rpath
= string (cwd
) + "/" + path
;
1057 // It can be canonicalized. Use the canonicalized name and add this
1058 // file or directory to the request package.
1062 // Including / would require special handling in the code below and
1063 // is a bad idea anyway. Let's not allow it.
1067 clog
<< _F("%s resolves to %s\n", path
.c_str (), rpath
.c_str ());
1068 clog
<< _F("Unable to send %s to the server\n", path
.c_str ());
1072 // First create the requested subdirectory.
1073 name
= client_tmpdir
+ "/" + subdir
;
1074 rc
= create_dir (name
.c_str ());
1077 // Now create each component of the path within the sub directory.
1078 assert (rpath
[0] == '/');
1079 tokenize (rpath
.substr (1), components
, "/");
1080 assert (components
.size () >= 1);
1082 for (i
= 0; i
< components
.size() - 1; ++i
)
1084 if (components
[i
].empty ())
1085 continue; // embedded '//'
1086 name
+= "/" + components
[i
];
1087 rc
= create_dir (name
.c_str ());
1091 // Now make a symbolic link to the actual file or directory.
1092 assert (i
== components
.size () - 1);
1093 name
+= "/" + components
[i
];
1094 rc
= symlink (rpath
.c_str (), name
.c_str ());
1098 // Name this file or directory in the packaged arguments.
1099 rc
= add_package_arg (subdir
+ "/" + rpath
.substr (1));
1104 const char* e
= strerror (errno
);
1105 clog
<< "ERROR: unable to add "
1107 << " to temp directory as "
1108 << name
<< ": " << e
1114 // Add the localization variables to the server request
1117 compile_server_client::add_localization_variables()
1123 const set
<string
> &locVars
= localization_variables();
1124 set
<string
>::iterator it
;
1126 /* Note: We don't have to check for the contents of the environment
1127 * variables here, since they will be checked extensively on the
1130 for (it
= locVars
.begin(); it
!= locVars
.end(); it
++)
1132 char* var
= getenv((*it
).c_str());
1134 envVar
+= *it
+ "=" + (string
)var
+ "\n";
1136 fname
= client_tmpdir
+ "/locale";
1137 rc
= write_to_file(fname
, envVar
);
1141 // Package the client's temp directory into a form suitable for sending to the
1144 compile_server_client::package_request ()
1146 // Package up the temporary directory into a zip file.
1147 client_zipfile
= client_tmpdir
+ ".zip";
1148 string cmd
= "cd " + cmdstr_quoted(client_tmpdir
) + " && zip -qr "
1149 + cmdstr_quoted(client_zipfile
) + " *";
1150 vector
<string
> sh_cmd
{ "sh", "-c", cmd
};
1151 int rc
= stap_system (s
.verbose
, sh_cmd
);
1156 compile_server_client::find_and_connect_to_server ()
1158 // Accumulate info on the specified servers.
1159 vector
<compile_server_info
> specified_servers
;
1160 get_specified_server_info (s
, specified_servers
);
1162 // Examine the specified servers to make sure that each has been resolved
1163 // with a host name, ip address and port. If not, try to obtain this
1164 // information by examining online servers.
1165 vector
<compile_server_info
> server_list
;
1166 for (vector
<compile_server_info
>::const_iterator i
= specified_servers
.begin ();
1167 i
!= specified_servers
.end ();
1170 // If we have an ip address and were given a port number, then just use the one we've
1171 // been given. Otherwise, check for matching compatible online servers and try their
1172 // ip addresses and ports.
1173 if (i
->hasAddress() && i
->fully_specified
)
1174 add_server_info (*i
, server_list
);
1177 // Obtain a list of online servers.
1178 vector
<compile_server_info
> online_servers
;
1179 get_or_keep_online_server_info (s
, online_servers
, false/*keep*/);
1181 // If no specific server (port) has been specified,
1182 // then we'll need the servers to be
1183 // compatible and possibly trusted as signers as well.
1184 if (! i
->fully_specified
)
1186 get_or_keep_compatible_server_info (s
, online_servers
, true/*keep*/);
1187 if (! pr_contains (s
.privilege
, pr_stapdev
))
1188 get_or_keep_signing_server_info (s
, online_servers
, true/*keep*/);
1191 // Keep the ones (if any) which match our server.
1192 keep_common_server_info (*i
, online_servers
);
1194 // Add these servers (if any) to the server list.
1195 add_server_info (online_servers
, server_list
);
1199 // Did we identify any potential servers?
1200 unsigned limit
= server_list
.size ();
1203 clog
<< _("Unable to find a suitable compile server. [man stap-server]") << endl
;
1205 // Try to explain why.
1206 vector
<compile_server_info
> online_servers
;
1207 get_or_keep_online_server_info (s
, online_servers
, false/*keep*/);
1208 if (online_servers
.empty ())
1209 clog
<< _("No servers online to select from.") << endl
;
1212 clog
<< _("The following servers are online:") << endl
;
1213 clog
<< online_servers
;
1214 if (! specified_servers
.empty ())
1216 clog
<< _("The following servers were requested:") << endl
;
1217 clog
<< specified_servers
;
1221 string criteria
= "online,trusted,compatible";
1222 if (! pr_contains (s
.privilege
, pr_stapdev
))
1223 criteria
+= ",signer";
1224 clog
<< _F("No servers matched the selection criteria of %s.", criteria
.c_str())
1231 // Sort the list of servers into a preferred order.
1232 preferred_order (server_list
);
1234 // Now try each of the identified servers in turn.
1235 int rc
= compile_using_server (server_list
);
1237 return 0; // success!
1239 // If the error was that a server's cert was expired, try again. This is because the server
1240 // should generate a new cert which may be automatically trusted by us if it is our server.
1241 // Give the server a chance to do this before retrying.
1242 if (rc
== SERVER_CERT_EXPIRED_ERROR
)
1245 clog
<< _("The server's certificate was expired. Trying again") << endl
<< flush
;
1247 rc
= compile_using_server (server_list
);
1249 return 0; // success!
1252 // We were unable to use any available server
1253 clog
<< _("Unable to connect to a server.") << endl
;
1256 // This information is redundant at higher verbosity levels.
1257 clog
<< _("The following servers were tried:") << endl
;
1258 clog
<< server_list
;
1260 return 1; // Failure
1264 compile_server_client::compile_using_server (
1265 vector
<compile_server_info
> &servers
1268 // Make sure NSPR is initialized. Must be done before NSS is initialized
1271 // Attempt connection using each of the available client certificate
1272 // databases. Assume the server certificate is invalid until proven otherwise.
1273 PR_SetError (SEC_ERROR_CA_CERT_INVALID
, 0);
1274 vector
<string
> dbs
= private_ssl_dbs
;
1275 vector
<string
>::iterator i
= dbs
.end();
1276 dbs
.insert (i
, public_ssl_dbs
.begin (), public_ssl_dbs
.end ());
1277 int rc
= GENERAL_ERROR
; // assume failure
1278 bool serverCertExpired
= false;
1279 for (i
= dbs
.begin (); i
!= dbs
.end (); ++i
)
1281 // Make sure the database directory exists. It is not an error if it
1283 if (! file_exists (*i
))
1286 #if 0 // no client authentication for now.
1287 // Set our password function callback.
1288 PK11_SetPasswordFunc (myPasswd
);
1291 // Initialize the NSS libraries.
1292 const char *cert_dir
= i
->c_str ();
1293 SECStatus secStatus
= nssInit (cert_dir
);
1294 if (secStatus
!= SECSuccess
)
1296 // Message already issued.
1297 continue; // try next database
1300 // Enable all cipher suites.
1301 // SSL_ClearSessionCache is required for the new settings to take effect.
1302 /* Some NSS versions don't do this correctly in NSS_SetDomesticPolicy. */
1304 const PRUint16
*cipher
;
1305 for (cipher
= SSL_GetImplementedCiphers(); *cipher
!= 0; ++cipher
)
1306 SSL_CipherPolicySet(*cipher
, SSL_ALLOWED
);
1308 SSL_ClearSessionCache ();
1310 server_zipfile
= s
.tmpdir
+ "/server.zip";
1312 // Try each server in turn.
1313 for (vector
<compile_server_info
>::iterator j
= servers
.begin ();
1314 j
!= servers
.end ();
1317 // At a minimum we need an ip_address along with a port
1318 // number in order to contact the server.
1319 if (! j
->hasAddress() || j
->port
== 0)
1321 // Set the port within the address.
1322 j
->setAddressPort (j
->port
);
1325 clog
<< _F("Attempting SSL connection with %s\n"
1326 " using certificates from the database in %s\n",
1327 lex_cast(*j
).c_str(), cert_dir
);
1329 rc
= client_connect (*j
, client_zipfile
.c_str(), server_zipfile
.c_str (),
1330 NULL
/*trustNewServer_p*/);
1333 s
.winning_server
= lex_cast(*j
);
1337 // Server cert has expired. Try other servers and/or databases, but take note because
1338 // server should generate a new certificate. If no other servers succeed, we'll try again
1339 // in case the new cert works.
1340 if (rc
== SERVER_CERT_EXPIRED_ERROR
)
1342 serverCertExpired
= true;
1348 clog
<< _(" Unable to connect: ");
1350 // Additional information: if the address is IPv6 and is link-local, then it must
1352 if (isIPv6LinkLocal (j
->address
) && j
->address
.ipv6
.scope_id
== 0)
1354 clog
<< _(" The address is an IPv6 link-local address with no scope specifier.")
1360 // SSL_ClearSessionCache is required before shutdown for client applications.
1361 SSL_ClearSessionCache ();
1362 nssCleanup (cert_dir
);
1364 if (rc
== SECSuccess
)
1368 // Indicate whether a server cert was expired, so we can try again, if desired.
1371 if (serverCertExpired
)
1372 rc
= SERVER_CERT_EXPIRED_ERROR
;
1379 compile_server_client::unpack_response ()
1381 // Unzip the response package.
1382 server_tmpdir
= s
.tmpdir
+ "/server";
1383 vector
<string
> cmd
{ "unzip", "-qd", server_tmpdir
, server_zipfile
};
1384 int rc
= stap_system (s
.verbose
, cmd
);
1387 clog
<< _F("Unable to unzip the server response '%s'\n", server_zipfile
.c_str());
1391 // Determine the server protocol version.
1392 string filename
= server_tmpdir
+ "/version";
1393 if (file_exists (filename
))
1394 ::read_from_file (filename
, server_version
);
1396 // Warn about the shortcomings of this server, if it is down level.
1397 show_server_compatibility ();
1399 // If the server's response contains a systemtap temp directory, move
1400 // its contents to our temp directory.
1402 string filespec
= server_tmpdir
+ "/stap??????";
1404 clog
<< _F("Searching \"%s\"\n", filespec
.c_str());
1405 int r
= glob(filespec
.c_str (), 0, NULL
, & globbuf
);
1406 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1408 if (globbuf
.gl_pathc
> 1)
1410 clog
<< _("Incorrect number of files in server response") << endl
;
1415 assert (globbuf
.gl_pathc
== 1);
1416 string dirname
= globbuf
.gl_pathv
[0];
1418 clog
<< _(" found ") << dirname
<< endl
;
1420 filespec
= dirname
+ "/*";
1422 clog
<< _F("Searching \"%s\"\n", filespec
.c_str());
1423 int r
= glob(filespec
.c_str (), GLOB_PERIOD
, NULL
, & globbuf
);
1424 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1426 unsigned prefix_len
= dirname
.size () + 1;
1427 for (unsigned i
= 0; i
< globbuf
.gl_pathc
; ++i
)
1429 string oldname
= globbuf
.gl_pathv
[i
];
1430 if (oldname
.substr (oldname
.size () - 2) == "/." ||
1431 oldname
.substr (oldname
.size () - 3) == "/..")
1433 string newname
= s
.tmpdir
+ "/" + oldname
.substr (prefix_len
);
1435 clog
<< _F(" found %s -- linking from %s", oldname
.c_str(), newname
.c_str());
1436 rc
= symlink (oldname
.c_str (), newname
.c_str ());
1439 clog
<< _F("Unable to link '%s' to '%s':%s\n",
1440 oldname
.c_str(), newname
.c_str(), strerror(errno
));
1447 // If the server version is less that 1.6, remove the output line due to the synthetic
1448 // server-side -k. Look for a message containing the name of the temporary directory.
1449 // We can look for the English message since server versions before 1.6 do not support
1451 if (server_version
< "1.6")
1453 cmd
= { "sed", "-i", "/^Keeping temporary directory.*/ d", server_tmpdir
+ "/stderr" };
1454 stap_system (s
.verbose
, cmd
);
1457 // Remove the output line due to the synthetic server-side -p4
1458 cmd
= { "sed", "-i", "/^.*\\.ko$/ d", server_tmpdir
+ "/stdout" };
1459 stap_system (s
.verbose
, cmd
);
1462 globfree (& globbuf
);
1467 compile_server_client::process_response ()
1469 // Pick up the results of running stap on the server.
1470 string filename
= server_tmpdir
+ "/rc";
1472 int rc
= read_from_file (filename
, stap_rc
);
1477 if (s
.last_pass
>= 4)
1479 // The server should have returned a module.
1480 string filespec
= s
.tmpdir
+ "/*.ko";
1482 clog
<< _F("Searching \"%s\"\n", filespec
.c_str());
1485 int r
= glob(filespec
.c_str (), 0, NULL
, & globbuf
);
1486 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1488 if (globbuf
.gl_pathc
> 1)
1489 clog
<< _("Incorrect number of modules in server response") << endl
;
1492 assert (globbuf
.gl_pathc
== 1);
1493 string modname
= globbuf
.gl_pathv
[0];
1495 clog
<< _(" found ") << modname
<< endl
;
1497 // If a module name was not specified by the user, then set it to
1498 // be the one generated by the server.
1499 if (! s
.save_module
)
1501 vector
<string
> components
;
1502 tokenize (modname
, components
, "/");
1503 s
.module_name
= components
.back ();
1504 s
.module_name
.erase(s
.module_name
.size() - 3);
1507 // If a uprobes.ko module was returned, then make note of it.
1509 if (server_version
< "1.6")
1510 uprobes_ko
= s
.tmpdir
+ "/server/uprobes.ko";
1512 uprobes_ko
= s
.tmpdir
+ "/uprobes/uprobes.ko";
1514 if (file_exists (uprobes_ko
))
1516 s
.need_uprobes
= true;
1517 s
.uprobes_path
= uprobes_ko
;
1521 else if (s
.have_script
)
1525 clog
<< _("No module was returned by the server.") << endl
;
1529 globfree (& globbuf
);
1532 // If the server returned a MOK certificate, copy it to the user's
1533 // current directory.
1534 string server_MOK_public_cert
= s
.tmpdir
+ "/server/" MOK_PUBLIC_CERT_NAME
;
1535 if (file_exists (server_MOK_public_cert
))
1537 string dst
= MOK_PUBLIC_CERT_NAME
;
1538 copy_file (server_MOK_public_cert
, dst
, (s
.verbose
>= 3));
1541 // Output stdout and stderr.
1542 filename
= server_tmpdir
+ "/stderr";
1543 flush_to_stream (filename
, clog
);
1545 filename
= server_tmpdir
+ "/stdout";
1546 flush_to_stream (filename
, cout
);
1552 compile_server_client::read_from_file (const string
&fname
, int &data
)
1554 // C++ streams may not set errno in the even of a failure. However if we
1555 // set it to 0 before each operation and it gets set during the operation,
1556 // then we can use its value in order to determine what happened.
1558 ifstream
f (fname
.c_str ());
1561 clog
<< _F("Unable to open file '%s' for reading: ", fname
.c_str());
1570 clog
<< _F("Unable to read from file '%s': ", fname
.c_str());
1574 // NB: not necessary to f.close ();
1575 return 0; // Success
1579 clog
<< strerror (errno
) << endl
;
1581 clog
<< _("unknown error") << endl
;
1582 return 1; // Failure
1587 compile_server_client::write_to_file (const string
&fname
, const T
&data
)
1589 // C++ streams may not set errno in the even of a failure. However if we
1590 // set it to 0 before each operation and it gets set during the operation,
1591 // then we can use its value in order to determine what happened.
1593 ofstream
f (fname
.c_str ());
1596 clog
<< _F("Unable to open file '%s' for writing: ", fname
.c_str());
1605 clog
<< _F("Unable to write to file '%s': ", fname
.c_str());
1609 // NB: not necessary to f.close ();
1610 return 0; // Success
1614 clog
<< strerror (errno
) << endl
;
1616 clog
<< _("unknown error") << endl
;
1617 return 1; // Failure
1621 compile_server_client::flush_to_stream (const string
&fname
, ostream
&o
)
1623 // C++ streams may not set errno in the even of a failure. However if we
1624 // set it to 0 before each operation and it gets set during the operation,
1625 // then we can use its value in order to determine what happened.
1627 ifstream
f (fname
.c_str ());
1630 clog
<< _F("Unable to open file '%s' for reading: ", fname
.c_str());
1636 // NB: o << f.rdbuf() misbehaves for some reason, appearing to close o,
1637 // which is unfortunate if o == clog or cout.
1642 if (f
.eof ()) return 0; // normal exit
1643 if (! f
.good()) break;
1645 if (! o
.good()) break;
1648 // NB: not necessary to f.close ();
1652 clog
<< strerror (errno
) << endl
;
1654 clog
<< _("unknown error") << endl
;
1655 return 1; // Failure
1659 compile_server_client::show_server_compatibility () const
1661 // Locale sensitivity was added in version 1.6
1662 if (server_version
< "1.6")
1664 clog
<< _F("Server protocol version is %s\n", server_version
.v
);
1665 clog
<< _("The server does not use localization information passed by the client\n");
1669 // Issue a status message for when a server's trust is already in place.
1671 trust_already_in_place (
1672 const compile_server_info
&server
,
1673 const vector
<compile_server_info
> &server_list
,
1674 const string cert_db_path
,
1678 // What level of trust?
1680 if (cert_db_path
== signing_cert_db_path ())
1681 purpose
= _("as a module signer for all users");
1684 purpose
= _("as an SSL peer");
1685 if (cert_db_path
== global_ssl_cert_db_path ())
1686 purpose
+= _(" for all users");
1688 purpose
+= _(" for the current user");
1691 // Issue a message for each server in the list with the same certificate.
1692 unsigned limit
= server_list
.size ();
1693 for (unsigned i
= 0; i
< limit
; ++i
)
1695 if (server
.certinfo
!= server_list
[i
].certinfo
)
1697 clog
<< server_list
[i
] << _(" is already ");
1699 clog
<< _("untrusted ") << purpose
<< endl
;
1701 clog
<< _("trusted ") << purpose
<< endl
;
1705 // Add the given servers to the given database of trusted servers.
1708 systemtap_session
&s
,
1709 const string
&cert_db_path
,
1710 vector
<compile_server_info
> &server_list
1713 // Get a list of servers already trusted. This opens the database, so do it
1714 // before we open it for our own purposes.
1715 vector
<compile_server_info
> already_trusted
;
1716 get_server_info_from_db (s
, already_trusted
, cert_db_path
);
1718 // Make sure the given path exists.
1719 if (create_dir (cert_db_path
.c_str (), 0755) != 0)
1721 clog
<< _F("Unable to find or create the client certificate database directory %s: ", cert_db_path
.c_str());
1726 // Must predeclare this because of jumps to cleanup: below.
1727 vector
<string
> processed_certs
;
1729 // Make sure NSPR is initialized. Must be done before NSS is initialized
1732 // Initialize the NSS libraries -- read/write
1733 SECStatus secStatus
= nssInit (cert_db_path
.c_str (), 1/*readwrite*/);
1734 if (secStatus
!= SECSuccess
)
1736 // Message already issued.
1740 // Enable all cipher suites.
1741 // SSL_ClearSessionCache is required for the new settings to take effect.
1742 /* Some NSS versions don't do this correctly in NSS_SetDomesticPolicy. */
1744 const PRUint16
*cipher
;
1745 for (cipher
= SSL_GetImplementedCiphers(); *cipher
!= 0; ++cipher
)
1746 SSL_CipherPolicySet(*cipher
, SSL_ALLOWED
);
1748 SSL_ClearSessionCache ();
1750 // Iterate over the servers to become trusted. Contact each one and
1751 // add it to the list of trusted servers if it is not already trusted.
1752 // client_connect will issue any error messages.
1753 for (vector
<compile_server_info
>::iterator server
= server_list
.begin();
1754 server
!= server_list
.end ();
1757 // Trust is based on certificates. We need only add trust in the
1758 // same certificate once.
1760 // RHBZ 1075685: If the new server to be trusted is selected by address + port,
1761 // and there is no avahi assistance available, or the server is not known
1762 // to avahi, then its certificate serial number field will be empty. We
1763 // therefore have no basis for comparing it to the serial numbers on already-trusted
1764 // certificates. In this case, unconditionally contact the new server to obtain
1766 if (! server
->certinfo
.empty ())
1768 // We need not contact the server if it has already been processed.
1769 if (find (processed_certs
.begin (), processed_certs
.end (),
1770 server
->certinfo
) != processed_certs
.end ())
1772 processed_certs
.push_back (server
->certinfo
);
1774 // We need not contact the server if it is already trusted.
1775 if (find (already_trusted
.begin (), already_trusted
.end (), *server
) !=
1776 already_trusted
.end ())
1779 trust_already_in_place (*server
, server_list
, cert_db_path
, false/*revoking*/);
1784 // At a minimum we need an ip_address along with a port
1785 // number in order to contact the server.
1786 if (! server
->hasAddress() || server
->port
== 0)
1788 // Set the port within the address.
1789 server
->setAddressPort (server
->port
);
1791 int rc
= client_connect (*server
, NULL
, NULL
, "permanent");
1794 clog
<< _F("Unable to connect to %s", lex_cast(*server
).c_str()) << endl
;
1796 // Additional information: if the address is IPv6 and is link-local, then it must
1798 if (isIPv6LinkLocal (server
->address
) && server
->address
.ipv6
.scope_id
== 0)
1800 clog
<< _(" The address is an IPv6 link-local address with no scope specifier.")
1808 // SSL_ClearSessionCache is required before shutdown for client applications.
1809 SSL_ClearSessionCache ();
1810 nssCleanup (cert_db_path
.c_str ());
1812 // Make sure the database files are readable.
1814 string filespec
= cert_db_path
+ "/*.db";
1816 clog
<< _F("Searching \"%s\"\n", filespec
.c_str());
1817 int r
= glob (filespec
.c_str (), 0, NULL
, & globbuf
);
1818 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1820 for (unsigned i
= 0; i
< globbuf
.gl_pathc
; ++i
)
1822 string filename
= globbuf
.gl_pathv
[i
];
1824 clog
<< _(" found ") << filename
<< endl
;
1826 if (chmod (filename
.c_str (), 0644) != 0)
1828 s
.print_warning("Unable to change permissions on " + filename
+ ": ");
1835 // Remove the given servers from the given database of trusted servers.
1837 revoke_server_trust (
1838 systemtap_session
&s
,
1839 const string
&cert_db_path
,
1840 const vector
<compile_server_info
> &server_list
1843 // Make sure the given path exists.
1844 if (! file_exists (cert_db_path
))
1848 clog
<< _F("Certificate database '%s' does not exist",
1849 cert_db_path
.c_str()) << endl
;
1850 for (vector
<compile_server_info
>::const_iterator server
= server_list
.begin();
1851 server
!= server_list
.end ();
1853 trust_already_in_place (*server
, server_list
, cert_db_path
, true/*revoking*/);
1858 // Must predeclare these because of jumps to cleanup: below.
1859 CERTCertDBHandle
*handle
;
1860 PRArenaPool
*tmpArena
= NULL
;
1861 CERTCertList
*certs
= NULL
;
1862 CERTCertificate
*db_cert
;
1863 vector
<string
> processed_certs
;
1864 const char *nickname
;
1866 // Make sure NSPR is initialized. Must be done before NSS is initialized
1869 // Initialize the NSS libraries -- read/write
1870 SECStatus secStatus
= nssInit (cert_db_path
.c_str (), 1/*readwrite*/);
1871 if (secStatus
!= SECSuccess
)
1873 // Message already issued
1876 handle
= CERT_GetDefaultCertDB();
1878 // A memory pool to work in
1879 tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1882 clog
<< _("Out of memory:");
1887 // Iterate over the servers to become untrusted.
1888 nickname
= server_cert_nickname ();
1889 for (vector
<compile_server_info
>::const_iterator server
= server_list
.begin();
1890 server
!= server_list
.end ();
1893 // If the server's certificate serial number is unknown, then we can't
1894 // match it with one in the database.
1895 if (server
->certinfo
.empty ())
1898 // Trust is based on certificates. We need only revoke trust in the same
1899 // certificate once.
1900 if (find (processed_certs
.begin (), processed_certs
.end (),
1901 server
->certinfo
) != processed_certs
.end ())
1903 processed_certs
.push_back (server
->certinfo
);
1905 // Search the client-side database of trusted servers.
1906 db_cert
= PK11_FindCertFromNickname (nickname
, NULL
);
1909 // No trusted servers. Not an error, but issue a status message.
1911 trust_already_in_place (*server
, server_list
, cert_db_path
, true/*revoking*/);
1915 // Here, we have one cert with the desired nickname.
1916 // Now, we will attempt to get a list of ALL certs
1917 // with the same subject name as the cert we have. That list
1918 // should contain, at a minimum, the one cert we have already found.
1919 // If the list of certs is empty (NULL), the libraries have failed.
1920 certs
= CERT_CreateSubjectCertList (NULL
, handle
, & db_cert
->derSubject
,
1921 PR_Now (), PR_FALSE
);
1922 CERT_DestroyCertificate (db_cert
);
1925 clog
<< _F("Unable to query certificate database %s: ",
1926 cert_db_path
.c_str()) << endl
;
1927 PORT_SetError (SEC_ERROR_LIBRARY_FAILURE
);
1932 // Find the certificate matching the one belonging to our server.
1933 CERTCertListNode
*node
;
1934 for (node
= CERT_LIST_HEAD (certs
);
1935 ! CERT_LIST_END (node
, certs
);
1936 node
= CERT_LIST_NEXT (node
))
1938 // The certificate we're working with.
1939 db_cert
= node
->cert
;
1941 // Get the serial number.
1942 string serialNumber
= get_cert_serial_number (db_cert
);
1944 // Does the serial number match that of the current server?
1945 if (serialNumber
!= server
->certinfo
)
1946 continue; // goto next certificate
1948 // All is ok! Remove the certificate from the database.
1950 } // Loop over certificates in the database
1952 // Was a certificate matching the server found? */
1953 if (CERT_LIST_END (node
, certs
))
1955 // Not found. Server is already untrusted.
1957 trust_already_in_place (*server
, server_list
, cert_db_path
, true/*revoking*/);
1961 secStatus
= SEC_DeletePermCertificate (db_cert
);
1962 if (secStatus
!= SECSuccess
)
1964 clog
<< _F("Unable to remove certificate from %s: ",
1965 cert_db_path
.c_str()) << endl
;
1969 CERT_DestroyCertList (certs
);
1971 } // Loop over servers
1976 PORT_FreeArena (tmpArena
, PR_FALSE
);
1978 nssCleanup (cert_db_path
.c_str ());
1981 // Obtain information about servers from the certificates in the given database.
1983 get_server_info_from_db (
1984 systemtap_session
&s
,
1985 vector
<compile_server_info
> &servers
,
1986 const string
&cert_db_path
1989 // Make sure the given path exists.
1990 if (! file_exists (cert_db_path
))
1993 clog
<< _F("Certificate database '%s' does not exist.",
1994 cert_db_path
.c_str()) << endl
;
1998 // Make sure NSPR is initialized. Must be done before NSS is initialized
2001 // Initialize the NSS libraries -- readonly
2002 SECStatus secStatus
= nssInit (cert_db_path
.c_str ());
2003 if (secStatus
!= SECSuccess
)
2005 // Message already issued.
2009 // Must predeclare this because of jumps to cleanup: below.
2010 PRArenaPool
*tmpArena
= NULL
;
2011 CERTCertList
*certs
= get_cert_list_from_db (server_cert_nickname ());
2015 clog
<< _F("No certificate found in database %s", cert_db_path
.c_str ()) << endl
;
2019 // A memory pool to work in
2020 tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2023 clog
<< _("Out of memory:");
2027 for (CERTCertListNode
*node
= CERT_LIST_HEAD (certs
);
2028 ! CERT_LIST_END (node
, certs
);
2029 node
= CERT_LIST_NEXT (node
))
2031 compile_server_info server_info
;
2033 // The certificate we're working with.
2034 CERTCertificate
*db_cert
= node
->cert
;
2036 // Get the host name. It is in the alt-name extension of the
2039 subAltName
.data
= NULL
;
2040 secStatus
= CERT_FindCertExtension (db_cert
,
2041 SEC_OID_X509_SUBJECT_ALT_NAME
,
2043 if (secStatus
!= SECSuccess
|| ! subAltName
.data
)
2045 clog
<< _("Unable to find alt name extension on server certificate: ") << endl
;
2050 // Decode the extension.
2051 CERTGeneralName
*nameList
= CERT_DecodeAltNameExtension (tmpArena
, & subAltName
);
2052 SECITEM_FreeItem(& subAltName
, PR_FALSE
);
2055 clog
<< _("Unable to decode alt name extension on server certificate: ") << endl
;
2060 // We're interested in the first alternate name.
2061 assert (nameList
->type
== certDNSName
);
2062 server_info
.host_name
= string ((const char *)nameList
->name
.other
.data
,
2063 nameList
->name
.other
.len
);
2064 // Don't free nameList. It's part of the tmpArena.
2066 // Get the serial number.
2067 server_info
.certinfo
= get_cert_serial_number (db_cert
);
2069 // Our results will at a minimum contain this server.
2070 add_server_info (server_info
, servers
);
2072 // Augment the list by querying all online servers and keeping the ones
2073 // with the same cert serial number.
2074 vector
<compile_server_info
> online_servers
;
2075 get_or_keep_online_server_info (s
, online_servers
, false/*keep*/);
2076 keep_server_info_with_cert_and_port (s
, server_info
, online_servers
);
2077 add_server_info (online_servers
, servers
);
2082 CERT_DestroyCertList (certs
);
2084 PORT_FreeArena (tmpArena
, PR_FALSE
);
2086 nssCleanup (cert_db_path
.c_str ());
2089 // Utility Functions.
2090 //-----------------------------------------------------------------------
2091 ostream
&operator<< (ostream
&s
, const compile_server_info
&i
)
2093 // Don't print empty information
2098 if (! i
.host_name
.empty ())
2106 switch (i
.address
.raw
.family
)
2111 #define MAX_NETADDR_SIZE 46 // from the NSPR API reference.
2112 char buf
[MAX_NETADDR_SIZE
];
2113 prStatus
= PR_NetAddrToString(& i
.address
, buf
, sizeof (buf
));
2114 if (prStatus
== PR_SUCCESS
) {
2133 if (! i
.sysinfo
.empty ())
2134 s
<< i
.sysinfo
<< '"';
2138 if (! i
.version
.empty ())
2142 s
<< " certinfo=\"";
2143 if (! i
.certinfo
.empty ())
2144 s
<< i
.certinfo
<< '"';
2147 if (! i
.mok_fingerprints
.empty ())
2149 // FIXME: Yikes, this output is ugly. Perhaps the server output
2150 // needs a more structured approach.
2151 s
<< " mok_fingerprints=\"";
2152 vector
<string
>::const_iterator it
;
2153 for (it
= i
.mok_fingerprints
.begin (); it
!= i
.mok_fingerprints
.end ();
2156 if (it
!= i
.mok_fingerprints
.begin ())
2165 ostream
&operator<< (ostream
&s
, const vector
<compile_server_info
> &v
)
2167 // Indicate an empty list.
2168 if (v
.size () == 0 || (v
.size () == 1 && v
[0].empty()))
2169 s
<< "No Servers" << endl
;
2172 for (unsigned i
= 0; i
< v
.size(); ++i
)
2174 // Don't print empty items.
2183 copyNetAddr (PRNetAddr
&x
, const PRNetAddr
&y
)
2185 PRUint32 saveScope
= 0;
2187 // For IPv6 addresses, don't overwrite the scope_id of x unless x is uninitialized or it is 0.
2188 if (x
.raw
.family
== PR_AF_INET6
)
2189 saveScope
= x
.ipv6
.scope_id
;
2194 x
.ipv6
.scope_id
= saveScope
;
2200 operator== (const PRNetAddr
&x
, const PRNetAddr
&y
)
2202 // Same address family?
2203 if (x
.raw
.family
!= y
.raw
.family
)
2206 switch (x
.raw
.family
)
2209 // If both scope ids are set, compare them.
2210 if (x
.ipv6
.scope_id
!= 0 && y
.ipv6
.scope_id
!= 0 && x
.ipv6
.scope_id
!= y
.ipv6
.scope_id
)
2211 return false; // not equal
2212 // Scope is not a factor. Compare the address bits
2213 return memcmp (& x
.ipv6
.ip
, & y
.ipv6
.ip
, sizeof(x
.ipv6
.ip
)) == 0;
2215 return x
.inet
.ip
== y
.inet
.ip
;
2223 operator!= (const PRNetAddr
&x
, const PRNetAddr
&y
)
2229 copyAddress (PRIPv6Addr
&PRin6
, const in6_addr
&in6
)
2231 // The NSPR type is a typedef of struct in6_addr, but C++ won't let us copy it
2232 assert (sizeof (PRin6
) == sizeof (in6
));
2233 memcpy (& PRin6
, & in6
, sizeof (PRin6
));
2237 // Return the default server specification, used when none is given on the
2240 default_server_spec (const systemtap_session
&s
)
2242 // If --privilege=X has been used, where X is not stapdev,
2243 // the default is online,trusted,compatible,signer
2245 // the default is online,trusted,compatible
2247 // Having said that,
2248 // 'online' and 'compatible' will only succeed if we have avahi
2249 // 'trusted' and 'signer' will only succeed if we have NSS
2251 string working_string
= "online,trusted,compatible";
2252 if (! pr_contains (s
.privilege
, pr_stapdev
))
2253 working_string
+= ",signer";
2254 return working_string
;
2258 server_spec_to_pmask (const string
&server_spec
)
2260 // Construct a mask of the server properties that have been requested.
2261 // The available properties are:
2262 // trusted - servers which are trusted SSL peers.
2263 // online - online servers.
2264 // compatible - servers which compile for the current kernel release
2265 // and architecture.
2266 // signer - servers which are trusted module signers.
2267 // specified - servers which have been specified using --use-server=XXX.
2268 // If no servers have been specified, then this is
2269 // equivalent to --list-servers=trusted,online,compatible.
2270 // all - all trusted servers, trusted module signers,
2271 // servers currently online and specified servers.
2272 string working_spec
= server_spec
;
2273 vector
<string
> properties
;
2274 tokenize (working_spec
, properties
, ",");
2276 unsigned limit
= properties
.size ();
2277 for (unsigned i
= 0; i
< limit
; ++i
)
2279 const string
&property
= properties
[i
];
2280 // Tolerate (and ignore) empty properties.
2281 if (property
.empty ())
2283 if (property
== "all")
2285 pmask
|= compile_server_all
;
2287 else if (property
== "specified")
2289 pmask
|= compile_server_specified
;
2291 else if (property
== "trusted")
2293 pmask
|= compile_server_trusted
;
2295 else if (property
== "online")
2297 pmask
|= compile_server_online
;
2299 else if (property
== "compatible")
2301 pmask
|= compile_server_compatible
;
2303 else if (property
== "signer")
2305 pmask
|= compile_server_signer
;
2309 // XXX PR13274 needs-session to use print_warning()
2310 clog
<< _F("WARNING: unsupported compile server property: %s", property
.c_str())
2318 query_server_status (systemtap_session
&s
)
2320 unsigned limit
= s
.server_status_strings
.size ();
2321 for (unsigned i
= 0; i
< limit
; ++i
)
2322 query_server_status (s
, s
.server_status_strings
[i
]);
2326 query_server_status (systemtap_session
&s
, const string
&status_string
)
2328 // If this string is empty, then the default is "specified"
2329 string working_string
= status_string
;
2330 if (working_string
.empty ())
2331 working_string
= "specified";
2333 // If the query is "specified" and no servers have been specified
2334 // (i.e. --use-server not used or used with no argument), then
2335 // use the default query.
2336 // TODO: This may not be necessary. The underlying queries should handle
2337 // "specified" properly.
2338 if (working_string
== "specified" &&
2339 (s
.specified_servers
.empty () ||
2340 (s
.specified_servers
.size () == 1 && s
.specified_servers
[0].empty ())))
2341 working_string
= default_server_spec (s
);
2343 int pmask
= server_spec_to_pmask (working_string
);
2345 // Now obtain a list of the servers which match the criteria.
2346 vector
<compile_server_info
> raw_servers
;
2347 get_server_info (s
, pmask
, raw_servers
);
2349 // Augment the listing with as much information as possible by adding
2350 // information from known servers.
2351 vector
<compile_server_info
> servers
;
2352 get_all_server_info (s
, servers
);
2353 keep_common_server_info (raw_servers
, servers
);
2355 // Sort the list of servers into a preferred order.
2356 preferred_order (servers
);
2358 // Print the server information. Skip the empty entry at the head of the list.
2359 clog
<< _F("Systemtap Compile Server Status for '%s'", working_string
.c_str()) << endl
;
2361 unsigned limit
= servers
.size ();
2362 for (unsigned i
= 0; i
< limit
; ++i
)
2364 assert (! servers
[i
].empty ());
2365 // Don't list servers with no cert information. They may not actually
2367 // TODO: Could try contacting the server and obtaining its cert
2368 if (servers
[i
].certinfo
.empty ())
2370 clog
<< servers
[i
] << endl
;
2374 clog
<< _("No servers found") << endl
;
2377 // Add or remove trust of the servers specified on the command line.
2379 manage_server_trust (systemtap_session
&s
)
2381 // This function should do nothing if we don't have NSS.
2382 // Nothing to do if --trust-servers was not specified.
2383 if (s
.server_trust_spec
.empty ())
2386 // Break up and analyze the trust specification. Recognized components are:
2387 // ssl - trust the specified servers as ssl peers
2388 // signer - trust the specified servers as module signers
2389 // revoke - revoke the requested trust
2390 // all-users - apply/revoke the requested trust for all users
2391 // no-prompt - don't prompt the user for confirmation
2392 vector
<string
>components
;
2393 tokenize (s
.server_trust_spec
, components
, ",");
2395 bool signer
= false;
2396 bool revoke
= false;
2397 bool all_users
= false;
2398 bool no_prompt
= false;
2400 for (vector
<string
>::const_iterator i
= components
.begin ();
2401 i
!= components
.end ();
2406 else if (*i
== "signer")
2408 if (geteuid () != 0)
2410 clog
<< _("Only root can specify 'signer' on --trust-servers") << endl
;
2416 else if (*i
== "revoke")
2418 else if (*i
== "all-users")
2420 if (geteuid () != 0)
2422 clog
<< _("Only root can specify 'all-users' on --trust-servers") << endl
;
2428 else if (*i
== "no-prompt")
2431 s
.print_warning("Unrecognized server trust specification: " + *i
);
2436 // Make sure NSPR is initialized
2439 // Now obtain the list of specified servers.
2440 vector
<compile_server_info
> server_list
;
2441 get_specified_server_info (s
, server_list
, true/*no_default*/);
2443 // Did we identify any potential servers?
2444 unsigned limit
= server_list
.size ();
2447 clog
<< _("No servers identified for trust") << endl
;
2451 // Create a string representing the request in English.
2452 // If neither 'ssl' or 'signer' was specified, the default is 'ssl'.
2453 if (! ssl
&& ! signer
)
2455 ostringstream trustString
;
2458 trustString
<< _("as an SSL peer");
2460 trustString
<< _(" for all users");
2462 trustString
<< _(" for the current user");
2467 trustString
<< _(" and ");
2468 trustString
<< _("as a module signer for all users");
2471 // Prompt the user to confirm what's about to happen.
2475 clog
<< _("Revoking trust ");
2477 clog
<< _("Adding trust ");
2482 clog
<< _("Revoke trust ");
2484 clog
<< _("Add trust ");
2486 clog
<< _F("in the following servers %s", trustString
.str().c_str());
2490 for (unsigned i
= 0; i
< limit
; ++i
)
2491 clog
<< " " << server_list
[i
] << endl
;
2494 clog
<< "[y/N] " << flush
;
2496 // Only carry out the operation if the response is "yes"
2499 if (response
[0] != 'y' && response
[0] != 'Y')
2501 clog
<< _("Server trust unchanged") << endl
;
2506 // Now add/revoke the requested trust.
2507 string cert_db_path
;
2511 cert_db_path
= global_ssl_cert_db_path ();
2513 cert_db_path
= private_ssl_cert_db_path ();
2515 revoke_server_trust (s
, cert_db_path
, server_list
);
2517 add_server_trust (s
, cert_db_path
, server_list
);
2521 cert_db_path
= signing_cert_db_path ();
2523 revoke_server_trust (s
, cert_db_path
, server_list
);
2525 add_server_trust (s
, cert_db_path
, server_list
);
2529 static compile_server_cache
*
2530 cscache(systemtap_session
& s
)
2532 if (!s
.server_cache
)
2533 s
.server_cache
= new compile_server_cache();
2534 return s
.server_cache
;
2539 systemtap_session
&s
,
2541 vector
<compile_server_info
> &servers
2544 // Get information on compile servers matching the requested criteria.
2545 // The order of queries is significant. Accumulating queries must go first
2546 // followed by accumulating/filtering queries.
2548 if (((pmask
& compile_server_all
)))
2550 get_all_server_info (s
, servers
);
2553 // Add the specified servers, if requested
2554 if ((pmask
& compile_server_specified
))
2556 get_specified_server_info (s
, servers
);
2559 // Now filter or accumulate the list depending on whether a query has
2560 // already been made.
2561 if ((pmask
& compile_server_online
))
2563 get_or_keep_online_server_info (s
, servers
, keep
);
2566 if ((pmask
& compile_server_trusted
))
2568 get_or_keep_trusted_server_info (s
, servers
, keep
);
2571 if ((pmask
& compile_server_signer
))
2573 get_or_keep_signing_server_info (s
, servers
, keep
);
2576 if ((pmask
& compile_server_compatible
))
2578 get_or_keep_compatible_server_info (s
, servers
, keep
);
2583 // Get information about all online servers as well as servers trusted
2584 // as SSL peers and servers trusted as signers.
2586 get_all_server_info (
2587 systemtap_session
&s
,
2588 vector
<compile_server_info
> &servers
2591 // We only need to obtain this once per session. This is a good thing(tm)
2592 // since obtaining this information is expensive.
2593 vector
<compile_server_info
>& all_servers
= cscache(s
)->all_servers
;
2594 if (all_servers
.empty ())
2596 get_or_keep_online_server_info (s
, all_servers
, false/*keep*/);
2597 get_or_keep_trusted_server_info (s
, all_servers
, false/*keep*/);
2598 get_or_keep_signing_server_info (s
, all_servers
, false/*keep*/);
2602 clog
<< _("All known servers:") << endl
;
2603 clog
<< all_servers
;
2607 // Add the information, but not duplicates.
2608 add_server_info (all_servers
, servers
);
2612 get_default_server_info (
2613 systemtap_session
&s
,
2614 vector
<compile_server_info
> &servers
2618 clog
<< _("Using the default servers") << endl
;
2620 // We only need to obtain this once per session. This is a good thing(tm)
2621 // since obtaining this information is expensive.
2622 vector
<compile_server_info
>& default_servers
= cscache(s
)->default_servers
;
2623 if (default_servers
.empty ())
2625 // Get the required information.
2626 // get_server_info will add an empty entry at the beginning to indicate
2627 // that the search has been performed, in case the search comes up empty.
2628 int pmask
= server_spec_to_pmask (default_server_spec (s
));
2629 get_server_info (s
, pmask
, default_servers
);
2633 clog
<< _("Default servers are:") << endl
;
2634 clog
<< default_servers
;
2638 // Add the information, but not duplicates.
2639 add_server_info (default_servers
, servers
);
2643 isPort (const char *pstr
, compile_server_info
&server_info
)
2647 unsigned long p
= strtoul (pstr
, & estr
, 10);
2648 if (errno
!= 0 || *estr
!= '\0' || p
> USHRT_MAX
)
2650 clog
<< _F("Invalid port number specified: %s", pstr
) << endl
;
2653 server_info
.port
= p
;
2654 server_info
.fully_specified
= true;
2659 isIPv6 (const string
&server
, compile_server_info
&server_info
)
2661 // An IPv6 address is 8 hex components separated by colons.
2662 // One contiguous block of zero segments in the address may be elided using ::.
2663 // An interface may be specified by appending %IF_NAME to the address (e.g. %eth0).
2664 // A port may be specified by enclosing the ip address in [] and adding :<port>.
2665 // Allow a bracketed address without a port.
2666 assert (! server
.empty());
2668 string::size_type portIx
;
2669 if (server
[0] == '[')
2671 string::size_type endBracket
= server
.find (']');
2672 if (endBracket
== string::npos
)
2673 return false; // Not a valid IPv6 address
2674 // Extract the address.
2675 ip
= server
.substr (1, endBracket
- 1);
2676 portIx
= endBracket
+ 1;
2681 portIx
= string::npos
;
2684 // Find out how many components there are. The maximum is 8
2686 vector
<string
> components
;
2687 tokenize_full (ip
, components
, ":");
2688 if (components
.size() > 8)
2689 return false; // Not a valid IPv6 address
2691 // The components must be either hex values between 0 and 0xffff, or must be empty.
2692 // There can be only one empty component.
2694 for (unsigned i
= 0; i
< components
.size(); ++i
)
2696 if (components
[i
].empty())
2699 return false; // Not a valid IPv6 address
2701 // If it's the final component, see if it specifies the interface. If so, strip it from the
2702 // component in order to simplify parsing. It still remains as part of the original ip address
2704 if (i
== components
.size() - 1)
2706 size_t ix
= components
[i
].find ('%');
2707 if (ix
!= string::npos
)
2709 interface
= components
[i
].substr(ix
);
2710 components
[i
] = components
[i
].substr(0, ix
);
2713 // Skip leading zeroes.
2715 for (j
= 0; j
< components
[i
].size(); ++j
)
2717 if (components
[i
][j
] != '0')
2720 // Max of 4 hex digits
2721 if (components
[i
].size() - j
> 4)
2722 return false; // Not a valid IPv6 address
2723 for (/**/; j
< components
[i
].size(); ++j
)
2725 if (! isxdigit (components
[i
][j
]))
2726 return false; // Not a valid IPv6 address
2729 // If there is no empty component, then there must be exactly 8 components.
2730 if (! empty
&& components
.size() != 8)
2731 return false; // Not a valid IPv6 address
2733 // Try to convert the string to an address.
2734 PRStatus prStatus
= PR_StringToNetAddr (ip
.c_str(), & server_info
.address
);
2735 if (prStatus
!= PR_SUCCESS
)
2738 // Examine the optional port
2739 if (portIx
!= string::npos
)
2741 string port
= server
.substr (portIx
);
2742 if (port
.size() != 0)
2744 if (port
.size() < 2 || port
[0] != ':')
2745 return false; // Not a valid Port
2747 port
= port
.substr (1);
2748 if (! isPort (port
.c_str(), server_info
))
2749 return false; // not a valid port
2753 server_info
.port
= 0;
2755 return true; // valid IPv6 address.
2759 isIPv4 (const string
&server
, compile_server_info
&server_info
)
2761 // An IPv4 address is 4 decimal components separated by periods with an
2762 // additional optional decimal port separated from the address by a colon.
2763 assert (! server
.empty());
2765 // Find out how many components there are. The maximum is 8
2766 vector
<string
> components
;
2767 tokenize (server
, components
, ":");
2768 if (components
.size() > 2)
2769 return false; // Not a valid IPv4 address
2771 // Separate the address from the port (if any).
2774 if (components
.size() <= 1)
2777 addr
= components
[0];
2778 port
= components
[1];
2781 // Separate the address components.
2782 // There must be exactly 4 components.
2783 components
.clear ();
2784 tokenize (addr
, components
, ".");
2785 if (components
.size() != 4)
2786 return false; // Not a valid IPv4 address
2788 // The components must be decimal values between 0 and 255.
2789 for (unsigned i
= 0; i
< components
.size(); ++i
)
2791 if (components
[i
].empty())
2792 return false; // Not a valid IPv4 address
2795 long p
= strtol (components
[i
].c_str(), & estr
, 10);
2796 if (errno
!= 0 || *estr
!= '\0' || p
< 0 || p
> 255)
2797 return false; // Not a valid IPv4 address
2800 // Try to convert the string to an address.
2801 PRStatus prStatus
= PR_StringToNetAddr (addr
.c_str(), & server_info
.address
);
2802 if (prStatus
!= PR_SUCCESS
)
2805 // Examine the optional port
2806 if (! port
.empty ()) {
2807 if (! isPort (port
.c_str(), server_info
))
2808 return false; // not a valid port
2811 server_info
.port
= 0;
2813 return true; // valid IPv4 address.
2817 isCertSerialNumber (const string
&server
, compile_server_info
&server_info
)
2819 // This function assumes that we have already ruled out the server spec being an IPv6 address.
2820 // Certificate serial numbers are 5 fields separated by colons plus an optional 6th decimal
2821 // field specifying a port.
2822 assert (! server
.empty());
2823 string host
= server
;
2824 vector
<string
> components
;
2825 tokenize (host
, components
, ":");
2826 switch (components
.size ())
2829 if (! isPort (components
.back().c_str(), server_info
))
2830 return false; // not a valid port
2831 host
= host
.substr (0, host
.find_last_of (':'));
2834 server_info
.certinfo
= host
;
2837 return false; // not a cert serial number
2840 return true; // valid cert serial number and optional port
2844 isDomain (const string
&server
, compile_server_info
&server_info
)
2846 // Accept one or two components separated by a colon. The first will be the domain name and
2847 // the second must a port number.
2848 assert (! server
.empty());
2849 string host
= server
;
2850 vector
<string
> components
;
2851 tokenize (host
, components
, ":");
2852 switch (components
.size ())
2855 if (! isPort (components
.back().c_str(), server_info
))
2856 return false; // not a valid port
2857 host
= host
.substr (0, host
.find_last_of (':'));
2860 server_info
.host_name
= host
;
2863 return false; // not a valid domain name
2870 get_specified_server_info (
2871 systemtap_session
&s
,
2872 vector
<compile_server_info
> &servers
,
2876 // We only need to obtain this once per session. This is a good thing(tm)
2877 // since obtaining this information is expensive.
2878 vector
<compile_server_info
>& specified_servers
= cscache(s
)->specified_servers
;
2879 if (specified_servers
.empty ())
2881 // Maintain an empty entry to indicate that this search has been
2882 // performed, in case the search comes up empty.
2883 specified_servers
.push_back (compile_server_info ());
2885 // If --use-server was not specified at all, then return info for the
2886 // default server list.
2887 if (s
.specified_servers
.empty ())
2890 clog
<< _("No servers specified") << endl
;
2892 get_default_server_info (s
, specified_servers
);
2896 // Iterate over the specified servers. For each specification, add to
2897 // the list of servers.
2898 unsigned num_specified_servers
= s
.specified_servers
.size ();
2899 for (unsigned i
= 0; i
< num_specified_servers
; ++i
)
2901 string
&server
= s
.specified_servers
[i
];
2903 // If no specific server(s) specified, then use the default servers.
2904 if (server
.empty ())
2907 clog
<< _("No servers specified") << endl
;
2909 get_default_server_info (s
, specified_servers
);
2913 // Determine what has been specified. Servers may be specified by:
2915 // - certificate-serial-number{:port}
2916 // - IPv4-address{:port}
2917 // - IPv6-address{:port}
2918 // where items within {} are optional.
2919 // Check for IPv6 addresses first. It reduces the amount of checking necessary for
2920 // certificate serial numbers.
2921 compile_server_info server_info
;
2922 vector
<compile_server_info
> resolved_servers
;
2923 if (isIPv6 (server
, server_info
) || isIPv4 (server
, server_info
) ||
2924 isCertSerialNumber (server
, server_info
))
2926 // An address or cert serial number has been specified.
2927 // No resolution is needed.
2928 resolved_servers
.push_back (server_info
);
2930 else if (isDomain (server
, server_info
))
2932 // Try to resolve the given name.
2933 resolve_host (s
, server_info
, resolved_servers
);
2937 clog
<< _F("Invalid server specification for --use-server: %s", server
.c_str())
2942 // Now examine the server(s) identified and add them to the list of specified
2944 vector
<compile_server_info
> known_servers
;
2945 vector
<compile_server_info
> new_servers
;
2946 for (vector
<compile_server_info
>::iterator i
= resolved_servers
.begin();
2947 i
!= resolved_servers
.end();
2950 // If this item was fully specified, then just add it.
2951 if (i
->fully_specified
)
2952 add_server_info (*i
, new_servers
);
2954 // It was not fully specified, so we need additional info. Try
2955 // to get it by matching what we have against other known servers.
2956 if (known_servers
.empty ())
2957 get_all_server_info (s
, known_servers
);
2959 // See if this server spec matches that of a known server
2960 vector
<compile_server_info
> matched_servers
= known_servers
;
2961 keep_common_server_info (*i
, matched_servers
);
2963 // If this server spec matches one or more known servers, then add the
2964 // augmented info to the specified_servers. Otherwise, if this server
2965 // spec is complete, then add it directly. Otherwise this server spec
2967 if (! matched_servers
.empty())
2968 add_server_info (matched_servers
, new_servers
);
2969 else if (i
->isComplete ())
2970 add_server_info (*i
, new_servers
);
2971 else if (s
.verbose
>= 3)
2972 clog
<< _("Incomplete server spec: ") << *i
<< endl
;
2978 clog
<< _F("Servers matching %s: ", server
.c_str()) << endl
;
2979 clog
<< new_servers
;
2982 // Add the newly identified servers to the list.
2983 if (! new_servers
.empty())
2984 add_server_info (new_servers
, specified_servers
);
2985 } // Loop over --use-server options
2986 } // -- use-server specified
2990 clog
<< _("All specified servers:") << endl
;
2991 clog
<< specified_servers
;
2993 } // Server information is not cached
2995 // Add the information, but not duplicates.
2996 add_server_info (specified_servers
, servers
);
3000 get_or_keep_trusted_server_info (
3001 systemtap_session
&s
,
3002 vector
<compile_server_info
> &servers
,
3006 // If we're filtering the list and it's already empty, then
3007 // there's nothing to do.
3008 if (keep
&& servers
.empty ())
3011 // We only need to obtain this once per session. This is a good thing(tm)
3012 // since obtaining this information is expensive.
3013 vector
<compile_server_info
>& trusted_servers
= cscache(s
)->trusted_servers
;
3014 if (trusted_servers
.empty ())
3016 // Maintain an empty entry to indicate that this search has been
3017 // performed, in case the search comes up empty.
3018 trusted_servers
.push_back (compile_server_info ());
3020 // Check the private database first.
3021 string cert_db_path
= private_ssl_cert_db_path ();
3022 get_server_info_from_db (s
, trusted_servers
, cert_db_path
);
3024 // Now check the global database.
3025 cert_db_path
= global_ssl_cert_db_path ();
3026 get_server_info_from_db (s
, trusted_servers
, cert_db_path
);
3030 clog
<< _("All servers trusted as ssl peers:") << endl
;
3031 clog
<< trusted_servers
;
3033 } // Server information is not cached
3037 // Filter the existing vector by keeping the information in common with
3038 // the trusted_server vector.
3039 keep_common_server_info (trusted_servers
, servers
);
3043 // Add the information, but not duplicates.
3044 add_server_info (trusted_servers
, servers
);
3049 get_or_keep_signing_server_info (
3050 systemtap_session
&s
,
3051 vector
<compile_server_info
> &servers
,
3055 // If we're filtering the list and it's already empty, then
3056 // there's nothing to do.
3057 if (keep
&& servers
.empty ())
3060 // We only need to obtain this once per session. This is a good thing(tm)
3061 // since obtaining this information is expensive.
3062 vector
<compile_server_info
>& signing_servers
= cscache(s
)->signing_servers
;
3063 if (signing_servers
.empty ())
3065 // Maintain an empty entry to indicate that this search has been
3066 // performed, in case the search comes up empty.
3067 signing_servers
.push_back (compile_server_info ());
3069 // For all users, check the global database.
3070 string cert_db_path
= signing_cert_db_path ();
3071 get_server_info_from_db (s
, signing_servers
, cert_db_path
);
3075 clog
<< _("All servers trusted as module signers:") << endl
;
3076 clog
<< signing_servers
;
3078 } // Server information is not cached
3082 // Filter the existing vector by keeping the information in common with
3083 // the signing_server vector.
3084 keep_common_server_info (signing_servers
, servers
);
3088 // Add the information, but not duplicates.
3089 add_server_info (signing_servers
, servers
);
3095 get_or_keep_compatible_server_info (
3096 systemtap_session
&s
,
3097 vector
<compile_server_info
> &servers
,
3102 // If we're filtering the list and it's already empty, then
3103 // there's nothing to do.
3104 if (keep
&& servers
.empty ())
3107 // Remove entries for servers incompatible with the host environment
3108 // from the given list of servers.
3109 // A compatible server compiles for the kernel release and architecture
3110 // of the host environment.
3112 // Compatibility can only be determined for online servers. So, augment
3113 // and filter the information we have with information for online servers.
3114 vector
<compile_server_info
> online_servers
;
3115 get_or_keep_online_server_info (s
, online_servers
, false/*keep*/);
3117 keep_common_server_info (online_servers
, servers
);
3119 add_server_info (online_servers
, servers
);
3121 // Now look to see which ones are compatible.
3122 // The vector can change size as we go, so be careful!!
3123 for (unsigned i
= 0; i
< servers
.size (); /**/)
3125 // Retain empty entries.
3126 assert (! servers
[i
].empty ());
3128 // Check the target of the server.
3129 if (servers
[i
].sysinfo
!= s
.kernel_release
+ " " + s
.architecture
)
3131 // Target platform mismatch.
3132 servers
.erase (servers
.begin () + i
);
3136 // If the client requires secure boot signing, make sure the
3137 // server has the right MOK.
3138 if (! s
.mok_fingerprints
.empty ())
3140 // This server has no MOKs.
3141 if (servers
[i
].mok_fingerprints
.empty ())
3143 servers
.erase (servers
.begin () + i
);
3147 // Make sure the server has at least one MOK in common with
3149 vector
<string
>::const_iterator it
;
3150 bool mok_found
= false;
3151 for (it
= s
.mok_fingerprints
.begin(); it
!= s
.mok_fingerprints
.end(); it
++)
3153 if (find(servers
[i
].mok_fingerprints
.begin(),
3154 servers
[i
].mok_fingerprints
.end(), *it
)
3155 != servers
[i
].mok_fingerprints
.end ())
3162 // This server has no MOK in common with the client.
3165 servers
.erase (servers
.begin () + i
);
3170 // The server is compatible. Leave it in the list.
3173 #else // ! HAVE_AVAHI
3174 // Without Avahi, we can't obtain the target platform of the server.
3177 clog
<< _("Unable to detect server compatibility without avahi") << endl
;
3184 keep_server_info_with_cert_and_port (
3185 systemtap_session
&,
3186 const compile_server_info
&server
,
3187 vector
<compile_server_info
> &servers
3190 assert (! server
.certinfo
.empty ());
3192 // Search the list of servers for ones matching the
3193 // serial number specified.
3194 // The vector can change size as we go, so be careful!!
3195 for (unsigned i
= 0; i
< servers
.size (); /**/)
3197 // Retain empty entries.
3198 if (servers
[i
].empty ())
3203 if (servers
[i
].certinfo
== server
.certinfo
&&
3204 (servers
[i
].port
== 0 || server
.port
== 0 ||
3205 servers
[i
].port
== server
.port
))
3207 // If the server is not online, then use the specified
3209 if (servers
[i
].port
== 0)
3211 servers
[i
].port
= server
.port
;
3212 servers
[i
].fully_specified
= server
.fully_specified
;
3217 // The item does not match. Delete it.
3218 servers
.erase (servers
.begin () + i
);
3222 // Obtain missing host name or ip address, if any. Return 0 on success.
3225 systemtap_session
& s
,
3226 compile_server_info
&server
,
3227 vector
<compile_server_info
> &resolved_servers
3230 vector
<resolved_host
>& cached_hosts
= cscache(s
)->resolved_hosts
[server
.host_name
];
3231 if (cached_hosts
.empty ())
3233 // The server's host_name member is a string containing either a host name or an ip address.
3234 // Either is acceptable for lookup.
3235 const char *lookup_name
= server
.host_name
.c_str();
3237 clog
<< _F("Looking up %s", lookup_name
) << endl
;
3239 struct addrinfo hints
;
3240 memset(& hints
, 0, sizeof (hints
));
3241 hints
.ai_family
= AF_UNSPEC
; // AF_INET or AF_INET6 to force version
3242 struct addrinfo
*addr_info
= 0;
3243 int rc
= getaddrinfo (lookup_name
, NULL
, & hints
, & addr_info
);
3245 // Failure to resolve will result in an appropriate message later, if other methods fail.
3249 clog
<< _F("%s not found: %s", lookup_name
, gai_strerror (rc
)) << endl
;
3253 // Loop over the results collecting information.
3255 for (const struct addrinfo
*ai
= addr_info
; ai
!= NULL
; ai
= ai
->ai_next
)
3257 PRNetAddr new_address
;
3259 // We support IPv4 and IPv6, Ignore other protocols,
3260 if (ai
->ai_family
== AF_INET
)
3263 struct sockaddr_in
*ip
= (struct sockaddr_in
*)ai
->ai_addr
;
3264 new_address
.inet
.family
= PR_AF_INET
;
3265 new_address
.inet
.ip
= ip
->sin_addr
.s_addr
;
3267 else if (ai
->ai_family
== AF_INET6
)
3270 struct sockaddr_in6
*ip
= (struct sockaddr_in6
*)ai
->ai_addr
;
3271 new_address
.ipv6
.family
= PR_AF_INET6
;
3272 new_address
.ipv6
.scope_id
= ip
->sin6_scope_id
;
3273 copyAddress (new_address
.ipv6
.ip
, ip
->sin6_addr
);
3278 // Try to obtain a host name. Otherwise, leave it empty.
3279 char hbuf
[NI_MAXHOST
];
3280 int status
= getnameinfo (ai
->ai_addr
, ai
->ai_addrlen
, hbuf
, sizeof (hbuf
), NULL
, 0,
3281 NI_NAMEREQD
| NI_IDN
);
3285 cached_hosts
.push_back(resolved_host(hbuf
, new_address
));
3289 freeaddrinfo (addr_info
); // free the linked list
3292 // If no addresses were resolved, then return the info we were given.
3293 if (cached_hosts
.empty())
3294 add_server_info (server
, resolved_servers
);
3296 // We will add a new server for each address resolved
3297 vector
<compile_server_info
> new_servers
;
3298 for (vector
<resolved_host
>::const_iterator it
= cached_hosts
.begin();
3299 it
!= cached_hosts
.end(); ++it
)
3301 // Start with the info we were given
3302 compile_server_info new_server
= server
;
3304 // NB: do not overwrite port info
3305 if (it
->address
.raw
.family
== AF_INET
)
3307 new_server
.address
.inet
.family
= PR_AF_INET
;
3308 new_server
.address
.inet
.ip
= it
->address
.inet
.ip
;
3312 new_server
.address
.ipv6
.family
= PR_AF_INET6
;
3313 new_server
.address
.ipv6
.scope_id
= it
->address
.ipv6
.scope_id
;
3314 new_server
.address
.ipv6
.ip
= it
->address
.ipv6
.ip
;
3316 if (!it
->host_name
.empty())
3317 new_server
.host_name
= it
->host_name
;
3318 add_server_info (new_server
, new_servers
);
3323 clog
<< _F("%s resolves to:", server
.host_name
.c_str()) << endl
;
3324 clog
<< new_servers
;
3327 add_server_info (new_servers
, resolved_servers
);
3332 // Avahi API Callbacks.
3333 //-----------------------------------------------------------------------
3334 struct browsing_context
{
3335 AvahiSimplePoll
*simple_poll
;
3336 AvahiClient
*client
;
3337 vector
<compile_server_info
> *servers
;
3340 // Get the value of the requested key from the Avahi string list.
3342 get_value_from_avahi_string_list (AvahiStringList
*strlst
, const string
&key
)
3344 AvahiStringList
*p
= avahi_string_list_find (strlst
, key
.c_str ());
3352 int rc
= avahi_string_list_get_pair(p
, &k
, &v
, NULL
);
3353 if (rc
< 0 || v
== NULL
)
3365 // Get a vector of values of the requested key from the Avahi string
3366 // list. This is for multiple values having the same key.
3368 get_values_from_avahi_string_list (AvahiStringList
*strlst
, const string
&key
,
3369 vector
<string
> &value_vector
)
3373 value_vector
.clear();
3374 p
= avahi_string_list_find (strlst
, key
.c_str ());
3375 for (; p
!= NULL
; p
= avahi_string_list_get_next(p
))
3378 int rc
= avahi_string_list_get_pair(p
, &k
, &v
, NULL
);
3379 if (rc
< 0 || v
== NULL
)
3385 value_vector
.push_back(v
);
3393 void resolve_callback(
3394 AvahiServiceResolver
*r
,
3395 AvahiIfIndex interface
,
3396 AvahiProtocol protocol
,
3397 AvahiResolverEvent event
,
3401 const char *host_name
,
3402 const AvahiAddress
*address
,
3404 AvahiStringList
*txt
,
3405 AvahiLookupResultFlags
/*flags*/,
3406 AVAHI_GCC_UNUSED
void* userdata
)
3411 const browsing_context
*context
= (browsing_context
*)userdata
;
3412 vector
<compile_server_info
> *servers
= context
->servers
;
3414 // Called whenever a service has been resolved successfully or timed out.
3417 case AVAHI_RESOLVER_FAILURE
:
3418 clog
<< _F("Failed to resolve service '%s' of type '%s' in domain '%s': %s",
3420 avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r
)))) << endl
;
3423 case AVAHI_RESOLVER_FOUND
: {
3424 compile_server_info info
;
3426 // Decode the address.
3427 char a
[AVAHI_ADDRESS_STR_MAX
];
3428 avahi_address_snprint(a
, sizeof(a
), address
);
3429 prStatus
= PR_StringToNetAddr (a
, & info
.address
);
3430 if (prStatus
!= PR_SUCCESS
) {
3431 clog
<< _F("Invalid address '%s' from avahi", a
) << endl
;
3435 // We support both IPv4 and IPv6. Ignore other protocols.
3436 if (protocol
== AVAHI_PROTO_INET6
) {
3437 info
.address
.ipv6
.family
= PR_AF_INET6
;
3438 info
.address
.ipv6
.scope_id
= interface
;
3441 else if (protocol
== AVAHI_PROTO_INET
) {
3442 info
.address
.inet
.family
= PR_AF_INET
;
3448 // Save the host name.
3449 info
.host_name
= host_name
;
3451 // Save the text tags.
3452 info
.sysinfo
= get_value_from_avahi_string_list (txt
, "sysinfo");
3453 info
.certinfo
= get_value_from_avahi_string_list (txt
, "certinfo");
3454 info
.version
= get_value_from_avahi_string_list (txt
, "version");
3455 if (info
.version
.empty ())
3456 info
.version
= "1.0"; // default version is 1.0
3458 // The server might provide one or more MOK certificate's
3460 get_values_from_avahi_string_list(txt
, "mok_info",
3461 info
.mok_fingerprints
);
3463 // Add this server to the list of discovered servers.
3464 add_server_info (info
, *servers
);
3471 avahi_service_resolver_free(r
);
3475 void browse_callback(
3476 AvahiServiceBrowser
*b
,
3477 AvahiIfIndex interface
,
3478 AvahiProtocol protocol
,
3479 AvahiBrowserEvent event
,
3483 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags
,
3486 browsing_context
*context
= (browsing_context
*)userdata
;
3487 AvahiClient
*c
= context
->client
;
3488 AvahiSimplePoll
*simple_poll
= context
->simple_poll
;
3491 // Called whenever a new services becomes available on the LAN or is removed from the LAN.
3494 case AVAHI_BROWSER_FAILURE
:
3495 clog
<< _F("Avahi browse failed: %s",
3496 avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b
))))
3498 avahi_simple_poll_quit(simple_poll
);
3501 case AVAHI_BROWSER_NEW
:
3502 // We ignore the returned resolver object. In the callback
3503 // function we free it. If the server is terminated before
3504 // the callback function is called the server will free
3505 // the resolver for us.
3506 if (!(avahi_service_resolver_new(c
, interface
, protocol
, name
, type
, domain
,
3507 AVAHI_PROTO_UNSPEC
, (AvahiLookupFlags
)0, resolve_callback
, context
))) {
3508 clog
<< _F("Failed to resolve service '%s': %s",
3509 name
, avahi_strerror(avahi_client_errno(c
))) << endl
;
3513 case AVAHI_BROWSER_REMOVE
:
3514 case AVAHI_BROWSER_ALL_FOR_NOW
:
3515 case AVAHI_BROWSER_CACHE_EXHAUSTED
:
3521 void client_callback(AvahiClient
*c
, AvahiClientState state
, AVAHI_GCC_UNUSED
void * userdata
) {
3523 browsing_context
*context
= (browsing_context
*)userdata
;
3524 AvahiSimplePoll
*simple_poll
= context
->simple_poll
;
3526 // Called whenever the client or server state changes.
3528 if (state
== AVAHI_CLIENT_FAILURE
) {
3529 clog
<< _F("Avahi Server connection failure: %s", avahi_strerror(avahi_client_errno(c
))) << endl
;
3530 avahi_simple_poll_quit(simple_poll
);
3535 void timeout_callback(AVAHI_GCC_UNUSED AvahiTimeout
*e
, AVAHI_GCC_UNUSED
void *userdata
) {
3536 browsing_context
*context
= (browsing_context
*)userdata
;
3537 AvahiSimplePoll
*simple_poll
= context
->simple_poll
;
3538 avahi_simple_poll_quit(simple_poll
);
3540 #endif // HAVE_AVAHI
3543 get_or_keep_online_server_info (
3544 systemtap_session
&s
,
3545 vector
<compile_server_info
> &servers
,
3549 // If we're filtering the list and it's already empty, then
3550 // there's nothing to do.
3551 if (keep
&& servers
.empty ())
3554 // We only need to obtain this once per session. This is a good thing(tm)
3555 // since obtaining this information is expensive.
3556 vector
<compile_server_info
>& online_servers
= cscache(s
)->online_servers
;
3557 if (online_servers
.empty ())
3559 // Maintain an empty entry to indicate that this search has been
3560 // performed, in case the search comes up empty.
3561 online_servers
.push_back (compile_server_info ());
3563 // Must predeclare these due to jumping on error to fail:
3564 vector
<compile_server_info
> avahi_servers
;
3567 AvahiClient
*client
= NULL
;
3568 AvahiServiceBrowser
*sb
= NULL
;
3570 // Allocate main loop object.
3571 AvahiSimplePoll
*simple_poll
;
3572 if (!(simple_poll
= avahi_simple_poll_new()))
3574 clog
<< _("Failed to create Avahi simple poll object") << endl
;
3577 browsing_context context
;
3578 context
.simple_poll
= simple_poll
;
3579 context
.servers
= & avahi_servers
;
3581 // Allocate a new Avahi client
3583 client
= avahi_client_new (avahi_simple_poll_get (simple_poll
),
3584 (AvahiClientFlags
)0,
3585 client_callback
, & context
, & error
);
3587 // Check whether creating the client object succeeded.
3590 clog
<< _F("Failed to create Avahi client: %s",
3591 avahi_strerror(error
)) << endl
;
3594 context
.client
= client
;
3596 // Create the service browser.
3597 if (!(sb
= avahi_service_browser_new (client
, AVAHI_IF_UNSPEC
,
3598 AVAHI_PROTO_UNSPEC
, "_stap._tcp",
3599 NULL
, (AvahiLookupFlags
)0,
3600 browse_callback
, & context
)))
3602 clog
<< _F("Failed to create Avahi service browser: %s",
3603 avahi_strerror(avahi_client_errno(client
))) << endl
;
3607 // Timeout after 0.5 seconds.
3609 avahi_simple_poll_get(simple_poll
)->timeout_new(
3610 avahi_simple_poll_get(simple_poll
),
3611 avahi_elapse_time(&tv
, 1000/2, 0),
3615 // Run the main loop.
3616 avahi_simple_poll_loop(simple_poll
);
3620 clog
<< _("Avahi reports the following servers online:") << endl
;
3621 clog
<< avahi_servers
;
3624 // Merge with the list of servers, as obtained by avahi.
3625 add_server_info (avahi_servers
, online_servers
);
3630 // Also frees the service browser
3631 avahi_client_free(client
);
3634 avahi_simple_poll_free(simple_poll
);
3635 #else // ! HAVE_AVAHI
3636 // Without Avahi, we can't detect online servers. Issue a warning.
3638 clog
<< _("Unable to detect online servers without avahi") << endl
;
3639 #endif // ! HAVE_AVAHI
3643 clog
<< _("All online servers:") << endl
;
3644 clog
<< online_servers
;
3646 } // Server information is not cached.
3650 // Filter the existing vector by keeping the information in common with
3651 // the online_server vector.
3652 keep_common_server_info (online_servers
, servers
);
3656 // Add the information, but not duplicates.
3657 add_server_info (online_servers
, servers
);
3661 // Add server info to a list, avoiding duplicates. Merge information from
3662 // two duplicate items.
3665 const compile_server_info
&info
, vector
<compile_server_info
>& target
3672 for (vector
<compile_server_info
>::iterator i
= target
.begin ();
3678 // Duplicate. Merge the two items.
3679 merge_server_info (info
, *i
);
3684 target
.push_back (info
);
3687 // Add server info from one vector to another.
3690 const vector
<compile_server_info
> &source
,
3691 vector
<compile_server_info
> &target
3694 for (vector
<compile_server_info
>::const_iterator i
= source
.begin ();
3698 add_server_info (*i
, target
);
3702 // Filter the vector by keeping information in common with the item.
3704 keep_common_server_info (
3705 const compile_server_info
&info_to_keep
,
3706 vector
<compile_server_info
> &filtered_info
3709 assert (! info_to_keep
.empty ());
3711 // The vector may change size as we go. Be careful!!
3712 for (unsigned i
= 0; i
< filtered_info
.size (); /**/)
3714 // Retain empty entries.
3715 if (filtered_info
[i
].empty ())
3720 if (info_to_keep
== filtered_info
[i
])
3722 merge_server_info (info_to_keep
, filtered_info
[i
]);
3726 // The item does not match. Delete it.
3727 filtered_info
.erase (filtered_info
.begin () + i
);
3732 // Filter the second vector by keeping information in common with the first
3735 keep_common_server_info (
3736 const vector
<compile_server_info
> &info_to_keep
,
3737 vector
<compile_server_info
> &filtered_info
3740 // The vector may change size as we go. Be careful!!
3741 for (unsigned i
= 0; i
< filtered_info
.size (); /**/)
3743 // Retain empty entries.
3744 if (filtered_info
[i
].empty ())
3750 for (unsigned j
= 0; j
< info_to_keep
.size (); ++j
)
3752 if (filtered_info
[i
] == info_to_keep
[j
])
3754 merge_server_info (info_to_keep
[j
], filtered_info
[i
]);
3759 // If the item was not found. Delete it. Otherwise, advance to the next
3764 filtered_info
.erase (filtered_info
.begin () + i
);
3768 // Merge two compile server info items.
3771 const compile_server_info
&source
,
3772 compile_server_info
&target
3775 // Copy the host name if the source has one.
3776 if (! source
.host_name
.empty())
3777 target
.host_name
= source
.host_name
;
3778 // Copy the address unconditionally, if the source has an address, even if they are already
3779 // equal. The source address may be an IPv6 address with a scope_id that the target is missing.
3780 assert (! target
.hasAddress () || ! source
.hasAddress () || source
.address
== target
.address
);
3781 if (source
.hasAddress ())
3782 copyNetAddr (target
.address
, source
.address
);
3783 if (target
.port
== 0)
3785 target
.port
= source
.port
;
3786 target
.fully_specified
= source
.fully_specified
;
3788 if (target
.sysinfo
.empty ())
3789 target
.sysinfo
= source
.sysinfo
;
3790 if (target
.version
.empty ())
3791 target
.version
= source
.version
;
3792 if (target
.certinfo
.empty ())
3793 target
.certinfo
= source
.certinfo
;
3796 #if 0 // not used right now
3797 // Merge compile server info from one item into a vector.
3800 const compile_server_info
&source
,
3801 vector
<compile_server_info
> &target
3804 for (vector
<compile_server_info
>::iterator i
= target
.begin ();
3809 merge_server_info (source
, *i
);
3813 // Merge compile server from one vector into another.
3816 const vector
<compile_server_info
> &source
,
3817 vector
<compile_server_info
> &target
3820 for (vector
<compile_server_info
>::const_iterator i
= source
.begin ();
3823 merge_server_info (*i
, target
);
3828 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */