{"action":"created","issue":{"url":"https://api.github.com/repos/paramiko/paramiko/issues/915","repository_url":"https://api.github.com/repos/paramiko/paramiko","labels_url":"https://api.github.com/repos/paramiko/paramiko/issues/915/labels{/name}","comments_url":"https://api.github.com/repos/paramiko/paramiko/issues/915/comments","events_url":"https://api.github.com/repos/paramiko/paramiko/issues/915/events","html_url":"https://github.com/paramiko/paramiko/issues/915","id":211545551,"number":915,"title":"hostname canonicalization with GSSAPI","user":{"login":"pseudometric","id":1487528,"avatar_url":"https://avatars1.githubusercontent.com/u/1487528?v=4","gravatar_id":"","url":"https://api.github.com/users/pseudometric","html_url":"https://github.com/pseudometric","followers_url":"https://api.github.com/users/pseudometric/followers","following_url":"https://api.github.com/users/pseudometric/following{/other_user}","gists_url":"https://api.github.com/users/pseudometric/gists{/gist_id}","starred_url":"https://api.github.com/users/pseudometric/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pseudometric/subscriptions","organizations_url":"https://api.github.com/users/pseudometric/orgs","repos_url":"https://api.github.com/users/pseudometric/repos","events_url":"https://api.github.com/users/pseudometric/events{/privacy}","received_events_url":"https://api.github.com/users/pseudometric/received_events","type":"User","site_admin":false},"labels":[{"id":120561399,"url":"https://api.github.com/repos/paramiko/paramiko/labels/Bug","name":"Bug","color":"a04040","default":false},{"id":60522311,"url":"https://api.github.com/repos/paramiko/paramiko/labels/Needs%20investigation","name":"Needs investigation","color":"fad8c7","default":false},{"id":121094372,"url":"https://api.github.com/repos/paramiko/paramiko/labels/Needs%20patch","name":"Needs patch","color":"fad8c7","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2017-03-02T23:03:26Z","updated_at":"2017-09-13T17:04:54Z","closed_at":"2017-09-13T17:04:54Z","author_association":"NONE","body":"\r\nIn `Transport.set_gss_host()`, there is this:\r\n\r\n```\r\n# We need the FQDN to get this working with SSPI\r\nself.gss_host = socket.getfqdn(gss_host)\r\n```\r\n\r\nThis is a common mistake in GSSAPI programming, and a misunderstanding. I'm sure the author needed to canonicalize the hostname in order to get his test case working with SSPI, but that does not mean it's the right thing to do in general.\r\n\r\nWhen using hostbased-service names with GSSAPI (type GSS_C_NT_HOSTBASED_SERVICE) — the usual case — GSSAPI clients should pass the hostname exactly as provided by the user. It should *not* be canonicalized or altered in any way, because Kerberos implementations have their own name canonicalization policies when handling this name type, and it may not match. For example, if you are using MIT Kerberos and you set libdefaults.rdns = no in krb5.conf, this turns off the reverse-address component of hostname canonicalization — but the Python socket.getfqdn() still does it.\r\n\r\nAt a well-administered Kerberos site, the DNS and Kerberos principal names are coordinated, together with the local name canonicalization policy, so that everything works as expected. Applications that take it upon themselves to alter the hostname before passing it to GSSAPI will just break that correspondence in some cases, and not work properly.\r\n\r\nIt *is* useful to have a parameter like `gss_host`, so that users can override the hostname in cases where the site setup is wrong and names don't match. (Compare GSSAPIServerIdentity in OpenSSH. Even more useful is an option to pass a literal Kerberos principal name instead, bypassing the hostname entirely and providing complete flexibility) But, that would be the opposite of the current treatment of `gss_host`: it would *not* be canonicalized if passed. Worse, the current behavior of `gss_host` is inconsistent in this regard anyway: calling `set_gss_host()` canonicalizes, while passing `gss_host` as a parameter to the Transport init() routine does not, giving confusing behavior. It means that I can specify the literal GSSAPI hostname and fix the problem with this:\r\n\r\n```\r\n  t = paramiko.Transport((server, 22))\r\n  t.connect(username = os.environ['LOGNAME'],\r\n            gss_host = server,\r\n            gss_auth = True,\r\n            gss_kex  = True)\r\n```\r\n\r\nbut not with this:\r\n\r\n```\r\n  ssh = paramiko.SSHClient()\r\n  ssh.connect( hostname = server,\r\n               gss_host = server,\r\n               gss_auth = True,\r\n               gss_kex  = True)\r\n```\r\n\r\nbecause the latter calls `set_gss_host()` and canonicalizes, while the former does not.\r\n\r\nFinally, the code as-is is not in fact even right for SSPI. Windows behaves like MIT Kerberos with libdefaults.rdns = no: it does not reverse-map addresses, rather only resolving aliases (DNS CNAMEs) — so it does not match the behavior of socket.fqdn().\r\n\r\nSince fixing the discrepancy in the behavior the kwarg `gss_host` vs `set_gss_host()` means that some existing use cases are bound to break, I would take the simplest route to fixing this: remove the canonicalization entirely, and tell people that if they need to change the hostname before passing it to Paramiko to deal with broken DNS/Kerberos correspondence at their site, they'll have to do that themselves.\r\n\r\nIf you think it's more important to preserve the canonicalization, then I suggest:\r\n\r\n1. Fix the inconsistency by ensuring that `gss_host` is always canonicalized, regardless of how it's given.\r\n\r\n1. Add a `gss_canonicalize` option controlling that, default true, preserving (some of) the current behavior. Setting this to false will give the more generally correct behavior, and also allow users to override the hostname effectively if needed.\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/paramiko/paramiko/issues/comments/329233246","html_url":"https://github.com/paramiko/paramiko/issues/915#issuecomment-329233246","issue_url":"https://api.github.com/repos/paramiko/paramiko/issues/915","id":329233246,"user":{"login":"bitprophet","id":6088,"avatar_url":"https://avatars2.githubusercontent.com/u/6088?v=4","gravatar_id":"","url":"https://api.github.com/users/bitprophet","html_url":"https://github.com/bitprophet","followers_url":"https://api.github.com/users/bitprophet/followers","following_url":"https://api.github.com/users/bitprophet/following{/other_user}","gists_url":"https://api.github.com/users/bitprophet/gists{/gist_id}","starred_url":"https://api.github.com/users/bitprophet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bitprophet/subscriptions","organizations_url":"https://api.github.com/users/bitprophet/orgs","repos_url":"https://api.github.com/users/bitprophet/repos","events_url":"https://api.github.com/users/bitprophet/events{/privacy}","received_events_url":"https://api.github.com/users/bitprophet/received_events","type":"User","site_admin":false},"created_at":"2017-09-13T17:04:54Z","updated_at":"2017-09-13T17:04:54Z","author_association":"OWNER","body":"Let's assume #1063 fixes this; please comment if it does not and we can reopen."}}
{"actor":{"display_login":"bitprophet"}}