--- openldap-2.4.40/include/ldap.h	2014-09-18 18:48:49.000000000 -0700
+++ openldap-2.4.40-1/include/ldap.h	2015-01-21 15:59:24.000000000 -0800
@@ -196,6 +196,7 @@ LDAP_BEGIN_DECL
 /* OpenLDAP GSSAPI options */
 #define LDAP_OPT_X_GSSAPI_DO_NOT_FREE_CONTEXT      0x6200
 #define LDAP_OPT_X_GSSAPI_ALLOW_REMOTE_PRINCIPAL   0x6201
+#define LDAP_OPT_X_GSSAPI_CREDENTIAL_HANDLE        0x6202
 
 /*
  * OpenLDAP per connection tcp-keepalive settings
@@ -1238,6 +1239,15 @@ ldap_parse_sasl_bind_result LDAP_P((
 	struct berval	**servercredp,
 	int				freeit ));
 
+/*
+ * in gssapi.c:
+ */
+LDAP_F( int )
+ldap_gssapi_bind_s LDAP_P((
+	LDAP  *ld,
+	LDAP_CONST char *dn,
+	LDAP_CONST char *creds));
+
 #if LDAP_DEPRECATED
 /*
  * in bind.c:
diff -rupN openldap-2.4.40/libraries/libldap/gssapi.c openldap-2.4.40-1/libraries/libldap/gssapi.c
--- openldap-2.4.40/libraries/libldap/gssapi.c	2014-09-18 18:48:49.000000000 -0700
+++ openldap-2.4.40-1/libraries/libldap/gssapi.c	2015-01-21 17:32:47.000000000 -0800
@@ -199,6 +199,7 @@ sb_sasl_gssapi_encode(
 	if ( conf_req_flag && conf_state == 0 ) {
 		ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug,
 				"sb_sasl_gssapi_encode: GSS_C_CONF_FLAG was ignored by our gss_wrap()\n" );
+		gss_release_buffer(&minor_status, &wrapped);
 		return -1;
 	}
 
@@ -211,6 +212,7 @@ sb_sasl_gssapi_encode(
 		ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug,
 				"sb_sasl_gssapi_encode: failed to grow the buffer to %lu bytes\n",
 				pkt_len );
+		gss_release_buffer(&minor_status, &wrapped);
 		return -1;
 	}
 
@@ -240,12 +242,13 @@ sb_sasl_gssapi_decode(
 	gss_ctx_id_t gss_ctx = (gss_ctx_id_t)p->ops_private;
 	int gss_rc;
 	OM_uint32 minor_status;
-	gss_buffer_desc unwrapped, wrapped;
+	gss_buffer_desc unwrapped = {0}, wrapped;
 	gss_OID ctx_mech = GSS_C_NO_OID;
 	OM_uint32 ctx_flags = 0;
 	int conf_req_flag = 0;
 	int conf_state;
 	unsigned char *b;
+	ber_int_t result = 0;
 
 	wrapped.value	= src->buf_base + 4;
 	wrapped.length	= src->buf_end - 4;
@@ -272,13 +275,15 @@ sb_sasl_gssapi_decode(
 		ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug,
 				"sb_sasl_gssapi_decode: failed to decode packet: %s\n",
 				gsserrstr( msg, sizeof(msg), ctx_mech, gss_rc, minor_status ) );
-		return -1;
+		result = -1;
+		goto cleanup;
 	}
 
 	if ( conf_req_flag && conf_state == 0 ) {
 		ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug,
 				"sb_sasl_gssapi_encode: GSS_C_CONF_FLAG was ignored by our peer\n" );
-		return -1;
+		result = -1;
+		goto cleanup;
 	}
 
 	/* Grow the packet buffer if neccessary */
@@ -288,7 +293,8 @@ sb_sasl_gssapi_decode(
 		ber_log_printf( LDAP_DEBUG_ANY, p->sbiod->sbiod_sb->sb_debug,
 				"sb_sasl_gssapi_decode: failed to grow the buffer to %lu bytes\n",
 				unwrapped.length );
-		return -1;
+		result = -1;
+		goto cleanup;
 	}
 
 	dst->buf_end = unwrapped.length;
