diff --git a/.evergreen/run-enterprise-auth-tests.sh b/.evergreen/run-enterprise-auth-tests.sh index cc2c8dce0..030a0ab02 100644 --- a/.evergreen/run-enterprise-auth-tests.sh +++ b/.evergreen/run-enterprise-auth-tests.sh @@ -18,6 +18,7 @@ if [ ${PLATFORM} != "Java" ]; then if [ "Windows_NT" = "$OS" ]; then echo "Setting GSSAPI_PASS" export GSSAPI_PASS=${SASL_PASS} + export GSSAPI_CANONICALIZE="true" else # BUILD-3830 touch ${PROJECT_DIRECTORY}/.evergreen/krb5.conf.empty diff --git a/pymongo/auth.py b/pymongo/auth.py index 89febe581..3052b73d9 100644 --- a/pymongo/auth.py +++ b/pymongo/auth.py @@ -375,6 +375,20 @@ def _auth_key(nonce, username, password): return _unicode(md5hash.hexdigest()) +def _canonicalize_hostname(hostname): + """Canonicalize hostname following MIT-krb5 behavior.""" + # https://github.com/krb5/krb5/blob/d406afa363554097ac48646a29249c04f498c88e/src/util/k5test.py#L505-L520 + af, socktype, proto, canonname, sockaddr = socket.getaddrinfo( + hostname, None, 0, 0, socket.IPPROTO_TCP, socket.AI_CANONNAME)[0] + + try: + name = socket.getnameinfo(sockaddr, socket.NI_NAMEREQD) + except socket.gaierror: + return canonname.lower() + + return name[0].lower() + + def _authenticate_gssapi(credentials, sock_info): """Authenticate using GSSAPI. """ @@ -390,7 +404,7 @@ def _authenticate_gssapi(credentials, sock_info): # the security context. See RFC 4752, Section 3.1, first paragraph. host = sock_info.address[0] if props.canonicalize_host_name: - host = socket.getfqdn(host) + host = _canonicalize_hostname(host) service = props.service_name + '@' + host if props.service_realm is not None: service = service + '@' + props.service_realm