-
Notifications
You must be signed in to change notification settings - Fork 175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New option [libdefaults] block_dns = true to block all DNS queries. #1155
New option [libdefaults] block_dns = true to block all DNS queries. #1155
Conversation
@nicowilliams Is there an example of a libkrb5 test that sets krb5.conf that I can easily parrot? (I hope the existing tests don't behave differently depending on what is in /etc/krb5.conf or ~/.krb5/config?) |
@riastradh yes: |
116339b
to
b8a3b9b
Compare
krb5_set_error_message(context, ret, "DNS blocked when finding AD DC"); | ||
return ret; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lhoward do you want a config param here for specifying LDAP servers to use?
@@ -718,6 +728,13 @@ plugin_get_hosts(krb5_context context, | |||
{ | |||
struct plctx ctx = { type, kd, 0 }; | |||
|
|||
/* | |||
* XXX Need a way to pass this through -- unsure if any of this is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The plugins get the krb5_context
, so they get to check this parameter. I say let's trust them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do they? How does it get passed through here?
Lines 687 to 701 in 8ac4266
static KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL | |
plcallback(krb5_context context, | |
const void *plug, void *plugctx, void *userctx) | |
{ | |
const krb5plugin_service_locate_ftable *locate = plug; | |
struct plctx *plctx = userctx; | |
if (locate->minor_version >= KRB5_PLUGIN_LOCATE_VERSION_2) | |
return locate->lookup(plugctx, plctx->flags, plctx->type, plctx->kd->realm, 0, 0, add_locate, plctx->kd); | |
if (plctx->flags & KRB5_PLF_ALLOW_HOMEDIR) | |
return locate->old_lookup(plugctx, plctx->type, plctx->kd->realm, 0, 0, add_locate, plctx->kd); | |
return KRB5_PLUGIN_NO_HANDLE; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oy, yeah, most of our plugins do pass the context -- I'd just assumed we did it here too. You can add flags like KD_LARGE_MSG
and set them on the flags field of the instance of struct krb5_krbhst_data
that plctx->kd
points to.
I'm not sure that trying to get |
Why would getaddrinfo with AI_NUMERICHOST and no AI_CANONNAME ever do DNS lookups? Are there any serious implementations that do more than just parse the IP address (i.e., inet_pton) in that case? If there are, I could change it to call inet_pton explicitly instead -- somewhat more involved change but perhaps more confidence-inspiring.
No, that defeats the purpose -- my goal for #1154 is to guarantee that Heimdal leaks nothing into DNS queries. This is critical for location privacy. (Not sufficient -- that will also require #1151 -- but necessary.) |
If you don't pass an IP to
What I'm saying is that is that leaving out EDIT: But I'm ok with documenting that if you set |
What effect is AI_NUMERICHOST supposed to have, then? From POSIX:
I'm not sure if AI_CANONNAME actually matters when AI_NUMERICHOST is passed; I put it in there out of paranoia in case some clever implementation decided to look up a PTR record and then chase CNAMEs of the result. However, I suspect that part is unnecessary, because POSIX also prescribes:
Not quite. With just this change, yes: hostnames instead of IP addresses won't work (but will fail safe without DNS leaks) after this change. But after adding SOCKS proxy support (and/or HTTP CONNECT proxy support), hostnames can be passed through verbatim to the proxy without any DNS resolution beforehand. |
OK, thanks, that resolves my |
All network traffic to KDC goes through the SOCKS4a proxy if it is configured. This is deliberately kept simple -- and is not generalized to SOCKS4 or SOCKS5 or other types of proxies -- so it is easy to audit for network and DNS leaks. (SOCKS5 might be OK but takes more work to implement.) XXX Need to audit Heimdal for other kinds of traffic too. XXX Need to combine with heimdal#1155 to plug DNS leaks. XXX Need to figure out where the socks4a.c code should go. fix heimdal#1151
All network traffic to KDC goes through the SOCKS4a proxy if it is configured. This is deliberately kept simple -- and is not generalized to SOCKS4 or SOCKS5 or other types of proxies -- so it is easy to audit for network and DNS leaks. (SOCKS4 works in IP addresses, and so invites DNS leaks. SOCKS5 can be OK, if used judiciously, but takes more work to implement.) XXX Need to audit Heimdal for other kinds of traffic too outside libkrb5. Subsequent changes on this branch will address other parts of libkrb5. XXX Need to combine with heimdal#1155 to plug DNS leaks. XXX Need to figure out where the socks4a.c code should go. fix heimdal#1151
All network traffic to KDC goes through the SOCKS4a proxy if it is configured. This is deliberately kept simple -- and is not generalized to SOCKS4 or SOCKS5 or other types of proxies -- so it is easy to audit for network and DNS leaks. (SOCKS4 works in IP addresses, and so invites DNS leaks. SOCKS5 can be OK, if used judiciously, but takes more work to implement.) XXX Need to audit Heimdal for other kinds of traffic too outside libkrb5. Subsequent changes on this branch will address other parts of libkrb5. XXX Need to combine with heimdal#1155 to plug DNS leaks. XXX Need to figure out where the socks4a.c code should go. fix heimdal#1151
b8a3b9b
to
5c9f0de
Compare
Is this ready? It's marked draft. |
All network traffic to KDC goes through the SOCKS4a proxy if it is configured. This is deliberately kept simple -- and is not generalized to SOCKS4 or SOCKS5 or other types of proxies -- so it is easy to audit for network and DNS leaks. (SOCKS4 works in IP addresses, and so invites DNS leaks. SOCKS5 can be OK, if used judiciously, but takes more work to implement.) XXX Need to audit Heimdal for other kinds of traffic too outside libkrb5. Subsequent changes on this branch will address other parts of libkrb5. XXX Need to combine with heimdal#1155 to plug DNS leaks. XXX Need to figure out where the socks4a.c code should go. fix heimdal#1151
Other than the conflict resolution needed since merging #1206 (should be quick & easy), this doesn't have any automatic tests at the moment. I manually tested it, and verified no DNS queries with ktrace, back when I drafted it originally. Up to you to decide whether that's acceptable! |
All network traffic to KDC goes through the SOCKS4a proxy if it is configured. This is deliberately kept simple -- and is not generalized to SOCKS4 or SOCKS5 or other types of proxies -- so it is easy to audit for network and DNS leaks. (SOCKS4 works in IP addresses, and so invites DNS leaks. SOCKS5 can be OK, if used judiciously, but takes more work to implement.) XXX Need to audit Heimdal for other kinds of traffic too outside libkrb5. Subsequent changes on this branch will address other parts of libkrb5. XXX Need to combine with heimdal#1155 to plug DNS leaks. XXX Need to figure out where the socks4a.c code should go. fix heimdal#1151
To test this sort of thing we'd really need to use containers in the tests (unless already running in a container) so we can start a DNS server. |
All network traffic to KDC goes through the SOCKS4a proxy if it is configured. This is deliberately kept simple -- and is not generalized to SOCKS4 or SOCKS5 or other types of proxies -- so it is easy to audit for network and DNS leaks. (SOCKS4 works in IP addresses, and so invites DNS leaks. SOCKS5 can be OK, if used judiciously, but takes more work to implement.) XXX Need to audit Heimdal for other kinds of traffic too outside libkrb5. Subsequent changes on this branch will address other parts of libkrb5. XXX Need to combine with heimdal#1155 to plug DNS leaks. XXX Need to figure out where the socks4a.c code should go. fix heimdal#1151
Not really -- a good test would be to make some krb5_* or GSS-API calls in an executable program that defines the getaddrinfo symbol to call abort() if it doesn't have AI_NUMERICHOST|AI_NUMERICSERV set (and to call inet_pton otherwise to implement the usual functionality). It's not quite the same audit as ktracing and filtering for networking syscalls, but it should work on any elven platform. |
Documented and verified, not yet implemented.
If block_dns is set, call getaddrinfo with AI_NUMERICHOST set and AI_CANONNAME clear. Some paths may not have set AI_CANONNAME, but it's easier to audit this way when the getaddrinfo prelude is uniform across call sites, and the compiler can optimize it away.
Exception: In lib/kafs/common.c, we don't have a krb5_context in which to check.
Previously, the hostname was initialized to `localhost'. If it was not cleared by init_syslog, init_logger_addr (via openlog) would query gethostbyname to find the IP address of `localhost', which will essentially always be 127.0.0.1. But if it was cleared by init_syslog, init_logger_addr would return 127.0.0.1 anyway. This way, it always returns 127.0.0.1 in the event of no init_syslog call, and avoids a DNS lookup. You can always force a DNS lookup by passing `localhost' to init_syslog explicitly, of course. I'm not sure if anything even uses this as a fallback in Heimdal, but let's avoid leaving a rake to step on.
5c9f0de
to
90bfc48
Compare
I'm not sure that symbol interposition will work reliably on all platforms (Windows/MSYS/Cygwin?), but, yes, it's an idea. The fact that we generally can't rely on DNS servers on non-standard ports when using the system resolver means we eventually have to aim for a container-ish test scheme. An alternative would be to have our own resolver (which is a scary prospect, though it would have a number of benefits, but mainly it would be a tremendous time suck when we already don't have the time for it). |
If you're happy accepting this change without automatic tests, fine by me -- can add automatic tests in a subsequent change. |
Maybe we can have a very simple interposition-based test after all. If interposition fails then no problem: the test passes, and if interposition succeeds then the test will work. And we can add a test that interposition does work so that we can know from the test logs. |
We build variants of kinit and test_acquire_cred that define their own symbols rk_dns_lookup, gethostbyname, gethostbyname2, and getaddrinfo to print a message and abort. For getaddrinfo, we abort only if the caller failed to specify AI_NUMERICHOST; otherwise we use dlsym(RTLD_NEXT, "getaddrinfo") instead. The new test tests/gss/check-nodns is like tests/gss/check-basic, but uses kinit_auditdns and test_acquire_cred_auditdns to verify that no DNS resolution happens. This test should work and be effective on ELF platforms where the getaddrinfo function is implemented by the symbol `getaddrinfo'. On non-ELF platforms it may not be effective -- and on platforms where the getaddrinfo function is implemented by another symbol (like `__getaddrinfo50') it may not work, but we can cross that bridge when we come to it. Verified manually that the test fails, with the expected error message and abort, without `block_dns = yes' in krb5-nodns.conf. No automatic test of the mechanism for now because it might not work on some platforms. XXX check-nodns.in is copypasta of check-basic.in, should factor out the common parts so they don't get out of sync.
I drafted an automatic test that uses the symbol interposition technique I described above:
This test could stand some tidying, so if you want to merge the bulk of the branch first and defer the test to another PR to be merged separately, that would be reasonable. |
All network traffic to KDC goes through the SOCKS4a proxy if it is configured. This is deliberately kept simple -- and is not generalized to SOCKS4 or SOCKS5 or other types of proxies -- so it is easy to audit for network and DNS leaks. (SOCKS4 works in IP addresses, and so invites DNS leaks. SOCKS5 can be OK, if used judiciously, but takes more work to implement.) XXX Need to audit Heimdal for other kinds of traffic too outside libkrb5. Subsequent changes on this branch will address other parts of libkrb5. XXX Need to combine with heimdal#1155 to plug DNS leaks. XXX Need to figure out where the socks4a.c code should go. fix heimdal#1151
@riastradh it's been merged. Arguably |
Thanks! The two main things that are critical to test are:
Copying tests/gss/check-basic seemed like an easier path to testing both of those, with a minimum of unnecessary other testing, than anything I found under tests/kdc. But I'm not attached to this arrangement; feel free to move it around. |
if(context->srv_lookup) { | ||
if (krb5_config_get_bool(context, NULL, "libdefaults", "block_dns", | ||
NULL) && | ||
context->srv_lookup) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we running the following code only if block_dns
is true
? Correct me if I’m wrong, but shouldn’t this condition (and the following two) be the other way round?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ll submit a PR to fix this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops -- yes, I think I got this backwards, thanks for the review!
fix #1154
(draft pending automatic tests)