@@ -298,9 +304,11 @@ sb_sasl_gssapi_decode(
 	/* copy the wrapped blob to the right location */
 	memcpy(b, unwrapped.value, unwrapped.length);
 
+cleanup:
+
 	gss_release_buffer(&minor_status, &unwrapped);
 
-	return 0;
+	return result;
 }
 
 static void
@@ -512,15 +520,28 @@ guess_service_principal(
 	int gss_rc;
 	int ret;
 	size_t svc_principal_size;
+	size_t dns_domain_name_size;
 	char *svc_principal = NULL;
 	const char *principal_fmt = NULL;
-	const char *str = NULL;
 	const char *givenstr = NULL;
+	char *dns_domain_name = NULL;
+	char *name = NULL;
 	const char *ignore = "not_defined_in_RFC4178@please_ignore";
 	int allow_remote = 0;
 
 	if (ldapServiceName) {
 		givenstr = strchr(ldapServiceName, ':');
+
+		dns_domain_name_size = (size_t)((givenstr - ldapServiceName) + 1);
+		dns_domain_name = (char*) ldap_memalloc(dns_domain_name_size * sizeof(char));
+		if (!dns_domain_name) {
+			ld->ld_errno = LDAP_NO_MEMORY;
+			return ld->ld_errno;
+		}
+
+		strncpy(dns_domain_name, ldapServiceName, (dns_domain_name_size - 1));
+		dns_domain_name[dns_domain_name_size - 1] = '\0';
+
 		if (givenstr && givenstr[1]) {
 			givenstr++;
 			if (strcmp(givenstr, ignore) == 0) {
@@ -535,20 +556,42 @@ guess_service_principal(
 		allow_remote = 1;
 	}
 
+	/* Try to figure out correct service principal form given
+	   available information */
 	if (allow_remote && givenstr) {
 		principal_fmt = "%s";
 		svc_principal_size = strlen(givenstr) + 1;
-		str = givenstr;
+		name = strdup(givenstr);
+		if (!name) {
+			ld->ld_errno = LDAP_NO_MEMORY;
+			return ld->ld_errno;
+		}
 
-	} else if (allow_remote && dnsHostName) {
+	} else if (dnsHostName) {
 		principal_fmt = "ldap/%s";
-		svc_principal_size = STRLENOF("ldap/") + strlen(dnsHostName) + 1;
-		str = dnsHostName;
+        svc_principal_size = strlen(dnsHostName) + strlen(dns_domain_name) +
+                                     strlen(principal_fmt);
+                                     
+        /* svc_principal_size is actually a bit more than really needed, but
+           let's use it to avoid calculating yet another size */
+        name = (char*) ldap_memalloc(svc_principal_size * sizeof(char));
+        if (!name) {
+            ld->ld_errno = LDAP_NO_MEMORY;
+            return ld->ld_errno;
+        }               
+
+        snprintf(name, svc_principal_size, "%s/%s",
+             dnsHostName, dns_domain_name);
 
 	} else {
 		principal_fmt = "ldap/%s";
-		svc_principal_size = STRLENOF("ldap/") + strlen(host) + 1;
-		str = host;
+        svc_principal_size = strlen(dns_domain_name) + strlen(principal_fmt);
+        name = strdup(dns_domain_name);
+        if (!name) {
+            ld->ld_errno = LDAP_NO_MEMORY;
+            return ld->ld_errno;
+        }
+
 	}
 
 	svc_principal = (char*) ldap_memalloc(svc_principal_size * sizeof(char));
@@ -557,8 +600,8 @@ guess_service_principal(
 		return ld->ld_errno;
 	}
 
-	ret = snprintf( svc_principal, svc_principal_size, principal_fmt, str );
-	if (ret < 0 || (size_t)ret >= svc_principal_size) {
+	ret = snprintf( svc_principal, svc_principal_size, principal_fmt, name );
+	if (ret < 0 || (size_t)(ret+1) >= svc_principal_size) {
 		ld->ld_errno = LDAP_LOCAL_ERROR;
 		return ld->ld_errno;
 	}
@@ -571,6 +614,8 @@ guess_service_principal(
 
 	gss_rc = gss_import_name( &minor_status, &input_name, &nt_principal, principal );
 	ldap_memfree( svc_principal );
+	ldap_memfree(dns_domain_name);
+	ldap_memfree(name);
 	if ( gss_rc != GSS_S_COMPLETE ) {
 		return map_gsserr2ldap( ld, GSS_C_NO_OID, gss_rc, minor_status );
 	}
@@ -658,6 +703,7 @@ ldap_int_gss_spnego_bind_s( LDAP *ld )
 	gss_OID req_mech = GSS_C_NO_OID;
 	gss_OID ret_mech = GSS_C_NO_OID;
 	gss_ctx_id_t gss_ctx = GSS_C_NO_CONTEXT;
+	gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL;
 	gss_name_t principal = GSS_C_NO_NAME;
 	OM_uint32 req_flags;
 	OM_uint32 ret_flags;
@@ -670,7 +716,7 @@ ldap_int_gss_spnego_bind_s( LDAP *ld )
 	rc = ldap_gssapi_get_rootdse_infos ( ld, &mechlist,
 					     &ldapServiceName, &dnsHostName);
 	if ( rc != LDAP_SUCCESS ) {
-		return rc;
+		goto rc_error;
 	}
 
 	/* check that the server supports GSS-SPNEGO */
@@ -708,8 +754,16 @@ ldap_int_gss_spnego_bind_s( LDAP *ld )
 	 */
 	input_token.value = NULL;
 	input_token.length = 0;
+
+	/*
+	 * Set credentials handle if it's been set (e.g. for gss-ntlm authentication)
+	 */
+	if (ld->ld_options.gssapi_cred_handle) {
+		gss_cred = (gss_cred_id_t)ld->ld_options.gssapi_cred_handle;
+	}
+
 	gss_rc = gss_init_sec_context(&minor_status,
-				      GSS_C_NO_CREDENTIAL,
+				      gss_cred,
 				      &gss_ctx,
 				      principal,
 				      req_mech,
@@ -746,7 +800,7 @@ ldap_int_gss_spnego_bind_s( LDAP *ld )
 		}
 
 		gss_rc = gss_init_sec_context(&minor_status,
-					      GSS_C_NO_CREDENTIAL,
+					      gss_cred,
 					      &gss_ctx,
 					      principal,
 					      req_mech,
@@ -896,6 +950,14 @@ ldap_int_gssapi_get_option( LDAP *ld, in
 		}
 		break;
 
+	case LDAP_OPT_X_GSSAPI_CREDENTIAL_HANDLE:
+		if ( ld->ld_options.gssapi_cred_handle ) {
+			* (void**)arg = ld->ld_options.gssapi_cred_handle;
+		} else {
+			* (void**)arg = GSS_C_NO_CREDENTIAL;
+		}
+		break;
+
 	case LDAP_OPT_X_GSSAPI_DO_NOT_FREE_CONTEXT:
 		if ( ld->ld_options.ldo_gssapi_options & LDAP_GSSAPI_OPT_DO_NOT_FREE_GSS_CONTEXT ) {
 			* (int *) arg = (int)-1;
@@ -961,6 +1023,12 @@ ldap_int_gssapi_set_option( LDAP *ld, in
 		}
 		break;
 
+	case LDAP_OPT_X_GSSAPI_CREDENTIAL_HANDLE:
+		if ( arg != LDAP_OPT_OFF) {
+			ld->ld_options.gssapi_cred_handle = arg;
+		}
+		break;
+
 	case LDAP_OPT_X_GSSAPI_DO_NOT_FREE_CONTEXT:
 		if ( arg != LDAP_OPT_OFF ) {
 			ld->ld_options.ldo_gssapi_options |= LDAP_GSSAPI_OPT_DO_NOT_FREE_GSS_CONTEXT;
diff -rupN openldap-2.4.40/libraries/libldap/ldap-int.h openldap-2.4.40-1/libraries/libldap/ldap-int.h
--- openldap-2.4.40/libraries/libldap/ldap-int.h	2014-09-18 18:48:49.000000000 -0700
+++ openldap-2.4.40-1/libraries/libldap/ldap-int.h	2015-01-21 16:03:49.000000000 -0800
@@ -283,6 +283,7 @@ struct ldapoptions {
 #define LDAP_GSSAPI_OPT_DO_NOT_FREE_GSS_CONTEXT	0x0001
 #define LDAP_GSSAPI_OPT_ALLOW_REMOTE_PRINCIPAL	0x0002
 	unsigned ldo_gssapi_options;
+        void *gssapi_cred_handle;
 #define LDAP_LDO_GSSAPI_NULLARG ,0,0
 #else
 #define LDAP_LDO_GSSAPI_NULLARG
diff -rupN openldap-2.4.40/libraries/libldap/os-ip.c openldap-2.4.40-1/libraries/libldap/os-ip.c
--- openldap-2.4.40/libraries/libldap/os-ip.c	2014-09-18 18:48:49.000000000 -0700
+++ openldap-2.4.40-1/libraries/libldap/os-ip.c	2015-01-21 16:07:47.000000000 -0800
@@ -550,6 +550,7 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *
 	char serv[7];
 	int err;
 	struct addrinfo hints, *res, *sai;
+        int retry;
 #else
 	int i;
 	int use_hp = 0;
@@ -605,7 +606,22 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *
 	/* most getaddrinfo(3) use non-threadsafe resolver libraries */
 	LDAP_MUTEX_LOCK(&ldap_int_resolv_mutex);
 
+	/* The hostname may be an IP address, depending on what is stored in
+	 * the configuration file. To avoid issuing any unnecessary network
+	 * traffic, try looking it up as a numerical host first.
+	 */
+	hints.ai_flags |= AI_NUMERICHOST;
 	err = getaddrinfo( host, serv, &hints, &res );
+	retry = (err == EAI_NONAME);
+#ifdef EAI_NODATA
+	if (err == EAI_NODATA) {
+		retry = 1;
+	}
+#endif
+	if (retry) {
+		hints.ai_flags &= ~AI_NUMERICHOST;
+		err = getaddrinfo( host, serv, &hints, &res );
+	}
 
 	LDAP_MUTEX_UNLOCK(&ldap_int_resolv_mutex);
 
diff -rupN openldap-2.4.40/libraries/libldap/request.c openldap-2.4.40-1/libraries/libldap/request.c
--- openldap-2.4.40/libraries/libldap/request.c	2014-09-18 18:48:49.000000000 -0700
+++ openldap-2.4.40-1/libraries/libldap/request.c	2015-01-21 16:19:26.000000000 -0800
@@ -779,6 +779,7 @@ ldap_free_connection( LDAP *ld, LDAPConn
 
 		if ( lc->lconn_ber != NULL ) {
 			ber_free( lc->lconn_ber, 1 );
+			lc->lconn_ber = NULL;
 		}
 
 		ldap_int_sasl_close( ld, lc );
diff -rupN openldap-2.4.40/libraries/libldap/result.c openldap-2.4.40-1/libraries/libldap/result.c
--- openldap-2.4.40/libraries/libldap/result.c	2014-09-18 18:48:49.000000000 -0700
+++ openldap-2.4.40-1/libraries/libldap/result.c	2015-01-21 16:16:46.000000000 -0800
@@ -692,6 +692,8 @@ nextresp2:
 		char		*lr_res_error = NULL;
 
 		tmpber = *ber; 	/* struct copy */
+		lr->lr_res_matched = NULL;
+		lr_res_error = NULL;
 		if ( ber_scanf( &tmpber, "{eAA", &lderr,
 				&lr->lr_res_matched, &lr_res_error )
 				!= LBER_ERROR )
@@ -789,6 +791,12 @@ nextresp2:
 				lr->lr_res_errno = LDAP_PARTIAL_RESULTS;
 			}
 		}
+		else
+		{
+			/* Free lr_res_matched in case it was allocated before
+			 * ber_scanf found an error */
+			LDAP_FREE(lr->lr_res_matched);
+		}
 
 		/* in any case, don't leave any lr_res_error 'round */
 		if ( lr_res_error ) {
@@ -881,6 +889,9 @@ nextresp2:
 
 				if ( lr != &dummy_lr ) {
 					ldap_return_request( ld, lr, 1 );
+				} else {
+					LDAP_FREE(lr->lr_res_error);
+					lr->lr_res_error = NULL;
 				}
 				lr = NULL;
 			}
@@ -962,7 +973,8 @@ nextresp2:
 
 			/* need to return -1, because otherwise
 			 * a valid result is expected */
-			ld->ld_errno = lderr;
+			ber_free(ber, 1);
+			ld->ld_errno = LDAP_CONNECT_ERROR;
 			return -1;
 		}
 	}