capabilities from the ndhc master process.
Privsep is now complete. The only notable improvement from before is that
exploitation of ndhc would only allow an attacker to open raw sockets,
bind sockets to ports < port 1024, and create broadcast sockets on the
interface that ndhc is performing dhcp on rather than on all interfaces.
However, this seems like a worthwhile change; note that it was already
impossible for an attacker to sniff packets on any interfaces (as that
requires CAP_NET_ADMIN, which was always separated to ifch).
its original state by zeroing out the data that was appended to the buffer
by the failed snprintf.
This trick allows ifcmd_raw() to never fail in a way that would attach
corrupt commands to the output buffer.
The old functions were harder to audit. The new ones factor out most
of the work into a common ifcmd_raw() helper, and make sure to perform
the updates atomically wrt the output buffer.
snprintf is used heavily, as the C99 semantics should be on any targetted
system.
The atomicity will be improved in the next patch, allowing the number
of command buffers to be reduced.
RFC4361 requires clients to send a clientid, and specifies that by default
that clientid should be a combination of a machine-static DUID and an
interface-static IAID.
There are several RFC-compliant DUIDs. ndhc uses RFC6355's DUID-UUID,
but chooses not to follow RFC4122 for the UUID and instead simply uses
random bytes from its combined Tausworthe PRNG.
RFC4122 is excessively complex, and 128-bit random values are more than
sufficiently collision-resistant on even large DHCP segments.
ndhc requires a read/writable directory to store the DUID/IAID states. By
default this directory is /etc/ndhc. It exists outside the chroot. The DUID
will be stored in a single file, DUID. The IAIDs exist per-interface and are
stored in files with names similar to IAID-xx:xx:xx:xx:xx:xx, where the xx
values are replaced by the Ethernet hardware address of the interface.
If it is impossible to read or store the DUIDs or IAIDs, ndhc will
fail at start time before it performs any network activity or forks any
subprocesses.
If the host system lacks volatile storage, then a clientid should manually
be specified using the -c or --clientid command arguments.
All this entails is that ndhc needs to check to make sure that if the remote
server sends a dhcp packet with a client identifier, the client identifier
of that packet matches the client identifier that ndhc uses to identify
itself.
If the remote server does not attach a client identifier to its dhcp packets,
then the behavior of ndhc does not change.
the same value. Remove it, and introduce a slightly less useless
conditional that prevents a possible one-byte-read past the end of
packet.
This bug could possibly cause ndhc to segfault on some architectures
with extremely unlikely memory layouts and a very pathological crafted
input packet.
types are almost identical (same number of fields, each field has the
same length), so the code worked anyway, but nlattr and rtattr are
distinct.
nlattr is the type/length part of the nlmsg header. rtattr is the
type/length part of the individual rt attribute items attached after
a nlmsg.
Use the correct rtattr type, and use the standard macros where appropriate.