| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| |
|
| |
|
| |
|
|
|
|
|
|
|
| |
This makes it harder to run the Windows daemon our of memory.
It also addresses Include Security issue F1: [libpcap] Remote Packet
Capture Daemon (RPCAPD) Integer Overflow Leads to Heap Buffer Overflow.
|
|
|
|
|
|
|
|
|
| |
Using the same variable for the remaining request length and the reply
length is confusing at best and can cause errors at worst (if the
request had extra stuff at the end, so that the variable is non-zero).
This addresses Include Security issue I8: [libpcap] Remote Packet
Capture Daemon Parameter Reuse.
|
|
|
|
|
|
|
|
| |
You shouldn't be able to ask a server to open a remote device on some
*other* server; just open it yourself.
This addresses Include Security issue F13: [libpcap] Remote Packet
Capture Daemon Allows Opening Capture URLs.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
"no such user" tells the client that the user ID isn't valid and,
therefore, that it needn't bother trying to do password cracking for
that user ID; just saying that the authentication failed dosn't give
them that hint.
This resolves the third problem in Include Security issue F11: [libpcap]
Remote Packet Capture Daemon Multiple Authentication Improvements.
The Windows LogonUser() API returns ERROR_LOGON_FAILURE for both cases,
so the Windows code doesn't have this issue. Just return the same
"Authentication failed" message on Windows to the user.
For various authentication failures *other* than "no such user" and
"password not valid", log a message, as there's a problem that may need
debugging. We don't need to tell the end user what the problem is, as
they may not bother reporting it and, even if they do, they may not give
the full error message.
|
|
|
|
|
|
|
|
| |
It can fail, so make sure it doesn't before comparing its result with
the password.
This addresses Include Security issue F12: [libpcap] Remote Packet
Capture Daemon Null Pointer Dereference Denial of Service.
|
|
|
|
|
| |
Explicitly check for the characters we care about, to make it clearer
what we're doing.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Some of them are locale-dependent, and all of them run the risk of
failing if you hand them a char with the 8th bit set.
Define our own locale-independent macros that can be handed any integral
value.
Don't include <ctype.h>.
This should address the issue in GitHub pull request #839, and should
also catch any (highly unlikely) cases in which something other than
Boring Old Space And Tab and, sometimes, CR and LF are treated as white
space. (No, we don't want FF or VT treated as white space.)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Require Visual Studio 2015 or later; fail if we don't have it, and
remove checks for older versions.
That means we have C99-compliant snprintf() and vsnprintf(); require
them when configuring for UN*X, and then use them directly, rather than
having wrappers for systems lacking them.
If we're using MSVC, skip the tests for options to request C99
compatibility - either we have VS 2015, which is sufficient, or we
don't, in which case we fail.
|
|
|
|
|
|
|
|
|
| |
It's like pcap_fmt_errmsg_for_errno(), but for Windows error codes.
Use it, rather than calling pcap_win32_err_to_str() and then formatting
a message with pcap_strerror().
Clean up some error messages while we're at it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This might make it a bit cleaner to handle new authentication types;
clients will still have to check for PCAP_ERR_AUTH with particular error
strings to detect "that authentication type isn't supported by the
server", but at least they can check first for
PCAP_ERR_AUTH_TYPE_NOTSUP.
Also add PCAP_ERR_AUTH_FAILED for authentication failures and
PCAP_ERR_TLS_REQUIRED for "the server requires TLS". PCAP_ERR_AUTH is
used for all other errors, including internal errors.
While we're at it, fix one case where the wrong error code was returned
for "set sampling" request errors.
|
|
|
|
|
| |
If we haven't received a request containing a version number, send the
error reply with a version of 0.
|
|
|
|
|
|
| |
That makes brute-forcing harder, as a brute-forcing client isn't told
that it can give up on a given user name. (Perhaps it can guess that
based on how quickly we say "no".)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
During the authentication phase, which begins when the connection is
made and ends when an authentication reply is received or the connection
is closed, require that all request have a version number of 0, and
accept version 0 in that phase, regardless of whether we support it once
we're authenticated. That means the messages from the client will not
be rejected any server with an "unsupported version" error, and also
means we can distinguish between a plaintext request and a TLS handshake
message.
Have the server send out authentication replies with a payload giving
the minimum and maximum version number supported by the server. Have
the client accept authentication replies whether or not they have that
additional information; if the reply has no payload, the server is
assumed to support only version 0. This means that old servers that
don't supply that information, and new servers that do, can be handled
by the new client code; old clients discard extra payload, and only
support version 0 (no servers or clients supporting versions other than
0 have been released, yet), so they can also handle both old and new
servers.
The client then uses that information (sent or implied) to try to find
the highest version that it and the server supports. If there is no
such version, it's impossible for the client and server to communicate
further, so the client just reports an error to its caller and gives up.
If there *is* such a version, the client then uses it in all subsequent
requests, and the server replies with the version in the request.
For data packets, the version used in the "start capture" request is
used.
This avoids timeouts or dropped connections with old servers due to the
initial request having an unsupported version number, and means that the
negotiation never requires two authentication requests.
|
| |
|
|
|
|
|
|
|
|
|
| |
Before we shut down the socket, send a shutdown alert. That should
prevent some cases where errors are reported when they shouldn't be (it
was happening if I did a --list-remote-interfaces in tcpdump).
While we're at it, do the SSL shutdown *before* closing the main active
socket; we were doing it *after*. Also, fix a comment.
|
| |
|
|
|
|
|
|
| |
Removing it would be a *protocol* change, and there are clients out
there that expect the open reply to be 8 bytes long. Just continue to
send a zero over the wire.
|
|
|
|
|
|
| |
The Single UNIX Specification says you should use pthread_sigmask(), not
sigprocmask(), in multithreaded programs, and rpcapd is a multithreaded
program.
|
|
|
|
|
|
|
| |
And make a getaddrinfo() failure an error, so that they're logged.
("The host trying to connect to us is not in the list" is not an error;
we tell the client about it, but we don't have a reason to log it.)
|
| |
|
|
|
|
|
| |
If there was an error, a message should already have been logged at
priority LOGPRIO_ERROR; logging it again at LOGPRIO_DEBUG isn't useful.
|
| |
|
|
|
|
|
|
|
|
|
| |
There's no guarantee that we can arrange to wait for more than one byte
while peeking into the socket.
This means that a client sending a version 22 authentication request
will make us think they're requesting TLS, but They. Shouldn't. Be.
Doing. That.
|
|
|
|
|
|
|
|
|
|
|
| |
That way, the failure modes for those are a bit less ugly; for the
former, you'll get a TLS handshake failure error, and for the latter,
you'll get a "server requires TLS" authentication error, rather than
some ugly protocol error from rpcapd in the former case and TLS in the
latter case.
To make this work, we just have to make sure that we never use protocol
version 22. Do so.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
On UN*X, instead of just cancelling the thread doing the capture, send
it a SIGUSR1, to break out of a blocking call in libpcap, and wait for
the thread to end with pthread_join(). Don't make it a detached thread,
so that we can do this. In that thread, block SIGUSR1 unless we're in a
pcap call, so that other system calls aren't disturbed by the SIGUSR1.
(We were already doing things similarly on Windows.) Do all session
cleanup in the main thread, after the thread completes. That way, we
don't run the risk of trying to do cleanup in both threads.
Put the thread information into the session structure, rather than
having a separate structure.
In session_close(), if there's a thread, tell it to finish and wait for
it to finish, before cleaning up the session. Use session_close() in
all cases where we want to finish with a capture session.
|
| |
|
|
|
|
| |
Add a copyright notice to rpcapd/log.{c,h} while we're at it.
|
|
|
|
|
|
|
|
|
| |
It's not a boolean with 0 meaning "host not authorized" and 1 meaning
"host authorized"; it's negative if we shouldn't let them connect, with
-1 meaning "not in the host list" and -2 meaning "an error occurred in
the process of checking", and non-negative if we should let them
connect, with 0 meaning "they're in the host list" and 1 meaning "the
host list is empty, so we're letting everybody in".
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
If we do the accept() ourselves, we get only one socket on which we send
and from which we receive messages.
If we're run by an inetd-compatible daemon, it does the accept() and
gets only one socket, which it proceeds to dup and hand to us as the
standard input, output, and error; we really only need to use one of
them.
In the latter case, just dup the standard input, and then close the
standard input, output, and error as we dup a descriptor for /dev/null
to them.
In both cases, just hand the one control socket to daemon_serviceloop().
Close it in daemon_serviceloop() before it returns, rather than in the
caller after it returns.
Only free the SSL structure for the control connection right before we
close the socket for the control connection; we don't need to free it
when we close a data connection.
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
| |
We don't need N different places all doing their own calls to
FormatMessage(); centralize it in pcap_win32_err_to_str(), now in
fmtutils.c for use in rpcapd as well as libpcap.
Merge in some fixes from the code in sock_fmterror().
|
| |
|
| |
|
| |
|
| |
|
|
|
|
| |
Needs more work; this should fix compile errors for now.
|
|
|
|
|
|
|
|
| |
Rename the sock_copy structure to params_copy, and add a pointer to the
host list to it. Make the copy, stuff a pointer to it into the
allocated structure, and do the appropriate freeing on errors; in the
initial routine of the service thread, pass on the host list pointer
from the structure.
|
|
|
|
|
|
|
|
|
| |
Have routines that set them, given a pointer to the name. Use that in
rpcapd, rather than copying to a buffer (you don't need to copy strings
from argv - unless you're going to overwrite them, which you probably
shouldn't do).
This removes a requirement for the platform to define PATH_MAX.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
That:
1) arranges that it's done only in one code path;
2) arranges that it not be done in the main connection-accepting
thread/process if this isn't an inetd-style daemon;
3) means that we're doing the host/port list checking in
inetd-style daemons - we weren't doing it before;
4) means that we're doing both of them after we've turned off
non-blocking mode on Windows, not before - doing it before
may cause the SSL setup and sending a host/port list check
error not to work (as we won't block waiting for input or
waiting for buffer space to be available for output).
Fix the file descriptor handling for inetd-style daemons while we're at
it; we should redirect the standard error to /dev/null - it's not
guaranteed to, for example, go to a daemon that reads your error
messages and logs them, and it could be going over the connection, which
would be a problem.
Close the control socket with sock_close() after daemon_serviceloop()
returns, in case shutting down the write side is necessary to have the
connection shut down cleanly.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
That:
1) avoids doing any initialization if we end up logging to the
standard error
and
2) means that the first time we log to the "system log" we'll
attempt to initialize it, even if we've logged to the
standard error earlier.
|
|
|
|
|
| |
Only if it thinks it's being run as a daemon should rpcapd log to the
system log.
|
|
|
|
|
|
|
|
| |
That's what you want for daemons, as the standard error might not go
anywhere or, worse, might go to the control socket.
Also have a -D flag to control whether to log debug messages or not; the
default is "not".
|