2 Compile server client functions
3 Copyright (C) 2010-2011 Red Hat Inc.
5 This file is part of systemtap, and is free software. You can
6 redistribute it and/or modify it under the terms of the GNU General
7 Public License (GPL); either version 2, or (at your option) any
14 #include "stap-probe.h"
16 #include <sys/times.h>
27 #include <linux/limits.h>
31 #include <sys/socket.h>
34 #include <arpa/inet.h>
40 #include <avahi-client/client.h>
41 #include <avahi-client/lookup.h>
43 #include <avahi-common/simple-watch.h>
44 #include <avahi-common/malloc.h>
45 #include <avahi-common/error.h>
46 #include <avahi-common/timeval.h>
61 #include "nsscommon.h"
67 // Information about compile servers.
68 struct compile_server_info
70 compile_server_info () : port (0) {}
72 std::string host_name
;
73 std::string ip_address
;
80 return host_name
.empty () && ip_address
.empty ();
83 bool operator== (const compile_server_info
&that
) const
85 // If the ip address is not set, then the host names must match, otherwise
86 // the ip addresses must match.
87 if (this->ip_address
.empty () || that
.ip_address
.empty ())
89 if (this->host_name
!= that
.host_name
)
92 else if (this->ip_address
!= that
.ip_address
)
95 // Compare the other fields only if they have both been set.
96 if (this->port
!= 0 && that
.port
!= 0 && this->port
!= that
.port
)
98 if (! this->sysinfo
.empty () && ! that
.sysinfo
.empty () &&
99 this->sysinfo
!= that
.sysinfo
)
101 if (! this->certinfo
.empty () && ! that
.certinfo
.empty () &&
102 this->certinfo
!= that
.certinfo
)
108 ostream
&operator<< (ostream
&s
, const compile_server_info
&i
);
110 // For filtering queries.
111 enum compile_server_properties
{
112 compile_server_all
= 0x1,
113 compile_server_trusted
= 0x2,
114 compile_server_online
= 0x4,
115 compile_server_compatible
= 0x8,
116 compile_server_signer
= 0x10,
117 compile_server_specified
= 0x20
121 static void query_server_status (systemtap_session
&s
, const string
&status_string
);
123 static void get_server_info (systemtap_session
&s
, int pmask
, vector
<compile_server_info
> &servers
);
124 static void get_all_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
);
125 static void get_default_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
);
126 static void get_specified_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool no_default
= false);
127 static void get_or_keep_online_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
128 static void get_or_keep_trusted_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
129 static void get_or_keep_signing_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
130 static void get_or_keep_compatible_server_info (systemtap_session
&s
, vector
<compile_server_info
> &servers
, bool keep
);
131 static void keep_common_server_info (const compile_server_info
&info_to_keep
, vector
<compile_server_info
> &filtered_info
);
132 static void keep_common_server_info (const vector
<compile_server_info
> &info_to_keep
, vector
<compile_server_info
> &filtered_info
);
133 static void keep_server_info_with_cert_and_port (systemtap_session
&s
, const compile_server_info
&server
, vector
<compile_server_info
> &servers
);
135 static void add_server_info (const compile_server_info
&info
, vector
<compile_server_info
>& list
);
136 static void add_server_info (const vector
<compile_server_info
> &source
, vector
<compile_server_info
> &target
);
137 static void merge_server_info (const compile_server_info
&source
, compile_server_info
&target
);
138 #if 0 // not used right now
139 static void merge_server_info (const compile_server_info
&source
, vector
<compile_server_info
> &target
);
140 static void merge_server_info (const vector
<compile_server_info
> &source
, vector
<compile_server_info
> &target
);
142 static void resolve_host (systemtap_session
& s
, compile_server_info
&server
, vector
<compile_server_info
> &servers
);
145 // -----------------------------------------------------
146 // NSS related code used by the compile server client
147 // -----------------------------------------------------
148 static void add_server_trust (systemtap_session
&s
, const string
&cert_db_path
, const vector
<compile_server_info
> &server_list
);
149 static void revoke_server_trust (systemtap_session
&s
, const string
&cert_db_path
, const vector
<compile_server_info
> &server_list
);
150 static void get_server_info_from_db (systemtap_session
&s
, vector
<compile_server_info
> &servers
, const string
&cert_db_path
);
153 private_ssl_cert_db_path (const systemtap_session
&s
)
155 return s
.data_path
+ "/ssl/client";
159 global_ssl_cert_db_path ()
161 return SYSCONFDIR
"/systemtap/ssl/client";
165 signing_cert_db_path ()
167 return SYSCONFDIR
"/systemtap/staprun";
170 static const char *server_cert_nickname
= "stap-server";
172 /* Connection state. */
173 typedef struct connectionState_t
175 const char *hostName
;
178 const char *infileName
;
179 const char *outfileName
;
180 const char *trustNewServerMode
;
183 #if 0 /* No client authorization */
185 myPasswd(PK11SlotInfo
*info
, PRBool retry
, void *arg
)
187 char * passwd
= NULL
;
189 if ( (!retry
) && arg
)
190 passwd
= PORT_Strdup((char *)arg
);
196 /* Add the server's certificate to our database of trusted servers. */
198 trustNewServer (CERTCertificate
*serverCert
)
201 CERTCertTrust
*trust
= NULL
;
204 /* Import the certificate. */
205 slot
= PK11_GetInternalKeySlot();;
206 secStatus
= PK11_ImportCert(slot
, serverCert
, CK_INVALID_HANDLE
, "stap-server", PR_FALSE
);
207 if (secStatus
!= SECSuccess
)
210 /* Make it a trusted peer. */
211 trust
= (CERTCertTrust
*)PORT_ZAlloc(sizeof(CERTCertTrust
));
214 secStatus
= SECFailure
;
218 secStatus
= CERT_DecodeTrustString(trust
, "P,P,P");
219 if (secStatus
!= SECSuccess
)
222 secStatus
= CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), serverCert
, trust
);
223 if (secStatus
!= SECSuccess
)
232 /* Called when the server certificate verification fails. This gives us
233 the chance to trust the server anyway and add the certificate to the
236 badCertHandler(void *arg
, PRFileDesc
*sslSocket
)
239 PRErrorCode errorNumber
;
240 CERTCertificate
*serverCert
;
242 PRArenaPool
*tmpArena
= NULL
;
243 CERTGeneralName
*nameList
, *current
;
244 char *expected
= NULL
;
245 const connectionState_t
*connectionState
= (connectionState_t
*)arg
;
247 errorNumber
= PR_GetError ();
250 case SSL_ERROR_BAD_CERT_DOMAIN
:
251 /* Since we administer our own client-side databases of trustworthy
252 certificates, we don't need the domain name(s) on the certificate to
253 match. If the cert is in our database, then we can trust it.
254 Issue a warning and accept the certificate. */
255 expected
= SSL_RevealURL (sslSocket
);
256 fprintf (stderr
, "WARNING: The domain name, %s, does not match the DNS name(s) on the server certificate:\n", expected
);
258 /* List the DNS names from the server cert as part of the warning.
259 First, find the alt-name extension on the certificate. */
260 subAltName
.data
= NULL
;
261 serverCert
= SSL_PeerCertificate (sslSocket
);
262 secStatus
= CERT_FindCertExtension (serverCert
,
263 SEC_OID_X509_SUBJECT_ALT_NAME
,
265 if (secStatus
!= SECSuccess
|| ! subAltName
.data
)
267 fprintf (stderr
, "Unable to find alt name extension on the server certificate\n");
268 secStatus
= SECSuccess
; /* Not a fatal error */
272 // Now, decode the extension.
273 tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
276 fprintf (stderr
, "Out of memory\n");
277 secStatus
= SECSuccess
; /* Not a fatal error here */
280 nameList
= CERT_DecodeAltNameExtension (tmpArena
, & subAltName
);
281 SECITEM_FreeItem(& subAltName
, PR_FALSE
);
284 fprintf (stderr
, "Unable to decode alt name extension on server certificate\n");
285 secStatus
= SECSuccess
; /* Not a fatal error */
289 /* List the DNS names from the server cert as part of the warning.
290 The names are in a circular list. */
294 /* Make sure this is a DNS name. */
295 if (current
->type
== certDNSName
)
297 fprintf (stderr
, " %.*s\n",
298 (int)current
->name
.other
.len
, current
->name
.other
.data
);
300 current
= CERT_GetNextGeneralName (current
);
302 while (current
!= nameList
);
304 /* Accept the certificate */
305 secStatus
= SECSuccess
;
308 case SEC_ERROR_CA_CERT_INVALID
:
309 /* The server's certificate is not trusted. Should we trust it? */
310 secStatus
= SECFailure
; /* Do not trust by default. */
311 if (! connectionState
->trustNewServerMode
)
314 /* Trust it for this session only? */
315 if (strcmp (connectionState
->trustNewServerMode
, "session") == 0)
317 secStatus
= SECSuccess
;
321 /* Trust it permanently? */
322 if (strcmp (connectionState
->trustNewServerMode
, "permanent") == 0)
324 /* The user wants to trust this server. Get the server's certificate so
325 and add it to our database. */
326 serverCert
= SSL_PeerCertificate (sslSocket
);
327 if (serverCert
!= NULL
)
328 secStatus
= trustNewServer (serverCert
);
332 secStatus
= SECFailure
; /* Do not trust this server */
337 PORT_Free (expected
);
339 PORT_FreeArena (tmpArena
, PR_FALSE
);
345 setupSSLSocket (connectionState_t
*connectionState
)
347 PRFileDesc
*tcpSocket
;
348 PRFileDesc
*sslSocket
;
349 PRSocketOptionData socketOption
;
353 tcpSocket
= PR_NewTCPSocket();
354 if (tcpSocket
== NULL
)
357 /* Make the socket blocking. */
358 socketOption
.option
= PR_SockOpt_Nonblocking
;
359 socketOption
.value
.non_blocking
= PR_FALSE
;
361 prStatus
= PR_SetSocketOption(tcpSocket
, &socketOption
);
362 if (prStatus
!= PR_SUCCESS
)
365 /* Import the socket into the SSL layer. */
366 sslSocket
= SSL_ImportFD(NULL
, tcpSocket
);
370 /* Set configuration options. */
371 secStatus
= SSL_OptionSet(sslSocket
, SSL_SECURITY
, PR_TRUE
);
372 if (secStatus
!= SECSuccess
)
375 secStatus
= SSL_OptionSet(sslSocket
, SSL_HANDSHAKE_AS_CLIENT
, PR_TRUE
);
376 if (secStatus
!= SECSuccess
)
379 /* Set SSL callback routines. */
380 #if 0 /* no client authentication */
381 secStatus
= SSL_GetClientAuthDataHook(sslSocket
,
382 (SSLGetClientAuthData
)myGetClientAuthData
,
383 (void *)certNickname
);
384 if (secStatus
!= SECSuccess
)
387 #if 0 /* Use the default */
388 secStatus
= SSL_AuthCertificateHook(sslSocket
,
389 (SSLAuthCertificate
)myAuthCertificate
,
390 (void *)CERT_GetDefaultCertDB());
391 if (secStatus
!= SECSuccess
)
395 secStatus
= SSL_BadCertHook(sslSocket
, (SSLBadCertHandler
)badCertHandler
,
397 if (secStatus
!= SECSuccess
)
400 #if 0 /* No handshake callback */
401 secStatus
= SSL_HandshakeCallback(sslSocket
, myHandshakeCallback
, NULL
);
402 if (secStatus
!= SECSuccess
)
416 handle_connection (PRFileDesc
*sslSocket
, connectionState_t
*connectionState
)
421 PRFileDesc
*local_file_fd
;
423 SECStatus secStatus
= SECSuccess
;
425 #define READ_BUFFER_SIZE (60 * 1024)
427 /* read and send the data. */
428 /* Try to open the local file named.
429 * If successful, then write it to the server
431 prStatus
= PR_GetFileInfo(connectionState
->infileName
, &info
);
432 if (prStatus
!= PR_SUCCESS
||
433 info
.type
!= PR_FILE_FILE
||
436 fprintf (stderr
, "could not find input file %s\n",
437 connectionState
->infileName
);
441 local_file_fd
= PR_Open(connectionState
->infileName
, PR_RDONLY
, 0);
442 if (local_file_fd
== NULL
)
444 fprintf (stderr
, "could not open input file %s\n", connectionState
->infileName
);
448 /* Send the file size first, so the server knows when it has the entire file. */
449 numBytes
= htonl ((PRInt32
)info
.size
);
450 numBytes
= PR_Write(sslSocket
, & numBytes
, sizeof (numBytes
));
453 PR_Close(local_file_fd
);
457 /* Transmit the local file across the socket. */
458 numBytes
= PR_TransmitFile(sslSocket
, local_file_fd
,
460 PR_TRANSMITFILE_KEEP_OPEN
,
461 PR_INTERVAL_NO_TIMEOUT
);
464 PR_Close(local_file_fd
);
468 PR_Close(local_file_fd
);
471 readBuffer
= (char *)PORT_Alloc(READ_BUFFER_SIZE
);
473 fprintf (stderr
, "Out of memory\n");
477 local_file_fd
= PR_Open(connectionState
->outfileName
, PR_WRONLY
| PR_CREATE_FILE
| PR_TRUNCATE
,
478 PR_IRUSR
| PR_IWUSR
| PR_IRGRP
| PR_IWGRP
| PR_IROTH
);
479 if (local_file_fd
== NULL
)
481 fprintf (stderr
, "Unable to open output file %s\n", connectionState
->outfileName
);
486 numBytes
= PR_Read(sslSocket
, readBuffer
, READ_BUFFER_SIZE
);
492 secStatus
= SECFailure
;
496 /* Write to output file */
497 numBytes
= PR_Write(local_file_fd
, readBuffer
, numBytes
);
500 fprintf (stderr
, "could not write to %s\n", connectionState
->outfileName
);
501 secStatus
= SECFailure
;
507 PR_Close(local_file_fd
);
509 /* Caller closes the socket. */
513 /* make the connection.
516 do_connect (connectionState_t
*connectionState
)
518 PRFileDesc
*sslSocket
;
522 secStatus
= SECSuccess
;
524 /* Set up SSL secure socket. */
525 sslSocket
= setupSSLSocket (connectionState
);
526 if (sslSocket
== NULL
)
529 #if 0 /* no client authentication */
530 secStatus
= SSL_SetPKCS11PinArg(sslSocket
, password
);
531 if (secStatus
!= SECSuccess
)
535 secStatus
= SSL_SetURL(sslSocket
, connectionState
->hostName
);
536 if (secStatus
!= SECSuccess
)
539 prStatus
= PR_Connect(sslSocket
, & connectionState
->addr
, PR_INTERVAL_NO_TIMEOUT
);
540 if (prStatus
!= PR_SUCCESS
)
542 secStatus
= SECFailure
;
546 /* Established SSL connection, ready to send data. */
547 secStatus
= SSL_ResetHandshake(sslSocket
, /* asServer */ PR_FALSE
);
548 if (secStatus
!= SECSuccess
)
551 /* This is normally done automatically on the first I/O operation,
552 but doing it here catches any authentication problems early. */
553 secStatus
= SSL_ForceHandshake(sslSocket
);
554 if (secStatus
!= SECSuccess
)
557 /* If we don't have both the input and output file names, then we're
558 contacting this server only in order to establish trust. No need to
559 handle the connection in this case. */
560 if (connectionState
->infileName
&& connectionState
->outfileName
)
561 secStatus
= handle_connection(sslSocket
, connectionState
);
564 prStatus
= PR_Close(sslSocket
);
568 /* Exit error codes */
570 #define GENERAL_ERROR 1
571 #define CA_CERT_INVALID_ERROR 2
574 client_connect (const char *hostName
, PRUint32 ip
,
576 const char* infileName
, const char* outfileName
,
577 const char* trustNewServer
)
583 PRErrorCode errorNumber
;
584 char buffer
[PR_NETDB_BUF_SIZE
];
586 int errCode
= GENERAL_ERROR
;
587 struct connectionState_t connectionState
;
589 connectionState
.hostName
= hostName
;
590 connectionState
.port
= port
;
591 connectionState
.infileName
= infileName
;
592 connectionState
.outfileName
= outfileName
;
593 connectionState
.trustNewServerMode
= trustNewServer
;
595 /* Setup network connection. If we have an ip address, then
596 simply use it, otherwise we need to resolve the host name. */
599 connectionState
.addr
.inet
.family
= PR_AF_INET
;
600 connectionState
.addr
.inet
.port
= htons (port
);
601 connectionState
.addr
.inet
.ip
= htonl (ip
);
605 prStatus
= PR_GetHostByName(hostName
, buffer
, sizeof (buffer
), &hostEntry
);
606 if (prStatus
!= PR_SUCCESS
) {
607 fprintf (stderr
, "Unable to resolve server host name");
611 rv
= PR_EnumerateHostEnt(0, &hostEntry
, port
, &connectionState
.addr
);
613 fprintf (stderr
, "Unable to resolve server host address");
618 /* Some errors (see below) represent a situation in which trying again
619 should succeed. However, don't try forever. */
620 for (attempt
= 0; attempt
< 5; ++attempt
)
622 secStatus
= do_connect (& connectionState
);
623 if (secStatus
== SECSuccess
)
626 errorNumber
= PR_GetError ();
629 case PR_CONNECT_RESET_ERROR
:
630 /* Server was not ready. */
632 break; /* Try again */
633 case SEC_ERROR_EXPIRED_CERTIFICATE
:
634 /* The server's certificate has expired. It should
635 generate a new certificate. Give the server a chance to recover
638 break; /* Try again */
639 case SEC_ERROR_CA_CERT_INVALID
:
640 /* The server's certificate is not trusted. The exit code must
642 errCode
= CA_CERT_INVALID_ERROR
;
645 /* This error is fatal. */
655 compile_server_client::passes_0_4 ()
657 PROBE1(stap
, client__start
, &s
);
660 // This code will never be called, if we don't have NSS, but it must still
664 // arguments parsed; get down to business
666 clog
<< "Using a compile server" << endl
;
668 struct tms tms_before
;
669 times (& tms_before
);
670 struct timeval tv_before
;
671 gettimeofday (&tv_before
, NULL
);
673 // Create the request package.
674 int rc
= initialize ();
675 if (rc
!= 0 || pending_interrupts
) goto done
;
676 rc
= create_request ();
677 if (rc
!= 0 || pending_interrupts
) goto done
;
678 rc
= package_request ();
679 if (rc
!= 0 || pending_interrupts
) goto done
;
681 // Submit it to the server.
682 rc
= find_and_connect_to_server ();
683 if (rc
!= 0 || pending_interrupts
) goto done
;
685 // Unpack and process the response.
686 rc
= unpack_response ();
687 if (rc
!= 0 || pending_interrupts
) goto done
;
688 rc
= process_response ();
690 if (rc
== 0 && s
.last_pass
== 4)
692 cout
<< s
.module_name
+ ".ko";
697 struct tms tms_after
;
699 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
700 struct timeval tv_after
;
701 gettimeofday (&tv_after
, NULL
);
703 #define TIMESPRINT "in " << \
704 (tms_after.tms_cutime + tms_after.tms_utime \
705 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
706 << (tms_after.tms_cstime + tms_after.tms_stime \
707 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
708 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
709 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
711 // syntax errors, if any, are already printed
714 clog
<< "Passes: via server " << s
.winning_server
<< " "
722 // Save the module, if necessary.
723 if (s
.last_pass
== 4)
724 s
.save_module
= true;
726 // Copy module to the current directory.
727 if (s
.save_module
&& ! pending_interrupts
)
729 string module_src_path
= s
.tmpdir
+ "/" + s
.module_name
+ ".ko";
730 string module_dest_path
= s
.module_name
+ ".ko";
731 copy_file (module_src_path
, module_dest_path
, s
.verbose
> 1);
732 // Also copy the module signature, it it exists.
733 module_src_path
+= ".sgn";
734 if (file_exists (module_src_path
))
736 module_dest_path
+= ".sgn";
737 copy_file(module_src_path
, module_dest_path
, s
.verbose
> 1);
742 PROBE1(stap
, client__end
, &s
);
749 // Initialize a client/server session.
751 compile_server_client::initialize ()
755 // Initialize session state
758 // Private location for server certificates.
759 private_ssl_dbs
.push_back (private_ssl_cert_db_path (s
));
761 // Additional public location.
762 public_ssl_dbs
.push_back (global_ssl_cert_db_path ());
764 // Create a temporary directory to package things in.
765 client_tmpdir
= s
.tmpdir
+ "/client";
766 rc
= create_dir (client_tmpdir
.c_str ());
769 const char* e
= strerror (errno
);
770 cerr
<< "ERROR: cannot create temporary directory (\""
771 << client_tmpdir
<< "\"): " << e
778 // Create the request package.
780 compile_server_client::create_request ()
784 // Add the script file or script option
785 if (s
.script_file
!= "")
787 if (s
.script_file
== "-")
789 // Copy the script from stdin
790 string packaged_script_dir
= client_tmpdir
+ "/script";
791 rc
= create_dir (packaged_script_dir
.c_str ());
794 const char* e
= strerror (errno
);
795 cerr
<< "ERROR: cannot create temporary directory "
796 << packaged_script_dir
<< ": " << e
800 rc
= ! copy_file("/dev/stdin", packaged_script_dir
+ "/-");
804 // Name the script in the packaged arguments.
805 rc
= add_package_arg ("script/-");
811 // Add the script to our package. This will also name the script
812 // in the packaged arguments.
813 rc
= include_file_or_directory ("script", s
.script_file
);
819 // Add -I paths. Skip the default directory.
820 if (s
.include_arg_start
!= -1)
822 unsigned limit
= s
.include_path
.size ();
823 for (unsigned i
= s
.include_arg_start
; i
< limit
; ++i
)
825 rc
= add_package_arg ("-I");
828 rc
= include_file_or_directory ("tapset", s
.include_path
[i
]);
834 // Add other options.
835 rc
= add_package_args ();
839 // Add the sysinfo file
840 string sysinfo
= "sysinfo: " + s
.kernel_release
+ " " + s
.architecture
;
841 rc
= write_to_file (client_tmpdir
+ "/sysinfo", sysinfo
);
846 // Add the arguments specified on the command line to the server request
847 // package, as appropriate.
849 compile_server_client::add_package_args ()
851 // stap arguments to be passed to the server.
853 unsigned limit
= s
.server_args
.size();
854 for (unsigned i
= 0; i
< limit
; ++i
)
856 rc
= add_package_arg (s
.server_args
[i
]);
862 limit
= s
.args
.size();
864 rc
= add_package_arg ("--");
867 for (unsigned i
= 0; i
< limit
; ++i
)
869 rc
= add_package_arg (s
.args
[i
]);
878 compile_server_client::add_package_arg (const string
&arg
)
882 fname
<< client_tmpdir
<< "/argv" << ++argc
;
883 write_to_file (fname
.str (), arg
); // NB: No terminating newline
887 // Symbolically link the given file or directory into the client's temp
888 // directory under the given subdirectory.
890 compile_server_client::include_file_or_directory (
891 const string
&subdir
, const string
&path
, const char *option
894 // Must predeclare these because we do use 'goto done' to
895 // exit from error situations.
896 vector
<string
> components
;
900 // Canonicalize the given path and remove the leading /.
902 char *cpath
= canonicalize_file_name (path
.c_str ());
905 // It can not be canonicalized. Use the name relative to
906 // the current working directory and let the server deal with it.
908 if (getcwd (cwd
, sizeof (cwd
)) == NULL
)
914 rpath
= string (cwd
) + "/" + path
;
918 // It can be canonicalized. Use the canonicalized name and add this
919 // file or directory to the request package.
923 // First create the requested subdirectory.
924 name
= client_tmpdir
+ "/" + subdir
;
925 rc
= create_dir (name
.c_str ());
928 // Now create each component of the path within the sub directory.
929 assert (rpath
[0] == '/');
930 tokenize (rpath
.substr (1), components
, "/");
931 assert (components
.size () >= 1);
933 for (i
= 0; i
< components
.size() - 1; ++i
)
935 if (components
[i
].empty ())
936 continue; // embedded '//'
937 name
+= "/" + components
[i
];
938 rc
= create_dir (name
.c_str ());
942 // Now make a symbolic link to the actual file or directory.
943 assert (i
== components
.size () - 1);
944 name
+= "/" + components
[i
];
945 rc
= symlink (rpath
.c_str (), name
.c_str ());
949 // Name this file or directory in the packaged arguments along with any
950 // associated option.
953 rc
= add_package_arg (option
);
957 rc
= add_package_arg (subdir
+ "/" + rpath
.substr (1));
962 const char* e
= strerror (errno
);
963 cerr
<< "ERROR: unable to add "
965 << " to temp directory as "
972 // Package the client's temp directory into a form suitable for sending to the
975 compile_server_client::package_request ()
977 // Package up the temporary directory into a zip file.
978 client_zipfile
= client_tmpdir
+ ".zip";
979 string cmd
= "cd " + client_tmpdir
+ " && zip -qr " + client_zipfile
+ " *";
980 int rc
= stap_system (s
.verbose
, cmd
);
985 compile_server_client::find_and_connect_to_server ()
987 // Accumulate info on the specified servers.
988 vector
<compile_server_info
> specified_servers
;
989 get_specified_server_info (s
, specified_servers
);
991 // Examine the specified servers to make sure that each has been resolved
992 // with a host name, ip address and port. If not, try to obtain this
993 // information by examining online servers.
994 vector
<compile_server_info
> server_list
= specified_servers
;
995 for (vector
<compile_server_info
>::const_iterator i
= specified_servers
.begin ();
996 i
!= specified_servers
.end ();
999 // If we have an ip address and port number, then just use the one we've
1000 // been given. Otherwise, check for matching online servers and try their
1001 // ip addresses and ports.
1002 if (! i
->host_name
.empty () && ! i
->ip_address
.empty () && i
->port
!= 0)
1003 add_server_info (*i
, server_list
);
1006 // Obtain a list of online servers.
1007 vector
<compile_server_info
> online_servers
;
1008 get_or_keep_online_server_info (s
, online_servers
, false/*keep*/);
1010 // If no specific server (port) has been specified,
1011 // then we'll need the servers to be
1012 // compatible and possible trusted as signers as well.
1015 get_or_keep_compatible_server_info (s
, online_servers
, true/*keep*/);
1017 get_or_keep_signing_server_info (s
, online_servers
, true/*keep*/);
1020 // Keep the ones (if any) which match our server.
1021 keep_common_server_info (*i
, online_servers
);
1023 // Add these servers (if any) to the server list.
1024 add_server_info (online_servers
, server_list
);
1028 // Did we identify any potential servers?
1029 unsigned limit
= server_list
.size ();
1032 cerr
<< "Unable to find a server" << endl
;
1036 // Now try each of the identified servers in turn.
1037 int rc
= compile_using_server (server_list
);
1039 return 0; // success!
1041 return 1; // Failure - message already generated.
1045 // Convert the given string to an ip address in host byte order.
1047 stringToIpAddress (const string
&s
)
1050 return 0; // unknown
1052 vector
<string
>components
;
1053 tokenize (s
, components
, ".");
1054 assert (components
.size () >= 1);
1058 for (i
= 0; i
< components
.size (); ++i
)
1060 const char *ipstr
= components
[i
].c_str ();
1063 unsigned a
= strtoul (ipstr
, & estr
, 10);
1064 if (errno
== 0 && *estr
== '\0' && a
<= UCHAR_MAX
)
1074 compile_server_client::compile_using_server (
1075 const vector
<compile_server_info
> &servers
1078 // This code will never be called if we don't have NSS, but it must still
1081 // Make sure NSPR is initialized
1084 // Attempt connection using each of the available client certificate
1085 // databases. Assume the server certificate is invalid until proven otherwise.
1086 PR_SetError (SEC_ERROR_CA_CERT_INVALID
, 0);
1087 vector
<string
> dbs
= private_ssl_dbs
;
1088 vector
<string
>::iterator i
= dbs
.end();
1089 dbs
.insert (i
, public_ssl_dbs
.begin (), public_ssl_dbs
.end ());
1090 int rc
= 1; // assume failure
1091 for (i
= dbs
.begin (); i
!= dbs
.end (); ++i
)
1093 // Make sure the database directory exists. It is not an error if it
1095 if (! file_exists (*i
))
1098 #if 0 // no client authentication for now.
1099 // Set our password function callback.
1100 PK11_SetPasswordFunc (myPasswd
);
1103 // Initialize the NSS libraries.
1104 const char *cert_dir
= i
->c_str ();
1105 SECStatus secStatus
= NSS_InitReadWrite (cert_dir
);
1106 if (secStatus
!= SECSuccess
)
1108 // Try it again, readonly.
1109 secStatus
= NSS_Init(cert_dir
);
1110 if (secStatus
!= SECSuccess
)
1112 cerr
<< "Error initializing NSS" << endl
;
1115 continue; // try next database
1119 // All cipher suites except RSA_NULL_MD5 are enabled by Domestic Policy.
1120 NSS_SetDomesticPolicy ();
1122 server_zipfile
= s
.tmpdir
+ "/server.zip";
1124 // Try each server in turn.
1125 for (vector
<compile_server_info
>::const_iterator j
= servers
.begin ();
1126 j
!= servers
.end ();
1130 clog
<< "Attempting SSL connection with " << *j
<< endl
1131 << " using certificates from the database in " << cert_dir
1134 // The host name defaults to the ip address, if not specified.
1136 if (j
->host_name
.empty ())
1138 assert (! j
->ip_address
.empty ());
1139 hostName
= j
->ip_address
;
1142 hostName
= j
->host_name
;
1144 rc
= client_connect (hostName
.c_str (),
1145 stringToIpAddress (j
->ip_address
),
1147 client_zipfile
.c_str(), server_zipfile
.c_str (),
1148 NULL
/*trustNewServer_p*/);
1149 if (rc
== SECSuccess
)
1152 hostName
+ string(" [") +
1153 j
->ip_address
+ string(":") +
1154 lex_cast(j
->port
) + string("]");
1160 clog
<< " Unable to connect: ";
1167 if (rc
== SECSuccess
)
1171 if (rc
!= SECSuccess
)
1172 cerr
<< "Unable to connect to a server" << endl
;
1177 return 1; // Failure
1182 compile_server_client::unpack_response ()
1184 // Unzip the response package.
1185 server_tmpdir
= s
.tmpdir
+ "/server";
1186 string cmd
= "unzip -qd " + server_tmpdir
+ " " + server_zipfile
;
1187 int rc
= stap_system (s
.verbose
, cmd
);
1190 cerr
<< "Unable to unzip the server reponse '" << server_zipfile
<< '\''
1194 // If the server's response contains a systemtap temp directory, move
1195 // its contents to our temp directory.
1197 string filespec
= server_tmpdir
+ "/stap??????";
1199 clog
<< "Searching \"" << filespec
<< "\"" << endl
;
1200 int r
= glob(filespec
.c_str (), 0, NULL
, & globbuf
);
1201 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1203 if (globbuf
.gl_pathc
> 1)
1205 cerr
<< "Incorrect number of files in server response" << endl
;
1209 assert (globbuf
.gl_pathc
== 1);
1210 string dirname
= globbuf
.gl_pathv
[0];
1212 clog
<< " found " << dirname
<< endl
;
1214 filespec
= dirname
+ "/*";
1216 clog
<< "Searching \"" << filespec
<< "\"" << endl
;
1217 int r
= glob(filespec
.c_str (), GLOB_PERIOD
, NULL
, & globbuf
);
1218 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1220 unsigned prefix_len
= dirname
.size () + 1;
1221 for (unsigned i
= 0; i
< globbuf
.gl_pathc
; ++i
)
1223 string oldname
= globbuf
.gl_pathv
[i
];
1224 if (oldname
.substr (oldname
.size () - 2) == "/." ||
1225 oldname
.substr (oldname
.size () - 3) == "/..")
1227 string newname
= s
.tmpdir
+ "/" + oldname
.substr (prefix_len
);
1229 clog
<< " found " << oldname
1230 << " -- linking from " << newname
<< endl
;
1231 rc
= symlink (oldname
.c_str (), newname
.c_str ());
1234 cerr
<< "Unable to link '" << oldname
1235 << "' to '" << newname
<< "': "
1236 << strerror (errno
) << endl
;
1243 // Remove the output line due to the synthetic server-side -k
1244 cmd
= "sed -i '/^Keeping temporary directory.*/ d' " +
1245 server_tmpdir
+ "/stderr";
1246 stap_system (s
.verbose
, cmd
);
1248 // Remove the output line due to the synthetic server-side -p4
1249 cmd
= "sed -i '/^.*\\.ko$/ d' " + server_tmpdir
+ "/stdout";
1250 stap_system (s
.verbose
, cmd
);
1253 globfree (& globbuf
);
1258 compile_server_client::process_response ()
1260 // Pick up the results of running stap on the server.
1261 string filename
= server_tmpdir
+ "/rc";
1263 int rc
= read_from_file (filename
, stap_rc
);
1268 if (s
.last_pass
>= 4)
1270 // The server should have returned a module.
1271 string filespec
= s
.tmpdir
+ "/*.ko";
1273 clog
<< "Searching \"" << filespec
<< "\"" << endl
;
1276 int r
= glob(filespec
.c_str (), 0, NULL
, & globbuf
);
1277 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1279 if (globbuf
.gl_pathc
> 1)
1280 cerr
<< "Incorrect number of modules in server response" << endl
;
1283 assert (globbuf
.gl_pathc
== 1);
1284 string modname
= globbuf
.gl_pathv
[0];
1286 clog
<< " found " << modname
<< endl
;
1288 // If a module name was not specified by the user, then set it to
1289 // be the one generated by the server.
1290 if (! s
.save_module
)
1292 vector
<string
> components
;
1293 tokenize (modname
, components
, "/");
1294 s
.module_name
= components
.back ();
1295 s
.module_name
.erase(s
.module_name
.size() - 3);
1298 // If a uprobes.ko module was returned, then make note of it.
1299 if (file_exists (s
.tmpdir
+ "/server/uprobes.ko"))
1301 s
.need_uprobes
= true;
1302 s
.uprobes_path
= s
.tmpdir
+ "/server/uprobes.ko";
1306 else if (s
.have_script
)
1310 cerr
<< "No module was returned by the server" << endl
;
1314 globfree (& globbuf
);
1317 // Output stdout and stderr.
1318 filename
= server_tmpdir
+ "/stderr";
1319 flush_to_stream (filename
, cerr
);
1321 filename
= server_tmpdir
+ "/stdout";
1322 flush_to_stream (filename
, cout
);
1328 compile_server_client::read_from_file (const string
&fname
, int &data
)
1330 // C++ streams may not set errno in the even of a failure. However if we
1331 // set it to 0 before each operation and it gets set during the operation,
1332 // then we can use its value in order to determine what happened.
1334 ifstream
f (fname
.c_str ());
1337 cerr
<< "Unable to open file '" << fname
<< "' for reading: ";
1346 cerr
<< "Unable to read from file '" << fname
<< "': ";
1350 // NB: not necessary to f.close ();
1351 return 0; // Success
1355 cerr
<< strerror (errno
) << endl
;
1357 cerr
<< "unknown error" << endl
;
1358 return 1; // Failure
1362 compile_server_client::write_to_file (const string
&fname
, const string
&data
)
1364 // C++ streams may not set errno in the even of a failure. However if we
1365 // set it to 0 before each operation and it gets set during the operation,
1366 // then we can use its value in order to determine what happened.
1368 ofstream
f (fname
.c_str ());
1371 cerr
<< "Unable to open file '" << fname
<< "' for writing: ";
1380 cerr
<< "Unable to write to file '" << fname
<< "': ";
1384 // NB: not necessary to f.close ();
1385 return 0; // Success
1389 cerr
<< strerror (errno
) << endl
;
1391 cerr
<< "unknown error" << endl
;
1392 return 1; // Failure
1396 compile_server_client::flush_to_stream (const string
&fname
, ostream
&o
)
1398 // C++ streams may not set errno in the even of a failure. However if we
1399 // set it to 0 before each operation and it gets set during the operation,
1400 // then we can use its value in order to determine what happened.
1402 ifstream
f (fname
.c_str ());
1405 cerr
<< "Unable to open file '" << fname
<< "' for reading: ";
1411 // NB: o << f.rdbuf() misbehaves for some reason, appearing to close o,
1412 // which is unfortunate if o == cerr or cout.
1417 if (f
.eof ()) return 0; // normal exit
1418 if (! f
.good()) break;
1420 if (! o
.good()) break;
1423 // NB: not necessary to f.close ();
1427 cerr
<< strerror (errno
) << endl
;
1429 cerr
<< "unknown error" << endl
;
1430 return 1; // Failure
1434 // Utility Functions.
1435 //-----------------------------------------------------------------------
1436 ostream
&operator<< (ostream
&s
, const compile_server_info
&i
)
1439 if (! i
.host_name
.empty ())
1444 if (! i
.ip_address
.empty ())
1454 if (! i
.sysinfo
.empty ())
1455 s
<< i
.sysinfo
<< '"';
1458 s
<< " certinfo=\"";
1459 if (! i
.certinfo
.empty ())
1460 s
<< i
.certinfo
<< '"';
1466 // Return the default server specification, used when none is given on the
1469 default_server_spec (const systemtap_session
&s
)
1471 // If the --use-server option has been used
1472 // the default is 'specified'
1473 // otherwise if the --unprivileged has been used
1474 // the default is online,trusted,compatible,signer
1476 // the default is online,compatible
1478 // Having said that,
1479 // 'online' and 'compatible' will only succeed if we have avahi
1480 // 'trusted' and 'signer' will only succeed if we have NSS
1482 string working_string
= "online,trusted,compatible";
1484 working_string
+= ",signer";
1485 return working_string
;
1489 server_spec_to_pmask (const string
&server_spec
)
1491 // Construct a mask of the server properties that have been requested.
1492 // The available properties are:
1493 // trusted - servers which are trusted SSL peers.
1494 // online - online servers.
1495 // compatible - servers which compile for the current kernel release
1496 // and architecture.
1497 // signer - servers which are trusted module signers.
1498 // specified - servers which have been specified using --use-server=XXX.
1499 // If no servers have been specified, then this is
1500 // equivalent to --list-servers=trusted,online,compatible.
1501 // all - all trusted servers, trusted module signers,
1502 // servers currently online and specified servers.
1503 string working_spec
= server_spec
;
1504 vector
<string
> properties
;
1505 tokenize (working_spec
, properties
, ",");
1507 unsigned limit
= properties
.size ();
1508 for (unsigned i
= 0; i
< limit
; ++i
)
1510 const string
&property
= properties
[i
];
1511 // Tolerate (and ignore) empty properties.
1512 if (property
.empty ())
1514 if (property
== "all")
1516 pmask
|= compile_server_all
;
1518 else if (property
== "specified")
1520 pmask
|= compile_server_specified
;
1522 else if (property
== "trusted")
1524 pmask
|= compile_server_trusted
;
1526 else if (property
== "online")
1528 pmask
|= compile_server_online
;
1530 else if (property
== "compatible")
1532 pmask
|= compile_server_compatible
;
1534 else if (property
== "signer")
1536 pmask
|= compile_server_signer
;
1540 cerr
<< "Warning: unsupported compile server property: " << property
1548 query_server_status (systemtap_session
&s
)
1550 // Make sure NSPR is initialized
1553 unsigned limit
= s
.server_status_strings
.size ();
1554 for (unsigned i
= 0; i
< limit
; ++i
)
1555 query_server_status (s
, s
.server_status_strings
[i
]);
1559 query_server_status (systemtap_session
&s
, const string
&status_string
)
1561 // If this string is empty, then the default is "specified"
1562 string working_string
= status_string
;
1563 if (working_string
.empty ())
1564 working_string
= "specified";
1566 // If the query is "specified" and no servers have been specified
1567 // (i.e. --use-server not used or used with no argument), then
1568 // use the default query.
1569 // TODO: This may not be necessary. The underlying queries should handle
1570 // "specified" properly.
1571 if (working_string
== "specified" &&
1572 (s
.specified_servers
.empty () ||
1573 (s
.specified_servers
.size () == 1 && s
.specified_servers
[0].empty ())))
1574 working_string
= default_server_spec (s
);
1576 int pmask
= server_spec_to_pmask (working_string
);
1578 // Now obtain a list of the servers which match the criteria.
1579 vector
<compile_server_info
> raw_servers
;
1580 get_server_info (s
, pmask
, raw_servers
);
1582 // Augment the listing with as much information as possible by adding
1583 // information from known servers.
1584 vector
<compile_server_info
> servers
;
1585 get_all_server_info (s
, servers
);
1586 keep_common_server_info (raw_servers
, servers
);
1588 // Print the server information. Skip the empty entry at the head of the list.
1589 clog
<< "Systemtap Compile Server Status for '" << working_string
<< '\''
1592 unsigned limit
= servers
.size ();
1593 for (unsigned i
= 0; i
< limit
; ++i
)
1595 assert (! servers
[i
].empty ());
1596 // Don't list servers with no cert information. They may not actually
1598 // TODO: Could try contacting the server and obtaining it cert
1599 if (servers
[i
].certinfo
.empty ())
1601 clog
<< servers
[i
] << endl
;
1605 clog
<< "No servers found" << endl
;
1608 // Add or remove trust of the servers specified on the command line.
1610 manage_server_trust (systemtap_session
&s
)
1612 // This function will never be called if we don't have NSS, but it must
1615 // Nothing to do if --trust-servers was not specified.
1616 if (s
.server_trust_spec
.empty ())
1619 // Break up and analyze the trust specification. Recognized components are:
1620 // ssl - trust the specified servers as ssl peers
1621 // signer - trust the specified servers as module signers
1622 // revoke - revoke the requested trust
1623 // all-users - apply/revoke the requested trust for all users
1624 // no-prompt - don't prompt the user for confirmation
1625 vector
<string
>components
;
1626 tokenize (s
.server_trust_spec
, components
, ",");
1628 bool signer
= false;
1629 bool revoke
= false;
1630 bool all_users
= false;
1631 bool no_prompt
= false;
1633 for (vector
<string
>::const_iterator i
= components
.begin ();
1634 i
!= components
.end ();
1639 else if (*i
== "signer")
1641 if (geteuid () != 0)
1643 cerr
<< "Only root can specify 'signer' on --trust-servers" << endl
;
1649 else if (*i
== "revoke")
1651 else if (*i
== "all-users")
1653 if (geteuid () != 0)
1655 cerr
<< "Only root can specify 'all-users' on --trust-servers" << endl
;
1661 else if (*i
== "no-prompt")
1664 cerr
<< "Warning: Unrecognized server trust specification: " << *i
1670 // Make sure NSPR is initialized
1673 // Now obtain the list of specified servers.
1674 vector
<compile_server_info
> server_list
;
1675 get_specified_server_info (s
, server_list
, true/*no_default*/);
1677 // Did we identify any potential servers?
1678 unsigned limit
= server_list
.size ();
1681 cerr
<< "No servers identified for trust" << endl
;
1685 // Create a string representing the request in English.
1686 // If neither 'ssl' or 'signer' was specified, the default is 'ssl'.
1687 if (! ssl
&& ! signer
)
1689 ostringstream trustString
;
1692 trustString
<< "as an SSL peer";
1694 trustString
<< " for all users";
1696 trustString
<< " for the current user";
1701 trustString
<< " and ";
1702 trustString
<< "as a module signer for all users";
1705 // Prompt the user to confirm what's about to happen.
1709 clog
<< "Revoking trust ";
1711 clog
<< "Adding trust ";
1716 clog
<< "Revoke trust ";
1718 clog
<< "Add trust ";
1720 clog
<< "in the following servers " << trustString
.str ();
1724 for (unsigned i
= 0; i
< limit
; ++i
)
1725 clog
<< " " << server_list
[i
] << endl
;
1728 clog
<< "[y/N] " << flush
;
1730 // Only carry out the operation if the response is "yes"
1733 if (response
[0] != 'y' && response
[0] != 'Y')
1735 clog
<< "Server trust unchanged" << endl
;
1740 // Now add/revoke the requested trust.
1741 string cert_db_path
;
1745 cert_db_path
= global_ssl_cert_db_path ();
1747 cert_db_path
= private_ssl_cert_db_path (s
);
1749 revoke_server_trust (s
, cert_db_path
, server_list
);
1751 add_server_trust (s
, cert_db_path
, server_list
);
1755 cert_db_path
= signing_cert_db_path ();
1757 revoke_server_trust (s
, cert_db_path
, server_list
);
1759 add_server_trust (s
, cert_db_path
, server_list
);
1765 // Issue a status message for when a server's trust is already in place.
1767 trust_already_in_place (
1768 const compile_server_info
&server
,
1769 const vector
<compile_server_info
> &server_list
,
1770 const string cert_db_path
,
1774 // What level of trust?
1776 if (cert_db_path
== signing_cert_db_path ())
1777 purpose
= "as a module signer for all users";
1780 purpose
= "as an SSL peer";
1781 if (cert_db_path
== global_ssl_cert_db_path ())
1782 purpose
+= " for all users";
1784 purpose
+= " for the current user";
1787 // Issue a message for each server in the list with the same certificate.
1788 unsigned limit
= server_list
.size ();
1789 for (unsigned i
= 0; i
< limit
; ++i
)
1791 if (server
.certinfo
!= server_list
[i
].certinfo
)
1793 clog
<< server_list
[i
] << " is already ";
1796 clog
<< "trusted " << purpose
<< endl
;
1800 // Add the given servers to the given database of trusted servers.
1803 systemtap_session
&s
,
1804 const string
&cert_db_path
,
1805 const vector
<compile_server_info
> &server_list
1808 // Get a list of servers already trusted. This opens the database, so do it
1809 // before we open it for our own purposes.
1810 vector
<compile_server_info
> already_trusted
;
1811 get_server_info_from_db (s
, already_trusted
, cert_db_path
);
1813 // Make sure the given path exists.
1814 if (create_dir (cert_db_path
.c_str (), 0755) != 0)
1816 cerr
<< "Unable to find or create the client certificate database directory "
1817 << cert_db_path
<< ": ";
1822 // Must predeclare this because of jumps to cleanup: below.
1823 vector
<string
> processed_certs
;
1825 // Initialize the NSS libraries -- read/write
1826 SECStatus secStatus
= NSS_InitReadWrite (cert_db_path
.c_str ());
1827 if (secStatus
!= SECSuccess
)
1829 cerr
<< "Error initializing NSS for " << cert_db_path
<< endl
;
1834 // All cipher suites except RSA_NULL_MD5 are enabled by Domestic Policy.
1835 NSS_SetDomesticPolicy ();
1837 // Iterate over the servers to become trusted. Contact each one and
1838 // add it to the list of trusted servers if it is not already trusted.
1839 // client_connect will issue any error messages.
1840 for (vector
<compile_server_info
>::const_iterator server
= server_list
.begin();
1841 server
!= server_list
.end ();
1844 // Trust is based on certificates. We need only add trust in the
1845 // same certificate once.
1846 if (find (processed_certs
.begin (), processed_certs
.end (),
1847 server
->certinfo
) != processed_certs
.end ())
1849 processed_certs
.push_back (server
->certinfo
);
1851 // We need not contact the server if it is already trusted.
1852 if (find (already_trusted
.begin (), already_trusted
.end (), *server
) !=
1853 already_trusted
.end ())
1856 trust_already_in_place (*server
, server_list
, cert_db_path
, false/*revoking*/);
1859 // At a minimum we need a host name or ip_address along with a port
1860 // number in order to contact the server.
1861 if (server
->empty () || server
->port
== 0)
1863 int rc
= client_connect (server
->host_name
.c_str (),
1864 stringToIpAddress (server
->ip_address
),
1866 NULL
, NULL
, "permanent");
1867 if (rc
!= SECSuccess
)
1869 cerr
<< "Unable to connect to " << *server
<< endl
;
1878 // Make sure the database files are readable.
1880 string filespec
= cert_db_path
+ "/*.db";
1882 clog
<< "Searching \"" << filespec
<< "\"" << endl
;
1883 int r
= glob (filespec
.c_str (), 0, NULL
, & globbuf
);
1884 if (r
!= GLOB_NOSPACE
&& r
!= GLOB_ABORTED
&& r
!= GLOB_NOMATCH
)
1886 for (unsigned i
= 0; i
< globbuf
.gl_pathc
; ++i
)
1888 string filename
= globbuf
.gl_pathv
[i
];
1890 clog
<< " found " << filename
<< endl
;
1892 if (chmod (filename
.c_str (), 0644) != 0)
1894 cerr
<< "Warning: Unable to change permissions on "
1895 << filename
<< ": ";
1902 // Remove the given servers from the given database of trusted servers.
1904 revoke_server_trust (
1905 systemtap_session
&s
,
1906 const string
&cert_db_path
,
1907 const vector
<compile_server_info
> &server_list
1910 // Make sure the given path exists.
1911 if (! file_exists (cert_db_path
))
1914 cerr
<< "Certificate database '" << cert_db_path
<< "' does not exist."
1918 for (vector
<compile_server_info
>::const_iterator server
= server_list
.begin();
1919 server
!= server_list
.end ();
1921 trust_already_in_place (*server
, server_list
, cert_db_path
, true/*revoking*/);
1926 // Must predeclare these because of jumps to cleanup: below.
1927 PK11SlotInfo
*slot
= NULL
;
1928 CERTCertDBHandle
*handle
;
1929 PRArenaPool
*tmpArena
= NULL
;
1930 CERTCertList
*certs
= NULL
;
1931 CERTCertificate
*db_cert
;
1932 vector
<string
> processed_certs
;
1934 // Initialize the NSS libraries -- read/write
1935 SECStatus secStatus
= NSS_InitReadWrite (cert_db_path
.c_str ());
1936 if (secStatus
!= SECSuccess
)
1938 cerr
<< "Error initializing NSS for " << cert_db_path
<< endl
;
1942 slot
= PK11_GetInternalKeySlot ();
1943 handle
= CERT_GetDefaultCertDB();
1945 // A memory pool to work in
1946 tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1949 cerr
<< "Out of memory:";
1954 // Iterate over the servers to become untrusted.
1955 for (vector
<compile_server_info
>::const_iterator server
= server_list
.begin();
1956 server
!= server_list
.end ();
1959 // If the server's certificate serial number is unknown, then we can't
1960 // match it with one in the database.
1961 if (server
->certinfo
.empty ())
1964 // Trust is based on certificates. We need only revoke trust in the same
1965 // certificate once.
1966 if (find (processed_certs
.begin (), processed_certs
.end (),
1967 server
->certinfo
) != processed_certs
.end ())
1969 processed_certs
.push_back (server
->certinfo
);
1971 // Search the client-side database of trusted servers.
1972 db_cert
= PK11_FindCertFromNickname (server_cert_nickname
, NULL
);
1975 // No trusted servers. Not an error, but issue a status message.
1977 trust_already_in_place (*server
, server_list
, cert_db_path
, true/*revoking*/);
1981 // Here, we have one cert with the desired nickname.
1982 // Now, we will attempt to get a list of ALL certs
1983 // with the same subject name as the cert we have. That list
1984 // should contain, at a minimum, the one cert we have already found.
1985 // If the list of certs is empty (NULL), the libraries have failed.
1986 certs
= CERT_CreateSubjectCertList (NULL
, handle
, & db_cert
->derSubject
,
1987 PR_Now (), PR_FALSE
);
1988 CERT_DestroyCertificate (db_cert
);
1991 cerr
<< "Unable to query certificate database " << cert_db_path
1993 PORT_SetError (SEC_ERROR_LIBRARY_FAILURE
);
1998 // Find the certificate matching the one belonging to our server.
1999 CERTCertListNode
*node
;
2000 for (node
= CERT_LIST_HEAD (certs
);
2001 ! CERT_LIST_END (node
, certs
);
2002 node
= CERT_LIST_NEXT (node
))
2004 // The certificate we're working with.
2005 db_cert
= node
->cert
;
2007 // Get the serial number.
2008 ostringstream serialNumber
;
2009 serialNumber
<< hex
<< setfill('0') << right
;
2010 for (unsigned i
= 0; i
< db_cert
->serialNumber
.len
; ++i
)
2013 serialNumber
<< ':';
2014 serialNumber
<< setw(2) << (unsigned)db_cert
->serialNumber
.data
[i
];
2017 // Does the serial number match that of the current server?
2018 if (serialNumber
.str () != server
->certinfo
)
2019 continue; // goto next certificate
2021 // All is ok! Remove the certificate from the database.
2023 } // Loop over certificates in the database
2025 // Was a certificate matching the server found? */
2026 if (CERT_LIST_END (node
, certs
))
2028 // Not found. Server is already untrusted.
2030 trust_already_in_place (*server
, server_list
, cert_db_path
, true/*revoking*/);
2034 secStatus
= SEC_DeletePermCertificate (db_cert
);
2035 if (secStatus
!= SECSuccess
)
2037 cerr
<< "Unable to remove certificate from " << cert_db_path
2042 CERT_DestroyCertList (certs
);
2044 } // Loop over servers
2048 CERT_DestroyCertList (certs
);
2050 PK11_FreeSlot (slot
);
2052 PORT_FreeArena (tmpArena
, PR_FALSE
);
2060 systemtap_session
&s
,
2062 vector
<compile_server_info
> &servers
2065 // Get information on compile servers matching the requested criteria.
2066 // The order of queries is significant. Accumulating queries must go first
2067 // followed by accumulating/filtering queries.
2069 if (((pmask
& compile_server_all
)))
2071 get_all_server_info (s
, servers
);
2074 // Add the specified servers, if requested
2075 if ((pmask
& compile_server_specified
))
2077 get_specified_server_info (s
, servers
);
2080 // Now filter the or accumulate the list depending on whether a query has
2081 // already been made.
2082 if ((pmask
& compile_server_online
))
2084 get_or_keep_online_server_info (s
, servers
, keep
);
2087 if ((pmask
& compile_server_trusted
))
2089 get_or_keep_trusted_server_info (s
, servers
, keep
);
2092 if ((pmask
& compile_server_signer
))
2094 get_or_keep_signing_server_info (s
, servers
, keep
);
2097 if ((pmask
& compile_server_compatible
))
2099 get_or_keep_compatible_server_info (s
, servers
, keep
);
2104 // Get information about all online servers as well as servers trusted
2105 // as SSL peers and servers trusted as signers.
2107 get_all_server_info (
2108 systemtap_session
&s
,
2109 vector
<compile_server_info
> &servers
2112 get_or_keep_online_server_info (s
, servers
, false/*keep*/);
2113 get_or_keep_trusted_server_info (s
, servers
, false/*keep*/);
2114 get_or_keep_signing_server_info (s
, servers
, false/*keep*/);
2118 get_default_server_info (
2119 systemtap_session
&s
,
2120 vector
<compile_server_info
> &servers
2123 // We only need to obtain this once. This is a good thing(tm) since
2124 // obtaining this information is expensive.
2125 static vector
<compile_server_info
> default_servers
;
2126 if (default_servers
.empty ())
2128 // Get the required information.
2129 // get_server_info will add an empty entry at the beginning to indicate
2130 // that the search has been performed, in case the search comes up empty.
2131 int pmask
= server_spec_to_pmask (default_server_spec (s
));
2132 get_server_info (s
, pmask
, default_servers
);
2135 // Add the information, but not duplicates.
2136 add_server_info (default_servers
, servers
);
2140 get_specified_server_info (
2141 systemtap_session
&s
,
2142 vector
<compile_server_info
> &servers
,
2146 // We only need to obtain this once. This is a good thing(tm) since
2147 // obtaining this information is expensive.
2148 static vector
<compile_server_info
> specified_servers
;
2149 if (specified_servers
.empty ())
2151 // Maintain an empty entry to indicate that this search has been
2152 // performed, in case the search comes up empty.
2153 specified_servers
.push_back (compile_server_info ());
2155 // If --use-servers was not specified at all, then return info for the
2156 // default server list.
2157 if (s
.specified_servers
.empty ())
2160 get_default_server_info (s
, specified_servers
);
2164 // Iterate over the specified servers. For each specification, add to
2165 // the list of servers.
2166 unsigned num_specified_servers
= s
.specified_servers
.size ();
2167 for (unsigned i
= 0; i
< num_specified_servers
; ++i
)
2169 string
&server
= s
.specified_servers
[i
];
2170 if (server
.empty ())
2172 // No server specified. Use the default servers.
2174 get_default_server_info (s
, specified_servers
);
2178 // Work with the specified server
2179 compile_server_info server_info
;
2181 // See if a port was specified (:n suffix)
2182 vector
<string
> components
;
2183 tokenize (server
, components
, ":");
2184 if (components
.size () > 2)
2186 // Treat it as a certificate serial number. The final
2187 // component may still be a port number.
2188 if (components
.size () > 5)
2190 // Obtain the port number.
2191 const char *pstr
= components
.back ().c_str ();
2194 unsigned long port
= strtoul (pstr
, & estr
, 10);
2195 if (errno
== 0 && *estr
== '\0' && port
<= USHRT_MAX
)
2196 server_info
.port
= port
;
2199 cerr
<< "Invalid port number specified: "
2200 << components
.back ()
2204 // Remove the port number from the spec
2205 server_info
.certinfo
= server
.substr (0, server
.find_last_of (':'));
2208 server_info
.certinfo
= server
;
2210 // Look for all known servers with this serial number and
2211 // (optional) port number.
2212 vector
<compile_server_info
> known_servers
;
2213 get_all_server_info (s
, known_servers
);
2214 keep_server_info_with_cert_and_port (s
, server_info
, known_servers
);
2216 if (known_servers
.empty ())
2219 cerr
<< "No server matching " << server
<< " found"
2223 add_server_info (known_servers
, specified_servers
);
2224 } // specified by cert serial number
2226 // Not specified by serial number. Treat it as host name or
2227 // ip address and optional port number.
2228 if (components
.size () == 2)
2230 // Obtain the port number.
2231 const char *pstr
= components
.back ().c_str ();
2234 unsigned long port
= strtoul (pstr
, & estr
, 10);
2235 if (errno
== 0 && *estr
== '\0' && port
<= USHRT_MAX
)
2236 server_info
.port
= port
;
2239 cerr
<< "Invalid port number specified: "
2240 << components
.back ()
2246 // Obtain the host name or ip address.
2247 if (stringToIpAddress (components
.front ()))
2248 server_info
.ip_address
= components
.front ();
2250 server_info
.host_name
= components
.front ();
2252 // Find known servers matching the specified information.
2253 vector
<compile_server_info
> known_servers
;
2254 get_all_server_info (s
, known_servers
);
2255 keep_common_server_info (server_info
, known_servers
);
2256 add_server_info (known_servers
, specified_servers
);
2258 // Resolve this host and add any information that is discovered.
2259 resolve_host (s
, server_info
, specified_servers
);
2260 } // Not specified by cert serial number
2261 } // Loop over --use-server options
2262 } // -- use-server specified
2263 } // Server information is not cached
2265 // Add the information, but not duplicates.
2266 add_server_info (specified_servers
, servers
);
2270 get_or_keep_trusted_server_info (
2271 systemtap_session
&s
,
2272 vector
<compile_server_info
> &servers
,
2276 // If we're filtering the list and it's already empty, then
2277 // there's nothing to do.
2278 if (keep
&& servers
.empty ())
2281 // We only need to obtain this once. This is a good thing(tm) since
2282 // obtaining this information is expensive.
2283 static vector
<compile_server_info
> trusted_servers
;
2284 if (trusted_servers
.empty ())
2286 // Maintain an empty entry to indicate that this search has been
2287 // performed, in case the search comes up empty.
2288 trusted_servers
.push_back (compile_server_info ());
2291 // Check the private database first.
2292 string cert_db_path
= private_ssl_cert_db_path (s
);
2293 get_server_info_from_db (s
, trusted_servers
, cert_db_path
);
2295 // Now check the global database.
2296 cert_db_path
= global_ssl_cert_db_path ();
2297 get_server_info_from_db (s
, trusted_servers
, cert_db_path
);
2299 // Without NSS, we can't determine whether a server is trusted.
2302 clog
<< "Unable to determine server trust as an SSL peer" << endl
;
2303 #endif // ! HAVE_NSS
2304 } // Server information is not cached
2308 // Filter the existing vector by keeping the information in common with
2309 // the trusted_server vector.
2310 keep_common_server_info (trusted_servers
, servers
);
2314 // Add the information, but not duplicates.
2315 add_server_info (trusted_servers
, servers
);
2320 get_or_keep_signing_server_info (
2321 systemtap_session
&s
,
2322 vector
<compile_server_info
> &servers
,
2326 // If we're filtering the list and it's already empty, then
2327 // there's nothing to do.
2328 if (keep
&& servers
.empty ())
2331 // We only need to obtain this once. This is a good thing(tm) since
2332 // obtaining this information is expensive.
2333 static vector
<compile_server_info
> signing_servers
;
2334 if (signing_servers
.empty ())
2336 // Maintain an empty entry to indicate that this search has been
2337 // performed, in case the search comes up empty.
2338 signing_servers
.push_back (compile_server_info ());
2341 // For all users, check the global database.
2342 string cert_db_path
= signing_cert_db_path ();
2343 get_server_info_from_db (s
, signing_servers
, cert_db_path
);
2345 // Without NSS, we can't determine whether a server is a trusted
2346 // signer. Issue a warning.
2348 clog
<< "Unable to determine server trust as a module signer" << endl
;
2349 #endif // ! HAVE_NSS
2350 } // Server information is not cached
2354 // Filter the existing vector by keeping the information in common with
2355 // the signing_server vector.
2356 keep_common_server_info (signing_servers
, servers
);
2360 // Add the information, but not duplicates.
2361 add_server_info (signing_servers
, servers
);
2366 // Obtain information about servers from the certificates in the given database.
2368 get_server_info_from_db (
2369 systemtap_session
&s
,
2370 vector
<compile_server_info
> &servers
,
2371 const string
&cert_db_path
2374 // Make sure the given path exists.
2375 if (! file_exists (cert_db_path
))
2378 cerr
<< "Certificate database '" << cert_db_path
<< "' does not exist."
2383 // Must predeclare these because of jumps to cleanup: below.
2384 PK11SlotInfo
*slot
= NULL
;
2385 CERTCertDBHandle
*handle
;
2386 PRArenaPool
*tmpArena
= NULL
;
2387 CERTCertList
*certs
= NULL
;
2388 CERTCertificate
*db_cert
;
2390 // Initialize the NSS libraries -- readonly
2391 SECStatus secStatus
= NSS_Init (cert_db_path
.c_str ());
2392 if (secStatus
!= SECSuccess
)
2394 cerr
<< "Error initializing NSS for " << cert_db_path
<< endl
;
2399 // Search the client-side database of trusted servers.
2400 slot
= PK11_GetInternalKeySlot ();
2401 handle
= CERT_GetDefaultCertDB();
2402 db_cert
= PK11_FindCertFromNickname (server_cert_nickname
, NULL
);
2405 // No trusted servers. Not an error. Just an empty list returned.
2409 // Here, we have one cert with the desired nickname.
2410 // Now, we will attempt to get a list of ALL certs
2411 // with the same subject name as the cert we have. That list
2412 // should contain, at a minimum, the one cert we have already found.
2413 // If the list of certs is empty (NULL), the libraries have failed.
2414 certs
= CERT_CreateSubjectCertList (NULL
, handle
, & db_cert
->derSubject
,
2415 PR_Now (), PR_FALSE
);
2416 CERT_DestroyCertificate (db_cert
);
2419 cerr
<< "Unable to query client certificate database: " << endl
;
2420 PORT_SetError (SEC_ERROR_LIBRARY_FAILURE
);
2425 // A memory pool to work in
2426 tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2429 cerr
<< "Out of memory:";
2433 for (CERTCertListNode
*node
= CERT_LIST_HEAD (certs
);
2434 ! CERT_LIST_END (node
, certs
);
2435 node
= CERT_LIST_NEXT (node
))
2437 compile_server_info server_info
;
2439 // The certificate we're working with.
2440 db_cert
= node
->cert
;
2442 // Get the host name. It is in the alt-name extension of the
2445 subAltName
.data
= NULL
;
2446 secStatus
= CERT_FindCertExtension (db_cert
,
2447 SEC_OID_X509_SUBJECT_ALT_NAME
,
2449 if (secStatus
!= SECSuccess
|| ! subAltName
.data
)
2451 cerr
<< "Unable to find alt name extension on server certificate: " << endl
;
2456 // Decode the extension.
2457 CERTGeneralName
*nameList
= CERT_DecodeAltNameExtension (tmpArena
, & subAltName
);
2458 SECITEM_FreeItem(& subAltName
, PR_FALSE
);
2461 cerr
<< "Unable to decode alt name extension on server certificate: " << endl
;
2466 // We're interested in the first alternate name.
2467 assert (nameList
->type
== certDNSName
);
2468 server_info
.host_name
= string ((const char *)nameList
->name
.other
.data
,
2469 nameList
->name
.other
.len
);
2470 // Don't free nameList. It's part of the tmpArena.
2472 // Get the serial number.
2473 ostringstream field
;
2474 field
<< hex
<< setfill('0') << right
;
2475 for (unsigned i
= 0; i
< db_cert
->serialNumber
.len
; ++i
)
2479 field
<< setw(2) << (unsigned)db_cert
->serialNumber
.data
[i
];
2481 server_info
.certinfo
= field
.str ();
2483 // Our results will at a minimum contain this server.
2484 add_server_info (server_info
, servers
);
2486 // Augment the list by querying all online servers and keeping the ones
2487 // with the same cert serial number.
2488 vector
<compile_server_info
> online_servers
;
2489 get_or_keep_online_server_info (s
, online_servers
, false/*keep*/);
2490 keep_server_info_with_cert_and_port (s
, server_info
, online_servers
);
2491 add_server_info (online_servers
, servers
);
2496 CERT_DestroyCertList (certs
);
2498 PK11_FreeSlot (slot
);
2500 PORT_FreeArena (tmpArena
, PR_FALSE
);
2507 get_or_keep_compatible_server_info (
2508 systemtap_session
&s
,
2509 vector
<compile_server_info
> &servers
,
2514 // If we're filtering the list and it's already empty, then
2515 // there's nothing to do.
2516 if (keep
&& servers
.empty ())
2519 // Remove entries for servers incompatible with the host environment
2520 // from the given list of servers.
2521 // A compatible server compiles for the kernel release and architecture
2522 // of the host environment.
2524 // Compatibility can only be determined for online servers. So, augment
2525 // and filter the information we have with information for online servers.
2526 vector
<compile_server_info
> online_servers
;
2527 get_or_keep_online_server_info (s
, online_servers
, false/*keep*/);
2529 keep_common_server_info (online_servers
, servers
);
2531 add_server_info (online_servers
, servers
);
2533 // Now look to see which ones are compatible.
2534 // The vector can change size as we go, so be careful!!
2535 for (unsigned i
= 0; i
< servers
.size (); /**/)
2537 // Retain empty entries.
2538 assert (! servers
[i
].empty ());
2540 // Check the target of the server.
2541 if (servers
[i
].sysinfo
!= s
.kernel_release
+ " " + s
.architecture
)
2543 // Target platform mismatch.
2544 servers
.erase (servers
.begin () + i
);
2548 // The server is compatible. Leave it in the list.
2551 #else // ! HAVE_AVAHI
2552 // Without Avahi, we can't obtain the target platform of the server.
2555 clog
<< "Unable to detect server compatibility" << endl
;
2562 keep_server_info_with_cert_and_port (
2563 systemtap_session
&s
,
2564 const compile_server_info
&server
,
2565 vector
<compile_server_info
> &servers
2568 assert (! server
.certinfo
.empty ());
2570 // Search the list of servers for ones matching the
2571 // serial number specified.
2572 // The vector can change size as we go, so be careful!!
2573 for (unsigned i
= 0; i
< servers
.size (); /**/)
2575 // Retain empty entries.
2576 if (servers
[i
].empty ())
2581 if (servers
[i
].certinfo
== server
.certinfo
&&
2582 (servers
[i
].port
== 0 || server
.port
== 0 ||
2583 servers
[i
].port
== server
.port
))
2585 // If the server is not online, then use the specified
2587 if (servers
[i
].port
== 0)
2588 servers
[i
].port
= server
.port
;
2592 // The item does not match. Delete it.
2593 servers
.erase (servers
.begin () + i
);
2597 // Obtain missing host name or ip address, if any.
2600 systemtap_session
& s
,
2601 compile_server_info
&server
,
2602 vector
<compile_server_info
> &resolved_servers
2605 // Either the host name or the ip address or both are already set.
2606 const char *lookup_name
;
2607 if (! server
.host_name
.empty ())
2609 // Use the host name to do the lookup.
2610 lookup_name
= server
.host_name
.c_str ();
2614 // Use the ip address to do the lookup.
2615 // getaddrinfo works on both host names and ip addresses.
2616 assert (! server
.ip_address
.empty ());
2617 lookup_name
= server
.ip_address
.c_str ();
2620 // Resolve the server.
2621 struct addrinfo hints
;
2622 memset(& hints
, 0, sizeof (hints
));
2623 hints
.ai_family
= AF_INET
; // AF_UNSPEC or AF_INET6 to force version
2624 struct addrinfo
*addr_info
= NULL
;
2625 int status
= getaddrinfo (lookup_name
, NULL
, & hints
, & addr_info
);
2627 // Failure to resolve will result in an appropriate error later if other
2633 // Loop over the results collecting information.
2634 for (const struct addrinfo
*ai
= addr_info
; ai
!= NULL
; ai
= ai
->ai_next
)
2636 if (ai
->ai_family
!= AF_INET
)
2637 continue; // Not an IPv4 address
2639 // Start with the info we were given.
2640 compile_server_info new_server
= server
;
2642 // Obtain the ip address.
2643 // Start with the pointer to the address itself,
2644 struct sockaddr_in
*ipv4
= (struct sockaddr_in
*)ai
->ai_addr
;
2645 void *addr
= & ipv4
->sin_addr
;
2647 // convert the IP to a string.
2648 char ipstr
[INET_ADDRSTRLEN
];
2649 inet_ntop (ai
->ai_family
, addr
, ipstr
, sizeof (ipstr
));
2650 new_server
.ip_address
= ipstr
;
2652 // Try to obtain a host name.
2653 char hbuf
[NI_MAXHOST
];
2654 status
= getnameinfo (ai
->ai_addr
, sizeof (*ai
->ai_addr
),
2655 hbuf
, sizeof (hbuf
), NULL
, 0,
2656 NI_NAMEREQD
| NI_IDN
);
2658 new_server
.host_name
= hbuf
;
2660 // Don't resolve to localhost or localhost.localdomain, unless that's
2661 // what was asked for.
2662 if ((new_server
.host_name
== "localhost" ||
2663 new_server
.host_name
== "localhost.localdomain") &&
2664 new_server
.host_name
!= server
.host_name
)
2667 // Add the new resolved server to the list.
2668 add_server_info (new_server
, resolved_servers
);
2673 freeaddrinfo (addr_info
); // free the linked list
2676 // At a minimum, return the information we were given.
2677 add_server_info (server
, resolved_servers
);
2684 // Avahi API Callbacks.
2685 //-----------------------------------------------------------------------
2686 struct browsing_context
{
2687 AvahiSimplePoll
*simple_poll
;
2688 AvahiClient
*client
;
2689 vector
<compile_server_info
> *servers
;
2693 extract_field_from_avahi_txt (const string
&label
, const string
&txt
)
2695 // Extract the requested field from the Avahi TXT.
2696 string prefix
= "\"" + label
;
2697 size_t ix
= txt
.find (prefix
);
2698 if (ix
== string::npos
)
2704 // This is the start of the field.
2705 string field
= txt
.substr (ix
+ prefix
.size ());
2707 // Find the end of the field.
2708 ix
= field
.find('"');
2709 if (ix
!= string::npos
)
2710 field
= field
.substr (0, ix
);
2716 void resolve_callback(
2717 AvahiServiceResolver
*r
,
2718 AVAHI_GCC_UNUSED AvahiIfIndex interface
,
2719 AVAHI_GCC_UNUSED AvahiProtocol protocol
,
2720 AvahiResolverEvent event
,
2724 const char *host_name
,
2725 const AvahiAddress
*address
,
2727 AvahiStringList
*txt
,
2728 AvahiLookupResultFlags flags
,
2729 AVAHI_GCC_UNUSED
void* userdata
) {
2732 const browsing_context
*context
= (browsing_context
*)userdata
;
2733 vector
<compile_server_info
> *servers
= context
->servers
;
2735 // Called whenever a service has been resolved successfully or timed out.
2738 case AVAHI_RESOLVER_FAILURE
:
2739 cerr
<< "Failed to resolve service '" << name
2740 << "' of type '" << type
2741 << "' in domain '" << domain
2742 << "': " << avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r
)))
2746 case AVAHI_RESOLVER_FOUND
: {
2747 char a
[AVAHI_ADDRESS_STR_MAX
], *t
;
2748 avahi_address_snprint(a
, sizeof(a
), address
);
2749 t
= avahi_string_list_to_string(txt
);
2751 // Save the information of interest.
2752 compile_server_info info
;
2753 info
.host_name
= host_name
;
2754 info
.ip_address
= strdup (a
);
2756 info
.sysinfo
= extract_field_from_avahi_txt ("sysinfo=", t
);
2757 info
.certinfo
= extract_field_from_avahi_txt ("certinfo=", t
);
2759 // Add this server to the list of discovered servers.
2760 add_server_info (info
, *servers
);
2766 avahi_service_resolver_free(r
);
2770 void browse_callback(
2771 AvahiServiceBrowser
*b
,
2772 AvahiIfIndex interface
,
2773 AvahiProtocol protocol
,
2774 AvahiBrowserEvent event
,
2778 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags
,
2781 browsing_context
*context
= (browsing_context
*)userdata
;
2782 AvahiClient
*c
= context
->client
;
2783 AvahiSimplePoll
*simple_poll
= context
->simple_poll
;
2786 // Called whenever a new services becomes available on the LAN or is removed from the LAN.
2789 case AVAHI_BROWSER_FAILURE
:
2790 cerr
<< "Avahi browse failed: "
2791 << avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b
)))
2793 avahi_simple_poll_quit(simple_poll
);
2796 case AVAHI_BROWSER_NEW
:
2797 // We ignore the returned resolver object. In the callback
2798 // function we free it. If the server is terminated before
2799 // the callback function is called the server will free
2800 // the resolver for us.
2801 if (!(avahi_service_resolver_new(c
, interface
, protocol
, name
, type
, domain
,
2802 AVAHI_PROTO_UNSPEC
, (AvahiLookupFlags
)0, resolve_callback
, context
))) {
2803 cerr
<< "Failed to resolve service '" << name
2804 << "': " << avahi_strerror(avahi_client_errno(c
))
2809 case AVAHI_BROWSER_REMOVE
:
2810 case AVAHI_BROWSER_ALL_FOR_NOW
:
2811 case AVAHI_BROWSER_CACHE_EXHAUSTED
:
2817 void client_callback(AvahiClient
*c
, AvahiClientState state
, AVAHI_GCC_UNUSED
void * userdata
) {
2819 browsing_context
*context
= (browsing_context
*)userdata
;
2820 AvahiSimplePoll
*simple_poll
= context
->simple_poll
;
2822 // Called whenever the client or server state changes.
2824 if (state
== AVAHI_CLIENT_FAILURE
) {
2825 cerr
<< "Avahi Server connection failure: "
2826 << avahi_strerror(avahi_client_errno(c
))
2828 avahi_simple_poll_quit(simple_poll
);
2833 void timeout_callback(AVAHI_GCC_UNUSED AvahiTimeout
*e
, AVAHI_GCC_UNUSED
void *userdata
) {
2834 browsing_context
*context
= (browsing_context
*)userdata
;
2835 AvahiSimplePoll
*simple_poll
= context
->simple_poll
;
2836 avahi_simple_poll_quit(simple_poll
);
2838 #endif // HAVE_AVAHI
2841 get_or_keep_online_server_info (
2842 systemtap_session
&s
,
2843 vector
<compile_server_info
> &servers
,
2847 // If we're filtering the list and it's already empty, then
2848 // there's nothing to do.
2849 if (keep
&& servers
.empty ())
2852 // We only need to obtain this once. This is a good thing(tm) since
2853 // obtaining this information is expensive.
2854 static vector
<compile_server_info
> online_servers
;
2855 if (online_servers
.empty ())
2857 // Maintain an empty entry to indicate that this search has been
2858 // performed, in case the search comes up empty.
2859 online_servers
.push_back (compile_server_info ());
2861 // Must predeclare these due to jumping on error to fail:
2863 vector
<compile_server_info
> raw_servers
;
2866 AvahiClient
*client
= NULL
;
2867 AvahiServiceBrowser
*sb
= NULL
;
2869 // Allocate main loop object.
2870 AvahiSimplePoll
*simple_poll
;
2871 if (!(simple_poll
= avahi_simple_poll_new()))
2873 cerr
<< "Failed to create Avahi simple poll object" << endl
;
2876 browsing_context context
;
2877 context
.simple_poll
= simple_poll
;
2878 context
.servers
= & raw_servers
;
2880 // Allocate a new Avahi client
2882 client
= avahi_client_new (avahi_simple_poll_get (simple_poll
),
2883 (AvahiClientFlags
)0,
2884 client_callback
, & context
, & error
);
2886 // Check whether creating the client object succeeded.
2889 cerr
<< "Failed to create Avahi client: "
2890 << avahi_strerror(error
)
2894 context
.client
= client
;
2896 // Create the service browser.
2897 if (!(sb
= avahi_service_browser_new (client
, AVAHI_IF_UNSPEC
,
2898 AVAHI_PROTO_UNSPEC
, "_stap._tcp",
2899 NULL
, (AvahiLookupFlags
)0,
2900 browse_callback
, & context
)))
2902 cerr
<< "Failed to create Avahi service browser: "
2903 << avahi_strerror(avahi_client_errno(client
))
2908 // Timeout after 2 seconds.
2910 avahi_simple_poll_get(simple_poll
)->timeout_new(
2911 avahi_simple_poll_get(simple_poll
),
2912 avahi_elapse_time(&tv
, 1000*2, 0),
2916 // Run the main loop.
2917 avahi_simple_poll_loop(simple_poll
);
2919 // Resolve each server discovered and eliminate duplicates.
2920 limit
= raw_servers
.size ();
2921 for (unsigned i
= 0; i
< limit
; ++i
)
2923 compile_server_info
&raw_server
= raw_servers
[i
];
2925 // Delete the domain, if it is '.local'
2926 string
&host_name
= raw_server
.host_name
;
2927 string::size_type dot_index
= host_name
.find ('.');
2928 assert (dot_index
!= 0);
2929 string domain
= host_name
.substr (dot_index
+ 1);
2930 if (domain
== "local")
2931 host_name
= host_name
.substr (0, dot_index
);
2933 // Add it to the list of servers, unless it is duplicate.
2934 resolve_host (s
, raw_server
, online_servers
);
2940 avahi_service_browser_free(sb
);
2943 avahi_client_free(client
);
2946 avahi_simple_poll_free(simple_poll
);
2947 #else // ! HAVE_AVAHI
2948 // Without Avahi, we can't detect online servers. Issue a warning.
2950 clog
<< "Unable to detect online servers" << endl
;
2951 #endif // ! HAVE_AVAHI
2952 } // Server information is not cached.
2956 // Filter the existing vector by keeping the information in common with
2957 // the online_server vector.
2958 keep_common_server_info (online_servers
, servers
);
2962 // Add the information, but not duplicates.
2963 add_server_info (online_servers
, servers
);
2967 // Add server info to a list, avoiding duplicates. Merge information from
2968 // two duplicate items.
2971 const compile_server_info
&info
, vector
<compile_server_info
>& target
2978 for (vector
<compile_server_info
>::iterator i
= target
.begin ();
2984 // Duplicate. Merge the two items.
2985 merge_server_info (info
, *i
);
2990 target
.push_back (info
);
2993 // Add server info from one vector to another.
2996 const vector
<compile_server_info
> &source
,
2997 vector
<compile_server_info
> &target
3000 for (vector
<compile_server_info
>::const_iterator i
= source
.begin ();
3004 add_server_info (*i
, target
);
3008 // Filter the vector by keeping information in common with the item.
3010 keep_common_server_info (
3011 const compile_server_info
&info_to_keep
,
3012 vector
<compile_server_info
> &filtered_info
3015 assert (! info_to_keep
.empty ());
3017 // The vector may change size as we go. Be careful!!
3018 for (unsigned i
= 0; i
< filtered_info
.size (); /**/)
3020 // Retain empty entries.
3021 if (filtered_info
[i
].empty ())
3026 if (info_to_keep
== filtered_info
[i
])
3028 merge_server_info (info_to_keep
, filtered_info
[i
]);
3032 // The item does not match. Delete it.
3033 filtered_info
.erase (filtered_info
.begin () + i
);
3038 // Filter the second vector by keeping information in common with the first
3041 keep_common_server_info (
3042 const vector
<compile_server_info
> &info_to_keep
,
3043 vector
<compile_server_info
> &filtered_info
3046 // The vector may change size as we go. Be careful!!
3047 for (unsigned i
= 0; i
< filtered_info
.size (); /**/)
3049 // Retain empty entries.
3050 if (filtered_info
[i
].empty ())
3056 for (unsigned j
= 0; j
< info_to_keep
.size (); ++j
)
3058 if (filtered_info
[i
] == info_to_keep
[j
])
3060 merge_server_info (info_to_keep
[j
], filtered_info
[i
]);
3065 // If the item was not found. Delete it. Otherwise, advance to the next
3070 filtered_info
.erase (filtered_info
.begin () + i
);
3074 // Merge two compile server info items.
3077 const compile_server_info
&source
,
3078 compile_server_info
&target
3081 if (target
.host_name
.empty ())
3082 target
.host_name
= source
.host_name
;
3083 if (target
.ip_address
.empty ())
3084 target
.ip_address
= source
.ip_address
;
3085 if (target
.port
== 0)
3086 target
.port
= source
.port
;
3087 if (target
.sysinfo
.empty ())
3088 target
.sysinfo
= source
.sysinfo
;
3089 if (target
.certinfo
.empty ())
3090 target
.certinfo
= source
.certinfo
;
3093 #if 0 // not used right now
3094 // Merge compile server info from one item into a vector.
3097 const compile_server_info
&source
,
3098 vector
<compile_server_info
> &target
3101 for (vector
<compile_server_info
>::iterator i
= target
.begin ();
3106 merge_server_info (source
, *i
);
3110 // Merge compile server from one vector into another.
3113 const vector
<compile_server_info
> &source
,
3114 vector
<compile_server_info
> &target
3117 for (vector
<compile_server_info
>::const_iterator i
= source
.begin ();
3120 merge_server_info (*i
, target
);