aboutsummaryrefslogtreecommitdiff
path: root/rpcapd/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'rpcapd/daemon.c')
-rw-r--r--rpcapd/daemon.c100
1 files changed, 91 insertions, 9 deletions
diff --git a/rpcapd/daemon.c b/rpcapd/daemon.c
index dc92c0ac..88c72b96 100644
--- a/rpcapd/daemon.c
+++ b/rpcapd/daemon.c
@@ -144,11 +144,14 @@ static int rpcapd_discard(SOCKET sock, SSL *, uint32 len);
static void session_close(struct session *);
int
-daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, SSL *ssl, int isactive, int nullAuthAllowed, int uses_ssl)
+daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out,
+ int isactive, char *passiveClients, int nullAuthAllowed, int uses_ssl)
{
struct daemon_slpars pars; // service loop parameters
char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
char errmsgbuf[PCAP_ERRBUF_SIZE + 1]; // buffer for errors to send to the client
+ int host_port_ok;
+ SSL *ssl = NULL;
int nrecv;
struct rpcap_header header; // RPCAP message general header
uint32 plen; // payload length from header
@@ -172,14 +175,6 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, SSL *ssl, int isacti
struct timeval tv; // maximum time the select() can block waiting for data
int retval; // select() return value
- // Set parameters structure
- pars.sockctrl_in = sockctrl_in;
- pars.sockctrl_out = sockctrl_out;
- pars.ssl = ssl;
- pars.protocol_version = 0; // not yet known
- pars.isactive = isactive; // active mode
- pars.nullAuthAllowed = nullAuthAllowed;
-
// We don't have a thread yet.
threaddata.have_thread = 0;
//
@@ -199,6 +194,86 @@ daemon_serviceloop(SOCKET sockctrl_in, SOCKET sockctrl_out, SSL *ssl, int isacti
*errbuf = 0; // Initialize errbuf
+#ifdef HAVE_OPENSSL
+ //
+ // We have to upgrade to TLS as soon as possible, so that the
+ // whole protocol goes through the encrypted tunnel, including
+ // early error messages.
+ //
+ // Even in active mode, the other end has to initiate the TLS
+ // handshake as we still are the server as far as TLS is concerned,
+ // so we don't check isactive.
+ //
+ if (uses_ssl)
+ {
+ ssl = ssl_promotion_rw(1, pars.sockctrl_in, pars.sockctrl_out, errbuf, PCAP_ERRBUF_SIZE);
+ if (! ssl)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "TLS handshake on control connection failed: %s",
+ errbuf);
+ goto end;
+ }
+ }
+#endif
+
+ // Set parameters structure
+ pars.sockctrl_in = sockctrl_in;
+ pars.sockctrl_out = sockctrl_out;
+ pars.ssl = ssl;
+ pars.protocol_version = 0; // not yet known
+ pars.isactive = isactive; // active mode
+ pars.nullAuthAllowed = nullAuthAllowed;
+
+ //
+ // We have a connection.
+ //
+ // If it's a passive mode connection, check whether the connecting
+ // host is among the ones allowed.
+ //
+ // In either case, we were handed a copy of the host list; free it
+ // as soon as we're done with it.
+ //
+ if (pars.isactive)
+ {
+ // Nothing to do.
+ free(passiveClients);
+ passiveClients = NULL;
+ }
+ else
+ {
+ struct sockaddr_storage from;
+ socklen_t fromlen;
+
+ //
+ // Get the address of the other end of the connection.
+ //
+ fromlen = sizeof(struct sockaddr_storage);
+ if (getpeername(pars.sockctrl_in, (struct sockaddr *)&from,
+ &fromlen) == -1)
+ {
+ sock_geterror("getpeername(): ", errmsgbuf, PCAP_ERRBUF_SIZE);
+ if (rpcap_senderror(pars.sockctrl_out, pars.ssl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+
+ //
+ // Are they in the list of host/port combinations we allow?
+ //
+ host_port_ok = (sock_check_hostlist(passiveClients, RPCAP_HOSTLIST_SEP, &from, errmsgbuf, PCAP_ERRBUF_SIZE) == 0);
+ free(passiveClients);
+ passiveClients = NULL;
+ if (!host_port_ok)
+ {
+ //
+ // Sorry, you're not on the guest list.
+ //
+ if (rpcap_senderror(pars.sockctrl_out, pars.ssl, 0, PCAP_ERR_HOSTNOAUTH, errmsgbuf, errbuf) == -1)
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ }
+
//
// The client must first authenticate; loop until they send us a
// message with a version we support and credentials we accept,
@@ -880,6 +955,13 @@ end:
session = NULL;
}
+#ifdef HAVE_OPENSSL
+ if (ssl)
+ {
+ SSL_free(ssl);
+ }
+#endif
+
// Print message and return
rpcapd_log(LOGPRIO_DEBUG, "I'm exiting from the child loop");
rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);