f4d17450 |
--- 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;
}
} |