示例#1
0
int ldap_x_sasl_digest_md5_bind_s(
	LDAP *ld,
	char *user_name,
	struct berval *cred,
	LDAPControl **serverctrls,
	LDAPControl **clientctrls)
{
	struct berval	*challenge = NULL;
	int		errnum;
	char		*digest = NULL;
	struct berval	resp;

	LDAPDebug(LDAP_DEBUG_TRACE, "ldap_x_sasl_digest_md5_bind_s\n", 0, 0, 0);

	/* Add debug */
	if (ld == NULL || user_name == NULL || cred == NULL ||
	    cred->bv_val == NULL)
		return (LDAP_PARAM_ERROR);

	if (ld->ld_version < LDAP_VERSION3)
		return (LDAP_PARAM_ERROR);

	errnum = ldap_sasl_bind_s(ld, NULL, LDAP_SASL_DIGEST_MD5,
		NULL, serverctrls, clientctrls, &challenge);

	if (errnum == LDAP_SASL_BIND_IN_PROGRESS) {
		if (challenge != NULL) {
			LDAPDebug(LDAP_DEBUG_TRACE,
				"SASL challenge: %s\n",
				challenge->bv_val, 0, 0);
			errnum = ldap_digest_md5_encode(challenge->bv_val,
				user_name, cred->bv_val, &digest);
			ber_bvfree(challenge);
			challenge = NULL;
			if (errnum == LDAP_SUCCESS) {
				resp.bv_val = digest;
				resp.bv_len = strlen(digest);
				LDAPDebug(LDAP_DEBUG_TRACE,
					"SASL reply: %s\n",
					digest, 0, 0);
				errnum = ldap_sasl_bind_s(ld, NULL,
					LDAP_SASL_DIGEST_MD5, &resp,
					serverctrls, clientctrls, &challenge);
				free(digest);
			}
			if (challenge != NULL)
				ber_bvfree(challenge);
		} else {
			errnum = LDAP_NO_MEMORY; /* TO DO: What val? */
		}
	}

	LDAP_MUTEX_LOCK(ld, LDAP_ERR_LOCK);
	ld->ld_errno = errnum;
	LDAP_MUTEX_UNLOCK(ld, LDAP_ERR_LOCK);
	return (errnum);
}
示例#2
0
/* build an allocated LDAPv3 control.  Returns an LDAP error code. */
int ldap_build_control(char *oid, BerElement *ber, int freeber,
char iscritical, LDAPControl **ctrlp)
{
	int		rc;
	struct berval	*bvp;

	if (ber == NULL) {
		bvp = NULL;
	} else {
		/* allocate struct berval with contents of the BER encoding */
		rc = ber_flatten(ber, &bvp);
		if (freeber) {
			ber_free(ber, 1);
		}
		if (rc == -1) {
			return (LDAP_NO_MEMORY);
		}
	}

	/* allocate the new control structure */
	if ((*ctrlp = (LDAPControl *)calloc(1, sizeof (LDAPControl)))
	    == NULL) {
		if (bvp != NULL) {
			ber_bvfree(bvp);
		}
		return (LDAP_NO_MEMORY);
	}

	/* fill in the fields of this new control */
	(*ctrlp)->ldctl_iscritical = iscritical;
	if (((*ctrlp)->ldctl_oid = strdup(oid)) == NULL) {
		free(*ctrlp);
		*ctrlp = NULL;
		if (bvp != NULL) {
			ber_bvfree(bvp);
		}
		return (LDAP_NO_MEMORY);
	}

	if (bvp == NULL) {
		(*ctrlp)->ldctl_value.bv_len = 0;
		(*ctrlp)->ldctl_value.bv_val = NULL;
	} else {
		(*ctrlp)->ldctl_value = *bvp;	/* struct copy */
		free(bvp);	/* free container, not contents! */
	}

	return (LDAP_SUCCESS);
}
示例#3
0
文件: sasl.c 项目: 0x24bin/winexe-1
/* 
   perform a LDAP/SASL/SPNEGO/KRB5 bind
*/
static ADS_STATUS ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT *ads, const char *principal)
{
	DATA_BLOB blob = data_blob_null;
	struct berval cred, *scred = NULL;
	DATA_BLOB session_key = data_blob_null;
	int rc;

	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
		return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
	}

	rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0,
				     &ads->auth.tgs_expire);

	if (rc) {
		return ADS_ERROR_KRB5(rc);
	}

	/* now send the auth packet and we should be done */
	cred.bv_val = (char *)blob.data;
	cred.bv_len = blob.length;

	rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);

	data_blob_free(&blob);
	data_blob_free(&session_key);
	if(scred)
		ber_bvfree(scred);

	return ADS_ERROR(rc);
}
/* nsILDAPBERValue flatten (); */
NS_IMETHODIMP nsLDAPBERElement::GetAsValue(nsILDAPBERValue **_retval) {
  // create the value object
  nsCOMPtr<nsILDAPBERValue> berValue = new nsLDAPBERValue();

  if (!berValue) {
    NS_ERROR(
        "nsLDAPBERElement::GetAsValue(): out of memory"
        " creating nsLDAPBERValue object");
    return NS_ERROR_OUT_OF_MEMORY;
  }

  struct berval *bv;
  if (ber_flatten(mElement, &bv) < 0) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  nsresult rv =
      berValue->Set(bv->bv_len, reinterpret_cast<uint8_t *>(bv->bv_val));

  // whether or not we've succeeded, we're done with the ldap c sdk struct
  ber_bvfree(bv);

  // as of this writing, this error can only be NS_ERROR_OUT_OF_MEMORY
  if (NS_FAILED(rv)) {
    return rv;
  }

  // return the raw interface pointer
  NS_ADDREF(*_retval = berValue.get());

  return NS_OK;
}
示例#5
0
/*
 * Report error status to client, and the final
 * minor status from the server.
 * This is the end, my friend...
 */
static
OM_uint32
_srp_gss_accept_sec_ctx_error_resp(
    OM_uint32 *minor_status,
    gss_buffer_t output_token)
{
    OM_uint32 maj = 0;
    OM_uint32 min = 0;
    int berror = 0;
    BerElement *ber_resp = NULL;
    struct berval *flatten = NULL;

    ber_resp = ber_alloc_t(LBER_USE_DER);
    if (!ber_resp)
    {
        maj = GSS_S_FAILURE;
        min = ENOMEM;
        goto error;
    }
    berror = ber_printf(ber_resp, "t{i}",
                  (int) SRP_AUTH_FAILED,
                  *minor_status);
    if (berror == -1)
    {
        maj = GSS_S_FAILURE;
        goto error;
    }

    berror = ber_flatten(ber_resp, &flatten);
    if (berror == -1)
    {
        maj = GSS_S_FAILURE;
        goto error;
    }

    output_token->value = gssalloc_calloc(1, flatten->bv_len);
    if (!output_token->value)
    {
        maj = GSS_S_FAILURE;
        goto error;
    }
    output_token->length = flatten->bv_len;
    memcpy(output_token->value, flatten->bv_val, flatten->bv_len);

error:
    ber_bvfree(flatten);
    ber_free(ber_resp, 1);
    if (maj)
    {
        if (min)
        {
            *minor_status = min;
        }
        /* Cleanup return memory stuff here */
    }

    return maj;
}
示例#6
0
/*
 * controlType = LDAP_CONTROL_GET_EFFECTIVE_RIGHTS;
 * criticality = n/a;
 * controlValue = OCTET STRING of BER encoding of the SEQUENCE of
 *				  ENUMERATED LDAP code
 */
void
_ger_set_response_control (
	Slapi_PBlock	*pb,
	int				iscritical,
	int				rc
	)
{
	LDAPControl **resultctrls = NULL;
	LDAPControl gerrespctrl;
	BerElement *ber = NULL;
	struct berval *berval = NULL;
	int found = 0;
	int i;

	if ( (ber = der_alloc ()) == NULL )
	{
		goto bailout;
	}

	/* begin sequence, enumeration, end sequence */
	ber_printf ( ber, "{e}", rc );
	if ( ber_flatten ( ber, &berval ) != LDAP_SUCCESS )
	{
		goto bailout;
	}
	gerrespctrl.ldctl_oid = LDAP_CONTROL_GET_EFFECTIVE_RIGHTS;
	gerrespctrl.ldctl_iscritical = iscritical;
	gerrespctrl.ldctl_value.bv_val = berval->bv_val;
	gerrespctrl.ldctl_value.bv_len = berval->bv_len;

	slapi_pblock_get ( pb, SLAPI_RESCONTROLS, &resultctrls );
	for (i = 0; resultctrls && resultctrls[i]; i++)
	{
		if (strcmp(resultctrls[i]->ldctl_oid, LDAP_CONTROL_GET_EFFECTIVE_RIGHTS) == 0)
		{
			/*
			 * We get here if search returns more than one entry
			 * and this is not the first entry.
			 */
			ldap_control_free ( resultctrls[i] );
			resultctrls[i] = slapi_dup_control (&gerrespctrl);
			found = 1;
			break;
		}
	}

	if ( !found )
	{
		/* slapi_pblock_set() will dup the control */
		slapi_pblock_set ( pb, SLAPI_ADD_RESCONTROL, &gerrespctrl );
	}

bailout:
	ber_free ( ber, 1 );	/* ber_free() checks for NULL param */
	ber_bvfree ( berval );	/* ber_bvfree() checks for NULL param */
}
示例#7
0
VOID
LwLdapFreeCookie(
    PVOID pCookie
    )
{
    if (pCookie != NULL)
    {
        ber_bvfree((struct berval*)pCookie);
    }
}
示例#8
0
文件: dds.c 项目: ryo/netbsd-src
int
ldap_parse_refresh( LDAP *ld, LDAPMessage *res, ber_int_t *newttl )
{
    int		rc;
    struct berval	*retdata = NULL;
    ber_tag_t	tag;
    BerElement	*ber;

    assert( ld != NULL );
    assert( LDAP_VALID( ld ) );
    assert( res != NULL );
    assert( newttl != NULL );

    *newttl = 0;

    rc = ldap_parse_extended_result( ld, res, NULL, &retdata, 0 );

    if ( rc != LDAP_SUCCESS ) {
        return rc;
    }

    if ( ld->ld_errno != LDAP_SUCCESS ) {
        return ld->ld_errno;
    }

    if ( retdata == NULL ) {
        rc = ld->ld_errno = LDAP_DECODING_ERROR;
        return rc;
    }

    ber = ber_init( retdata );
    if ( ber == NULL ) {
        rc = ld->ld_errno = LDAP_NO_MEMORY;
        goto done;
    }

    /* check the tag */
    tag = ber_scanf( ber, "{i}", newttl );
    ber_free( ber, 1 );

    if ( tag != LDAP_TAG_EXOP_REFRESH_RES_TTL ) {
        *newttl = 0;
        rc = ld->ld_errno = LDAP_DECODING_ERROR;
    }

done:
    ;
    if ( retdata ) {
        ber_bvfree( retdata );
    }

    return rc;
}
示例#9
0
文件: page.c 项目: AlexSteel/wine
/* create a page control by hand */
static ULONG create_page_control( ULONG pagesize, struct WLDAP32_berval *cookie,
    UCHAR critical, PLDAPControlW *control )
{
    LDAPControlW *ctrl;
    BerElement *ber;
    ber_tag_t tag;
    struct berval *berval, null_cookie = { 0, NULL };
    INT ret, len;
    char *val;

    ber = ber_alloc_t( LBER_USE_DER );
    if (!ber) return WLDAP32_LDAP_NO_MEMORY;

    if (cookie)
        tag = ber_printf( ber, "{iO}", (ber_int_t)pagesize, cookie );
    else
        tag = ber_printf( ber, "{iO}", (ber_int_t)pagesize, &null_cookie );

    ret = ber_flatten( ber, &berval );
    ber_free( ber, 1 );

    if (tag == LBER_ERROR)
        return WLDAP32_LDAP_ENCODING_ERROR;

    if (ret == -1)
        return WLDAP32_LDAP_NO_MEMORY;

    /* copy the berval so it can be properly freed by the caller */
    val = HeapAlloc( GetProcessHeap(), 0, berval->bv_len );
    if (!val) return WLDAP32_LDAP_NO_MEMORY;

    len = berval->bv_len;
    memcpy( val, berval->bv_val, len );
    ber_bvfree( berval );

    ctrl = HeapAlloc( GetProcessHeap(), 0, sizeof(LDAPControlW) );
    if (!ctrl)
    {
        HeapFree( GetProcessHeap(), 0, val );
        return WLDAP32_LDAP_NO_MEMORY;
    }

    ctrl->ldctl_oid = strAtoW( LDAP_PAGED_RESULT_OID_STRING );
    ctrl->ldctl_value.bv_len = len;
    ctrl->ldctl_value.bv_val = val;
    ctrl->ldctl_iscritical = critical;

    *control = ctrl;

    return WLDAP32_LDAP_SUCCESS;
}
示例#10
0
void test_encode(void **state)
{
    int ret;
    struct berval *resp_val;
    struct ipa_extdom_ctx *ctx;
    struct test_data *test_data;

    test_data = (struct test_data *) *state;
    ctx = test_data->ctx;

    ctx->max_nss_buf_size = (128*1024*1024);

    ret = pack_ber_sid(TEST_SID, &resp_val);
    assert_int_equal(ret, LDAP_SUCCESS);
    assert_int_equal(sizeof(res_sid), resp_val->bv_len);
    assert_memory_equal(res_sid, resp_val->bv_val, resp_val->bv_len);
    ber_bvfree(resp_val);

    ret = pack_ber_name(TEST_DOMAIN_NAME, "test", &resp_val);
    assert_int_equal(ret, LDAP_SUCCESS);
    assert_int_equal(sizeof(res_nam), resp_val->bv_len);
    assert_memory_equal(res_nam, resp_val->bv_val, resp_val->bv_len);
    ber_bvfree(resp_val);

    ret = pack_ber_user(ctx, RESP_USER, TEST_DOMAIN_NAME, "test", 12345, 54321,
                        NULL, NULL, NULL, NULL, &resp_val);
    assert_int_equal(ret, LDAP_SUCCESS);
    assert_int_equal(sizeof(res_uid), resp_val->bv_len);
    assert_memory_equal(res_uid, resp_val->bv_val, resp_val->bv_len);
    ber_bvfree(resp_val);

    ret = pack_ber_group(RESP_GROUP, TEST_DOMAIN_NAME, "test_group", 54321,
                         NULL, NULL, &resp_val);
    assert_int_equal(ret, LDAP_SUCCESS);
    assert_int_equal(sizeof(res_gid), resp_val->bv_len);
    assert_memory_equal(res_gid, resp_val->bv_val, resp_val->bv_len);
    ber_bvfree(resp_val);
}
示例#11
0
文件: psearch.c 项目: leto/389-ds
/*
 * Create an LDAPv3 "Entry Change Notification" control.  They look like this:
 *
 *	EntryChangeNotification ::= SEQUENCE {
 *	    changeType		ENUMERATED {
 *		add	(1),	-- LDAP_CHANGETYPE_ADD
 *		delete	(2),    -- LDAP_CHANGETYPE_DELETE
 *		modify	(4),    -- LDAP_CHANGETYPE_MODIFY
 *		moddn	(8),    -- LDAP_CHANGETYPE_MODDN
 *	    },
 *	    previousDN	 LDAPDN OPTIONAL,   -- included for MODDN ops. only
 *	    changeNumber INTEGER OPTIONAL,  -- included if supported by DSA
 *	}
 *
 * This function returns an LDAP error code (LDAP_SUCCESS if all goes well).
 * The value returned in *ctrlp should be free'd use ldap_control_free().
 * If chgnum is 0 we omit it from the control.
 */
static int
create_entrychange_control( ber_int_t chgtype, ber_int_t chgnum, const char *dn,
	LDAPControl **ctrlp )
{
    int			rc;
    BerElement		*ber;
    struct berval	*bvp;
	const char *prevdn= dn;

    if ( prevdn == NULL ) {
	prevdn = "";
    }

    if ( ctrlp == NULL || ( ber = der_alloc()) == NULL ) {
	return( LDAP_OPERATIONS_ERROR );
    }

    *ctrlp = NULL;

    if (( rc = ber_printf( ber, "{e", chgtype )) != -1 ) {
	if ( chgtype == LDAP_CHANGETYPE_MODDN ) {
	    rc = ber_printf( ber, "s", prevdn );
	}
	if ( rc != -1 && chgnum != 0 ) {
	    rc = ber_printf( ber, "i", chgnum );
	}
	if ( rc != -1 ) {
	    rc = ber_printf( ber, "}" );
	}
    }

    if ( rc != -1 ) {
	rc = ber_flatten( ber, &bvp );
    }
    ber_free( ber, 1 );

    if ( rc == -1 ) {
	return( LDAP_OPERATIONS_ERROR );
    }

    *ctrlp = (LDAPControl *)slapi_ch_malloc( sizeof( LDAPControl ));
    (*ctrlp)->ldctl_iscritical = 0;
    (*ctrlp)->ldctl_oid = slapi_ch_strdup( LDAP_CONTROL_ENTRYCHANGE );
    (*ctrlp)->ldctl_value = *bvp;	/* struct copy */

	bvp->bv_val = NULL;
	ber_bvfree( bvp );

    return( LDAP_SUCCESS );
}
示例#12
0
static int
sasl_digest_md5_bind_2(
	LDAP *ld,
	char *user_name,
	struct berval *cred,
	LDAPControl **serverctrls,
	LDAPControl **clientctrls,
	LDAPMessage *result,
	int *msgidp)
{
	struct berval	*challenge = NULL;
	struct berval	resp;
	int		errnum;
	char		*digest = NULL;
	int		err;

	if (ld == NULL || user_name == NULL || cred == NULL ||
	    cred->bv_val == NULL || result == NULL || msgidp == NULL)
		return (LDAP_PARAM_ERROR);

	if (ld->ld_version < LDAP_VERSION3)
		return (LDAP_PARAM_ERROR);

	err = ldap_result2error(ld, result, 0);
	if (err != LDAP_SASL_BIND_IN_PROGRESS)
		return (err);

	if ((err = ldap_parse_sasl_bind_result(ld, result, &challenge, 0))
			!= LDAP_SUCCESS)
		return (err);
	if (challenge == NULL)
		return (LDAP_NO_MEMORY);

	err = ldap_digest_md5_encode(challenge->bv_val,
			user_name, cred->bv_val, &digest);
	ber_bvfree(challenge);

	if (err == LDAP_SUCCESS) {
		resp.bv_val = digest;
		resp.bv_len = strlen(digest);
		LDAPDebug(LDAP_DEBUG_TRACE, "SASL reply: %s\n",
			digest, 0, 0);
		err = ldap_sasl_bind(ld, NULL, LDAP_SASL_DIGEST_MD5,
			&resp, serverctrls, clientctrls, msgidp);
		free(digest);
	}
	return (err);
}
示例#13
0
static int
slapi_over_extended( Operation *op, SlapReply *rs )
{
	Slapi_PBlock	*pb;
	SLAPI_FUNC	callback;
	int		rc;
	int		internal_op;
	slap_callback	cb;

	slapi_int_get_extop_plugin( &op->ore_reqoid, &callback );
	if ( callback == NULL ) {
		return SLAP_CB_CONTINUE;
	}

	internal_op = slapi_op_internal_p( op, rs, &cb );
	if ( internal_op ) {
		return SLAP_CB_CONTINUE;
	}

	pb = SLAPI_OPERATION_PBLOCK( op );

	rc = (*callback)( pb );
	if ( rc == SLAPI_PLUGIN_EXTENDED_SENT_RESULT ) {
		goto cleanup;
	} else if ( rc == SLAPI_PLUGIN_EXTENDED_NOT_HANDLED ) {
		rc = SLAP_CB_CONTINUE;
		goto cleanup;
	}

	assert( rs->sr_rspoid != NULL );

	send_ldap_extended( op, rs );

#if 0
	slapi_ch_free_string( (char **)&rs->sr_rspoid );
#endif

	if ( rs->sr_rspdata != NULL )
		ber_bvfree( rs->sr_rspdata );

	rc = rs->sr_err;

cleanup:
	slapi_pblock_destroy( pb );
	op->o_callback = cb.sc_next;

	return rc;
}
示例#14
0
static PyObject *
LDAPSearchIter_AcquireNextPage(LDAPSearchIter *self) {
	int msgid = -1;

	/* If paged LDAP search is in progress. */
	if ((self->cookie != NULL) && (self->cookie->bv_val != NULL) &&
			(strlen(self->cookie->bv_val) > 0)) {
		msgid = LDAPConnection_Searching(self->conn, (PyObject *)self);
		if (msgid < 0) return NULL;

		return PyLong_FromLong((long int)msgid);
	} else {
		ber_bvfree(self->cookie);
		self->cookie = NULL;

		Py_RETURN_NONE;
	}
}
示例#15
0
void oath_token_free(Token *token) {

    if (token->pin) {
        slapi_ch_free_string(&token->pin);
        token->pin = NULL;
    }

    if (token->serial) {
        slapi_ch_free_string(&token->serial);
        token->serial = NULL;
    }

    if (token->seed) {
        ber_bvfree(token->seed);
        token->seed = NULL;
    }

}
示例#16
0
int ldap_parse_passwd(
	LDAP *ld,
	LDAPMessage *res,
	struct berval *newpasswd )
{
	int rc;
	struct berval *retdata = NULL;

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( res != NULL );
	assert( newpasswd != NULL );

	newpasswd->bv_val = NULL;
	newpasswd->bv_len = 0;

	rc = ldap_parse_extended_result( ld, res, NULL, &retdata, 0 );
	if ( rc != LDAP_SUCCESS ) {
		return rc;
	}

	if ( retdata != NULL ) {
		ber_tag_t tag;
		BerElement *ber = ber_init( retdata );

		if ( ber == NULL ) {
			rc = ld->ld_errno = LDAP_NO_MEMORY;
			goto done;
		}

		/* we should check the tag */
		tag = ber_scanf( ber, "{o}", newpasswd );
		ber_free( ber, 1 );

		if ( tag == LBER_ERROR ) {
			rc = ld->ld_errno = LDAP_DECODING_ERROR;
		}
	}

done:;
	ber_bvfree( retdata );

	return rc;
}
示例#17
0
/* Create an LDAP_SERVER_EXTENDED_DN control. */
int _ldap_create_extended_dn_control(LDAP *ld, int format, LDAPControl **edn_ctrl) {
    int rc = -1;
    BerElement *ber = NULL;
    struct berval *value = NULL;
    LDAPControl *ctrl = NULL;

    ber = ber_alloc_t(LBER_USE_DER);
    if (ber == NULL) return LDAP_NO_MEMORY;
    
    /* Transcode the data into a berval struct. */
    ber_printf(ber, "{i}", format);
    rc = ber_flatten(ber, &value);
    ber_free(ber, 1);
    if (rc != 0) return rc; 

    rc = ldap_control_create(LDAP_SERVER_EXTENDED_DN_OID, 0, value, 1, &ctrl);
    ber_bvfree(value);

    if (rc != LDAP_SUCCESS) return rc;

    *edn_ctrl = ctrl;
    return LDAP_SUCCESS;
}
示例#18
0
int
ldap_start_tls_s ( LDAP *ld,
	LDAPControl **serverctrls,
	LDAPControl **clientctrls )
{
#ifndef HAVE_TLS
	return LDAP_NOT_SUPPORTED;
#else
	int rc;
	char *rspoid = NULL;
	struct berval *rspdata = NULL;

	/* XXYYZ: this initiates operation only on default connection! */

	if ( ldap_tls_inplace( ld ) ) {
		return LDAP_LOCAL_ERROR;
	}

	rc = ldap_extended_operation_s( ld, LDAP_EXOP_START_TLS,
		NULL, serverctrls, clientctrls, &rspoid, &rspdata );

	if ( rspoid != NULL ) {
		LDAP_FREE(rspoid);
	}

	if ( rspdata != NULL ) {
		ber_bvfree( rspdata );
	}

	if ( rc == LDAP_SUCCESS ) {
		rc = ldap_int_tls_start( ld, ld->ld_defconn, NULL );
	}

	return rc;
#endif
}
示例#19
0
文件: sasl.c 项目: 0x24bin/winexe-1
/* 
   this performs a SASL/SPNEGO bind
*/
static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
{
	struct berval *scred=NULL;
	int rc, i;
	ADS_STATUS status;
	DATA_BLOB blob;
	char *given_principal = NULL;
	char *OIDs[ASN1_MAX_OIDS];
#ifdef HAVE_KRB5
	bool got_kerberos_mechanism = False;
#endif

	rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);

	if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
		status = ADS_ERROR(rc);
		goto failed;
	}

	blob = data_blob(scred->bv_val, scred->bv_len);

	ber_bvfree(scred);

#if 0
	file_save("sasl_spnego.dat", blob.data, blob.length);
#endif

	/* the server sent us the first part of the SPNEGO exchange in the negprot 
	   reply */
	if (!spnego_parse_negTokenInit(blob, OIDs, &given_principal)) {
		data_blob_free(&blob);
		status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
		goto failed;
	}
	data_blob_free(&blob);

	/* make sure the server understands kerberos */
	for (i=0;OIDs[i];i++) {
		DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i]));
#ifdef HAVE_KRB5
		if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
		    strcmp(OIDs[i], OID_KERBEROS5) == 0) {
			got_kerberos_mechanism = True;
		}
#endif
		talloc_free(OIDs[i]);
	}
	DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal));

#ifdef HAVE_KRB5
	if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
	    got_kerberos_mechanism) 
	{
		struct ads_service_principal p;

		status = ads_generate_service_principal(ads, given_principal, &p);
		TALLOC_FREE(given_principal);
		if (!ADS_ERR_OK(status)) {
			return status;
		}

		status = ads_sasl_spnego_krb5_bind(ads, &p);
		if (ADS_ERR_OK(status)) {
			ads_free_service_principal(&p);
			return status;
		}

		DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
			  "calling kinit\n", ads_errstr(status)));

		status = ADS_ERROR_KRB5(ads_kinit_password(ads)); 

		if (ADS_ERR_OK(status)) {
			status = ads_sasl_spnego_krb5_bind(ads, &p);
			if (!ADS_ERR_OK(status)) {
				DEBUG(0,("kinit succeeded but "
					"ads_sasl_spnego_krb5_bind failed: %s\n",
					ads_errstr(status)));
			}
		}

		ads_free_service_principal(&p);

		/* only fallback to NTLMSSP if allowed */
		if (ADS_ERR_OK(status) || 
		    !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
			return status;
		}
	} else
#endif
	{
		TALLOC_FREE(given_principal);
	}

	/* lets do NTLMSSP ... this has the big advantage that we don't need
	   to sync clocks, and we don't rely on special versions of the krb5 
	   library for HMAC_MD4 encryption */
	return ads_sasl_spnego_ntlmssp_bind(ads);

failed:
	return status;
}
示例#20
0
文件: sasl.c 项目: Alexander--/samba
/* this performs a SASL/gssapi bind
   we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
   is very dependent on correctly configured DNS whereas
   this routine is much less fragile
   see RFC2078 and RFC2222 for details
*/
static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
{
	uint32_t minor_status;
	gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL;
	gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
	gss_OID mech_type = GSS_C_NULL_OID;
	gss_buffer_desc output_token, input_token;
	uint32_t req_flags, ret_flags;
	int conf_state;
	struct berval cred;
	struct berval *scred = NULL;
	int i=0;
	int gss_rc, rc;
	uint8_t *p;
	uint32_t max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
	uint8_t wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
	ADS_STATUS status;
	struct ads_saslwrap *wrap = &ads->ldap_wrap_data;

	input_token.value = NULL;
	input_token.length = 0;

	status = ads_init_gssapi_cred(ads, &gss_cred);
	if (!ADS_ERR_OK(status)) {
		goto failed;
	}

	/*
	 * Note: here we always ask the gssapi for sign and seal
	 *       as this is negotiated later after the mutal
	 *       authentication
	 */
	req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;

	for (i=0; i < MAX_GSS_PASSES; i++) {
		gss_rc = gss_init_sec_context(&minor_status,
					  gss_cred,
					  &context_handle,
					  serv_name,
					  mech_type,
					  req_flags,
					  0,
					  NULL,
					  &input_token,
					  NULL,
					  &output_token,
					  &ret_flags,
					  NULL);
		if (scred) {
			ber_bvfree(scred);
			scred = NULL;
		}
		if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
			status = ADS_ERROR_GSS(gss_rc, minor_status);
			goto failed;
		}

		cred.bv_val = (char *)output_token.value;
		cred.bv_len = output_token.length;

		rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL, 
				      &scred);
		if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
			status = ADS_ERROR(rc);
			goto failed;
		}

		if (output_token.value) {
			gss_release_buffer(&minor_status, &output_token);
		}

		if (scred) {
			input_token.value = scred->bv_val;
			input_token.length = scred->bv_len;
		} else {
			input_token.value = NULL;
			input_token.length = 0;
		}

		if (gss_rc == 0) break;
	}

	gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
			    &conf_state,NULL);
	if (scred) {
		ber_bvfree(scred);
		scred = NULL;
	}
	if (gss_rc) {
		status = ADS_ERROR_GSS(gss_rc, minor_status);
		goto failed;
	}

	p = (uint8_t *)output_token.value;

#if 0
	file_save("sasl_gssapi.dat", output_token.value, output_token.length);
#endif

	if (p) {
		wrap_type = CVAL(p,0);
		SCVAL(p,0,0);
		max_msg_size = RIVAL(p,0);
	}

	gss_release_buffer(&minor_status, &output_token);

	if (!(wrap_type & wrap->wrap_type)) {
		/*
		 * the server doesn't supports the wrap
		 * type we want :-(
		 */
		DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
			wrap->wrap_type, wrap_type));
		DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
		status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
		goto failed;
	}

	/* 0x58 is the minimum windows accepts */
	if (max_msg_size < 0x58) {
		max_msg_size = 0x58;
	}

	output_token.length = 4;
	output_token.value = SMB_MALLOC(output_token.length);
	if (!output_token.value) {
		output_token.length = 0;
		status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
		goto failed;
	}
	p = (uint8_t *)output_token.value;

	RSIVAL(p,0,max_msg_size);
	SCVAL(p,0,wrap->wrap_type);

	/*
	 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
	 * but using ads->config.bind_path is the wrong! It should be
	 * the DN of the user object!
	 *
	 * w2k3 gives an error when we send an incorrect DN, but sending nothing
	 * is ok and matches the information flow used in GSS-SPNEGO.
	 */

	gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
			&output_token, /* used as *input* here. */
			&conf_state,
			&input_token); /* Used as *output* here. */
	if (gss_rc) {
		status = ADS_ERROR_GSS(gss_rc, minor_status);
		output_token.length = 0;
		SAFE_FREE(output_token.value);
		goto failed;
	}

	/* We've finished with output_token. */
	SAFE_FREE(output_token.value);
	output_token.length = 0;

	cred.bv_val = (char *)input_token.value;
	cred.bv_len = input_token.length;

	rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL, 
			      &scred);
	gss_release_buffer(&minor_status, &input_token);
	status = ADS_ERROR(rc);
	if (!ADS_ERR_OK(status)) {
		goto failed;
	}

	if (wrap->wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
		gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
					     (wrap->wrap_type == ADS_SASLWRAP_TYPE_SEAL),
					     GSS_C_QOP_DEFAULT,
					     max_msg_size, &wrap->out.max_unwrapped);
		if (gss_rc) {
			status = ADS_ERROR_GSS(gss_rc, minor_status);
			goto failed;
		}

		wrap->out.sig_size = max_msg_size - wrap->out.max_unwrapped;
		wrap->in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
		wrap->in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
		status = ads_setup_sasl_wrapping(wrap->wrap_private_data, ads->ldap.ld,
						 &ads_sasl_gssapi_ops,
						 context_handle);
		if (!ADS_ERR_OK(status)) {
			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
				ads_errstr(status)));
			goto failed;
		}
		/* make sure we don't free context_handle */
		context_handle = GSS_C_NO_CONTEXT;
	}

failed:
	if (gss_cred != GSS_C_NO_CREDENTIAL)
		gss_release_cred(&minor_status, &gss_cred);
	if (context_handle != GSS_C_NO_CONTEXT)
		gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);

	if(scred)
		ber_bvfree(scred);
	return status;
}
示例#21
0
文件: sasl.c 项目: Alexander--/samba
/* 
   this performs a SASL/SPNEGO bind
*/
static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct ads_service_principal p = {0};
	struct berval *scred=NULL;
	int rc, i;
	ADS_STATUS status;
	DATA_BLOB blob = data_blob_null;
	char *given_principal = NULL;
	char *OIDs[ASN1_MAX_OIDS];
#ifdef HAVE_KRB5
	bool got_kerberos_mechanism = False;
#endif
	const char *mech = NULL;

	rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);

	if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
		status = ADS_ERROR(rc);
		goto done;
	}

	blob = data_blob(scred->bv_val, scred->bv_len);

	ber_bvfree(scred);

#if 0
	file_save("sasl_spnego.dat", blob.data, blob.length);
#endif

	/* the server sent us the first part of the SPNEGO exchange in the negprot 
	   reply */
	if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &given_principal, NULL) ||
			OIDs[0] == NULL) {
		status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
		goto done;
	}
	TALLOC_FREE(given_principal);

	/* make sure the server understands kerberos */
	for (i=0;OIDs[i];i++) {
		DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i]));
#ifdef HAVE_KRB5
		if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
		    strcmp(OIDs[i], OID_KERBEROS5) == 0) {
			got_kerberos_mechanism = True;
		}
#endif
		talloc_free(OIDs[i]);
	}

	status = ads_generate_service_principal(ads, &p);
	if (!ADS_ERR_OK(status)) {
		goto done;
	}

#ifdef HAVE_KRB5
	if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
	    got_kerberos_mechanism) 
	{
		mech = "KRB5";

		if (ads->auth.password == NULL ||
		    ads->auth.password[0] == '\0')
		{

			status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
							     CRED_MUST_USE_KERBEROS,
							     p.service, p.hostname,
							     blob);
			if (ADS_ERR_OK(status)) {
				ads_free_service_principal(&p);
				goto done;
			}

			DEBUG(10,("ads_sasl_spnego_gensec_bind(KRB5) failed with: %s, "
				  "calling kinit\n", ads_errstr(status)));
		}

		status = ADS_ERROR_KRB5(ads_kinit_password(ads)); 

		if (ADS_ERR_OK(status)) {
			status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
							CRED_MUST_USE_KERBEROS,
							p.service, p.hostname,
							blob);
			if (!ADS_ERR_OK(status)) {
				DEBUG(0,("kinit succeeded but "
					"ads_sasl_spnego_gensec_bind(KRB5) failed "
					"for %s/%s with user[%s] realm[%s]: %s\n",
					p.service, p.hostname,
					ads->auth.user_name,
					ads->auth.realm,
					ads_errstr(status)));
			}
		}

		/* only fallback to NTLMSSP if allowed */
		if (ADS_ERR_OK(status) || 
		    !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
			goto done;
		}

		DEBUG(1,("ads_sasl_spnego_gensec_bind(KRB5) failed "
			 "for %s/%s with user[%s] realm[%s]: %s, "
			 "fallback to NTLMSSP\n",
			 p.service, p.hostname,
			 ads->auth.user_name,
			 ads->auth.realm,
			 ads_errstr(status)));
	}
#endif

	/* lets do NTLMSSP ... this has the big advantage that we don't need
	   to sync clocks, and we don't rely on special versions of the krb5 
	   library for HMAC_MD4 encryption */
	mech = "NTLMSSP";
	status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
					     CRED_DONT_USE_KERBEROS,
					     p.service, p.hostname,
					     data_blob_null);
done:
	if (!ADS_ERR_OK(status)) {
		DEBUG(1,("ads_sasl_spnego_gensec_bind(%s) failed "
			 "for %s/%s with user[%s] realm=[%s]: %s\n", mech,
			  p.service, p.hostname,
			  ads->auth.user_name,
			  ads->auth.realm,
			  ads_errstr(status)));
	}
	ads_free_service_principal(&p);
	TALLOC_FREE(frame);
	if (blob.data != NULL) {
		data_blob_free(&blob);
	}
	return status;
}
示例#22
0
文件: sasl.c 项目: Alexander--/samba
/* 
   perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
   we fit on one socket??)
*/
static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
				const char *sasl,
				enum credentials_use_kerberos krb5_state,
				const char *target_service,
				const char *target_hostname,
				const DATA_BLOB server_blob)
{
	DATA_BLOB blob_in = data_blob_null;
	DATA_BLOB blob_out = data_blob_null;
	int rc;
	NTSTATUS nt_status;
	ADS_STATUS status;
	struct auth_generic_state *auth_generic_state;
	bool use_spnego_principal = lp_client_use_spnego_principal();
	const char *sasl_list[] = { sasl, NULL };
	NTTIME end_nt_time;
	struct ads_saslwrap *wrap = &ads->ldap_wrap_data;

	nt_status = auth_generic_client_prepare(NULL, &auth_generic_state);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ADS_ERROR_NT(nt_status);
	}

	if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_username(auth_generic_state, ads->auth.user_name))) {
		return ADS_ERROR_NT(nt_status);
	}
	if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_domain(auth_generic_state, ads->auth.realm))) {
		return ADS_ERROR_NT(nt_status);
	}
	if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_password(auth_generic_state, ads->auth.password))) {
		return ADS_ERROR_NT(nt_status);
	}

	if (server_blob.length == 0) {
		use_spnego_principal = false;
	}

	if (krb5_state == CRED_DONT_USE_KERBEROS) {
		use_spnego_principal = false;
	}

	cli_credentials_set_kerberos_state(auth_generic_state->credentials,
					   krb5_state);

	if (target_service != NULL) {
		nt_status = gensec_set_target_service(
					auth_generic_state->gensec_security,
					target_service);
		if (!NT_STATUS_IS_OK(nt_status)) {
			return ADS_ERROR_NT(nt_status);
		}
	}

	if (target_hostname != NULL) {
		nt_status = gensec_set_target_hostname(
					auth_generic_state->gensec_security,
					target_hostname);
		if (!NT_STATUS_IS_OK(nt_status)) {
			return ADS_ERROR_NT(nt_status);
		}
	}

	if (target_service != NULL && target_hostname != NULL) {
		use_spnego_principal = false;
	}

	switch (wrap->wrap_type) {
	case ADS_SASLWRAP_TYPE_SEAL:
		gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
		gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
		break;
	case ADS_SASLWRAP_TYPE_SIGN:
		if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
		} else {
			/*
			 * windows servers are broken with sign only,
			 * so we let the NTLMSSP backend to seal here,
			 * via GENSEC_FEATURE_LDAP_STYLE.
			 */
			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
			gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_LDAP_STYLE);
		}
		break;
	case ADS_SASLWRAP_TYPE_PLAIN:
		break;
	}

	nt_status = auth_generic_client_start_by_sasl(auth_generic_state,
						      sasl_list);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ADS_ERROR_NT(nt_status);
	}

	rc = LDAP_SASL_BIND_IN_PROGRESS;
	nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
	if (use_spnego_principal) {
		blob_in = data_blob_dup_talloc(talloc_tos(), server_blob);
		if (blob_in.length == 0) {
			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
		}
	} else {
		blob_in = data_blob_null;
	}
	blob_out = data_blob_null;

	while (true) {
		struct berval cred, *scred = NULL;

		nt_status = gensec_update(auth_generic_state->gensec_security,
					  talloc_tos(), blob_in, &blob_out);
		data_blob_free(&blob_in);
		if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
		    && !NT_STATUS_IS_OK(nt_status))
		{
			TALLOC_FREE(auth_generic_state);
			data_blob_free(&blob_out);
			return ADS_ERROR_NT(nt_status);
		}

		if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_out.length == 0) {
			break;
		}

		cred.bv_val = (char *)blob_out.data;
		cred.bv_len = blob_out.length;
		scred = NULL;
		rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, sasl, &cred, NULL, NULL, &scred);
		data_blob_free(&blob_out);
		if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
			if (scred) {
				ber_bvfree(scred);
			}

			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR(rc);
		}
		if (scred) {
			blob_in = data_blob_talloc(talloc_tos(),
						   scred->bv_val,
						   scred->bv_len);
			if (blob_in.length != scred->bv_len) {
				ber_bvfree(scred);
				TALLOC_FREE(auth_generic_state);
				return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
			}
			ber_bvfree(scred);
		} else {
			blob_in = data_blob_null;
		}
		if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_in.length == 0) {
			break;
		}
	}

	data_blob_free(&blob_in);
	data_blob_free(&blob_out);

	if (wrap->wrap_type >= ADS_SASLWRAP_TYPE_SEAL) {
		bool ok;

		ok = gensec_have_feature(auth_generic_state->gensec_security,
					 GENSEC_FEATURE_SEAL);
		if (!ok) {
			DEBUG(0,("The gensec feature sealing request, but unavailable\n"));
			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
		}

		ok = gensec_have_feature(auth_generic_state->gensec_security,
					 GENSEC_FEATURE_SIGN);
		if (!ok) {
			DEBUG(0,("The gensec feature signing request, but unavailable\n"));
			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
		}

	} else if (wrap->wrap_type >= ADS_SASLWRAP_TYPE_SIGN) {
		bool ok;

		ok = gensec_have_feature(auth_generic_state->gensec_security,
					 GENSEC_FEATURE_SIGN);
		if (!ok) {
			DEBUG(0,("The gensec feature signing request, but unavailable\n"));
			TALLOC_FREE(auth_generic_state);
			return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
		}
	}

	ads->auth.tgs_expire = LONG_MAX;
	end_nt_time = gensec_expire_time(auth_generic_state->gensec_security);
	if (end_nt_time != GENSEC_EXPIRE_TIME_INFINITY) {
		struct timeval tv;
		nttime_to_timeval(&tv, end_nt_time);
		ads->auth.tgs_expire = tv.tv_sec;
	}

	if (wrap->wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
		size_t max_wrapped =
			gensec_max_wrapped_size(auth_generic_state->gensec_security);
		wrap->out.max_unwrapped =
			gensec_max_input_size(auth_generic_state->gensec_security);

		wrap->out.sig_size = max_wrapped - wrap->out.max_unwrapped;
		/*
		 * Note that we have to truncate this to 0x2C
		 * (taken from a capture with LDAP unbind), as the
		 * signature size is not constant for Kerberos with
		 * arcfour-hmac-md5.
		 */
		wrap->in.min_wrapped = MIN(wrap->out.sig_size, 0x2C);
		wrap->in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
		status = ads_setup_sasl_wrapping(wrap, ads->ldap.ld,
						 &ads_sasl_gensec_ops,
						 auth_generic_state->gensec_security);
		if (!ADS_ERR_OK(status)) {
			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
				ads_errstr(status)));
			TALLOC_FREE(auth_generic_state);
			return status;
		}
		/* Only keep the gensec_security element around long-term */
		talloc_steal(NULL, auth_generic_state->gensec_security);
	}
	TALLOC_FREE(auth_generic_state);

	return ADS_ERROR(rc);
}
示例#23
0
文件: ldap_sync.c 项目: Leeios/NodeJS
/*
 * handle the LDAP_RES_INTERMEDIATE response
 */
static int
ldap_sync_search_intermediate( ldap_sync_t *ls, LDAPMessage *res, int *refreshDone )
{
	int			rc;
	char			*retoid = NULL;
        struct berval		*retdata = NULL;
	BerElement		*ber = NULL;
	ber_len_t		len;
	ber_tag_t		syncinfo_tag;
	struct berval		cookie;
	int			refreshDeletes = 0;
	BerVarray		syncUUIDs = NULL;
	ldap_sync_refresh_t	phase;

#ifdef LDAP_SYNC_TRACE
	fprintf( stderr, "\tgot LDAP_RES_INTERMEDIATE\n" );
#endif /* LDAP_SYNC_TRACE */

	assert( ls != NULL );
	assert( res != NULL );
	assert( refreshDone != NULL );

	*refreshDone = 0;

	rc = ldap_parse_intermediate( ls->ls_ld, res,
		&retoid, &retdata, NULL, 0 );
#ifdef LDAP_SYNC_TRACE
	fprintf( stderr, "\t%sldap_parse_intermediate(%s) == %d\n",
		rc != LDAP_SUCCESS ? "!!! " : "",
		retoid == NULL ? "\"\"" : retoid,
		rc );
#endif /* LDAP_SYNC_TRACE */
	/* parsing must be successful, and yield the OID
	 * of the sync info intermediate response */
	if ( rc != LDAP_SUCCESS ) {
		goto done;
	}

	rc = LDAP_OTHER;

	if ( retoid == NULL || strcmp( retoid, LDAP_SYNC_INFO ) != 0 ) {
		goto done;
	}

	/* init ber using the value in the response */
	ber = ber_init( retdata );
	if ( ber == NULL ) {
		goto done;
	}

	syncinfo_tag = ber_peek_tag( ber, &len );
	switch ( syncinfo_tag ) {
	case LDAP_TAG_SYNC_NEW_COOKIE:
		if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) {
			goto done;
		}
		if ( cookie.bv_val != NULL ) {
			ber_bvreplace( &ls->ls_cookie, &cookie );
		}
#ifdef LDAP_SYNC_TRACE
		fprintf( stderr, "\t\tgot cookie=%s\n",
			cookie.bv_val ? cookie.bv_val : "(null)" );
#endif /* LDAP_SYNC_TRACE */
		break;

	case LDAP_TAG_SYNC_REFRESH_DELETE:
	case LDAP_TAG_SYNC_REFRESH_PRESENT:
		if ( syncinfo_tag == LDAP_TAG_SYNC_REFRESH_DELETE ) {
#ifdef LDAP_SYNC_TRACE
			fprintf( stderr, "\t\tgot refreshDelete\n" );
#endif /* LDAP_SYNC_TRACE */
			switch ( ls->ls_refreshPhase ) {
			case LDAP_SYNC_CAPI_NONE:
			case LDAP_SYNC_CAPI_PRESENTS:
				ls->ls_refreshPhase = LDAP_SYNC_CAPI_DELETES;
				break;

			default:
				/* TODO: impossible; handle */
				goto done;
			}

		} else {
#ifdef LDAP_SYNC_TRACE
			fprintf( stderr, "\t\tgot refreshPresent\n" );
#endif /* LDAP_SYNC_TRACE */
			switch ( ls->ls_refreshPhase ) {
			case LDAP_SYNC_CAPI_NONE:
				ls->ls_refreshPhase = LDAP_SYNC_CAPI_PRESENTS;
				break;

			default:
				/* TODO: impossible; handle */
				goto done;
			}
		}

		if ( ber_scanf( ber, "{" /*"}"*/ ) == LBER_ERROR ) {
			goto done;
		}
		if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
			if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) {
				goto done;
			}
			if ( cookie.bv_val != NULL ) {
				ber_bvreplace( &ls->ls_cookie, &cookie );
			}
#ifdef LDAP_SYNC_TRACE
			fprintf( stderr, "\t\tgot cookie=%s\n",
				cookie.bv_val ? cookie.bv_val : "(null)" );
#endif /* LDAP_SYNC_TRACE */
		}

		*refreshDone = 1;
		if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDONE ) {
			if ( ber_scanf( ber, "b", refreshDone ) == LBER_ERROR ) {
				goto done;
			}
		}

#ifdef LDAP_SYNC_TRACE
		fprintf( stderr, "\t\tgot refreshDone=%s\n",
			*refreshDone ? "TRUE" : "FALSE" );
#endif /* LDAP_SYNC_TRACE */

		if ( ber_scanf( ber, /*"{"*/ "}" ) == LBER_ERROR ) {
			goto done;
		}

		if ( *refreshDone ) {
			ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE;
		}

		if ( ls->ls_intermediate ) {
			ls->ls_intermediate( ls, res, NULL, ls->ls_refreshPhase );
		}

		break;

	case LDAP_TAG_SYNC_ID_SET:
#ifdef LDAP_SYNC_TRACE
		fprintf( stderr, "\t\tgot syncIdSet\n" );
#endif /* LDAP_SYNC_TRACE */
		if ( ber_scanf( ber, "{" /*"}"*/ ) == LBER_ERROR ) {
			goto done;
		}
		if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
			if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) {
				goto done;
			}
			if ( cookie.bv_val != NULL ) {
				ber_bvreplace( &ls->ls_cookie, &cookie );
			}
#ifdef LDAP_SYNC_TRACE
			fprintf( stderr, "\t\tgot cookie=%s\n",
				cookie.bv_val ? cookie.bv_val : "(null)" );
#endif /* LDAP_SYNC_TRACE */
		}

		if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) {
			if ( ber_scanf( ber, "b", &refreshDeletes ) == LBER_ERROR ) {
				goto done;
			}
		}

		if ( ber_scanf( ber, /*"{"*/ "[W]}", &syncUUIDs ) == LBER_ERROR
			|| syncUUIDs == NULL )
		{
			goto done;
		}

		if ( refreshDeletes ) {
			phase = LDAP_SYNC_CAPI_DELETES_IDSET;

		} else {
			phase = LDAP_SYNC_CAPI_PRESENTS_IDSET;
		}

		/* FIXME: should touch ls->ls_refreshPhase? */
		if ( ls->ls_intermediate ) {
			ls->ls_intermediate( ls, res, syncUUIDs, phase );
		}

		ber_bvarray_free( syncUUIDs );
		break;

	default:
#ifdef LDAP_SYNC_TRACE
		fprintf( stderr, "\t\tunknown tag!\n" );
#endif /* LDAP_SYNC_TRACE */
		goto done;
	}

	rc = LDAP_SUCCESS;

done:;
	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	if ( retoid != NULL ) {
		ldap_memfree( retoid );
	}

	if ( retdata != NULL ) {
		ber_bvfree( retdata );
	}

	return rc;
}
示例#24
0
int
fe_extended( Operation *op, SlapReply *rs )
{
	struct extop_list	*ext = NULL;
	struct berval		reqdata = BER_BVNULL;

	if (op->ore_reqdata) {
		reqdata = *op->ore_reqdata;
	}

	ext = find_extop(supp_ext_list, &op->ore_reqoid );
	if ( ext == NULL ) {
		Debug( LDAP_DEBUG_ANY, "%s do_extended: unsupported operation \"%s\"\n",
			op->o_log_prefix, op->ore_reqoid.bv_val, 0 );
		send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR,
			"unsupported extended operation" );
		goto done;
	}

	op->ore_flags = ext->flags;

	Debug( LDAP_DEBUG_ARGS, "do_extended: oid=%s\n",
		op->ore_reqoid.bv_val, 0 ,0 );

	{ /* start of OpenLDAP extended operation */
		BackendDB	*bd = op->o_bd;

		rs->sr_err = (ext->ext_main)( op, rs );

		if( rs->sr_err != SLAPD_ABANDON ) {
			if ( rs->sr_err == LDAP_REFERRAL && rs->sr_ref == NULL ) {
				rs->sr_ref = referral_rewrite( default_referral,
					NULL, NULL, LDAP_SCOPE_DEFAULT );
				if ( !rs->sr_ref ) rs->sr_ref = default_referral;
				if ( !rs->sr_ref ) {
					rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
					rs->sr_text = "referral missing";
				}
			}

			if ( op->o_bd == NULL )
				op->o_bd = bd;
			send_ldap_extended( op, rs );

			if ( rs->sr_ref != default_referral ) {
				ber_bvarray_free( rs->sr_ref );
				rs->sr_ref = NULL;
			}
		}

		if ( rs->sr_rspoid != NULL ) {
			free( (char *)rs->sr_rspoid );
			rs->sr_rspoid = NULL;
		}

		if ( rs->sr_rspdata != NULL ) {
			ber_bvfree( rs->sr_rspdata );
			rs->sr_rspdata = NULL;
		}
	} /* end of OpenLDAP extended operation */

done:;
	return rs->sr_err;
}
示例#25
0
int passwd_extop(
	Operation *op,
	SlapReply *rs )
{
	struct berval id = {0, NULL}, hash, *rsp = NULL;
	req_pwdexop_s *qpw = &op->oq_pwdexop;
	req_extended_s qext = op->oq_extended;
	Modifications *ml;
	slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
	int i, nhash;
	char **hashes, idNul;
	int rc;
	BackendDB *op_be;
	int freenewpw = 0;
	struct berval dn = BER_BVNULL, ndn = BER_BVNULL;

	assert( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) == 0 );

	if( op->o_dn.bv_len == 0 ) {
		Statslog( LDAP_DEBUG_STATS, "%s PASSMOD\n",
			op->o_log_prefix, 0, 0, 0, 0 );
		rs->sr_text = "only authenticated users may change passwords";
		return LDAP_STRONG_AUTH_REQUIRED;
	}

	qpw->rs_old.bv_len = 0;
	qpw->rs_old.bv_val = NULL;
	qpw->rs_new.bv_len = 0;
	qpw->rs_new.bv_val = NULL;
	qpw->rs_mods = NULL;
	qpw->rs_modtail = NULL;

	rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
		&qpw->rs_old, &qpw->rs_new, &rs->sr_text );

	if ( !BER_BVISNULL( &id )) {
		idNul = id.bv_val[id.bv_len];
		id.bv_val[id.bv_len] = '\0';
	}
	if ( rs->sr_err == LDAP_SUCCESS && !BER_BVISEMPTY( &id ) ) {
		Statslog( LDAP_DEBUG_STATS, "%s PASSMOD id=\"%s\"%s%s\n",
			op->o_log_prefix, id.bv_val,
			qpw->rs_old.bv_val ? " old" : "",
			qpw->rs_new.bv_val ? " new" : "", 0 );
	} else {
		Statslog( LDAP_DEBUG_STATS, "%s PASSMOD%s%s\n",
			op->o_log_prefix,
			qpw->rs_old.bv_val ? " old" : "",
			qpw->rs_new.bv_val ? " new" : "", 0, 0 );
	}

	if ( rs->sr_err != LDAP_SUCCESS ) {
		if ( !BER_BVISNULL( &id ))
			id.bv_val[id.bv_len] = idNul;
		return rs->sr_err;
	}

	if ( !BER_BVISEMPTY( &id ) ) {
		rs->sr_err = dnPrettyNormal( NULL, &id, &dn, &ndn, op->o_tmpmemctx );
		id.bv_val[id.bv_len] = idNul;
		if ( rs->sr_err != LDAP_SUCCESS ) {
			rs->sr_text = "Invalid DN";
			rc = rs->sr_err;
			goto error_return;
		}
		op->o_req_dn = dn;
		op->o_req_ndn = ndn;
		op->o_bd = select_backend( &op->o_req_ndn, 1 );

	} else {
		ber_dupbv_x( &dn, &op->o_dn, op->o_tmpmemctx );
		ber_dupbv_x( &ndn, &op->o_ndn, op->o_tmpmemctx );
		op->o_req_dn = dn;
		op->o_req_ndn = ndn;
		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
		op->o_bd = op->o_conn->c_authz_backend;
		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
	}

	if( op->o_bd == NULL ) {
		if ( qpw->rs_old.bv_val != NULL ) {
			rs->sr_text = "unwilling to verify old password";
			rc = LDAP_UNWILLING_TO_PERFORM;
			goto error_return;
		}

#ifdef HAVE_CYRUS_SASL
		rc = slap_sasl_setpass( op, rs );
#else
		rs->sr_text = "no authz backend";
		rc = LDAP_OTHER;
#endif
		goto error_return;
	}

	if ( op->o_req_ndn.bv_len == 0 ) {
		rs->sr_text = "no password is associated with the Root DSE";
		rc = LDAP_UNWILLING_TO_PERFORM;
		goto error_return;
	}

	/* If we've got a glued backend, check the real backend */
	op_be = op->o_bd;
	if ( SLAP_GLUE_INSTANCE( op->o_bd )) {
		op->o_bd = select_backend( &op->o_req_ndn, 0 );
	}

	if (backend_check_restrictions( op, rs,
			(struct berval *)&slap_EXOP_MODIFY_PASSWD ) != LDAP_SUCCESS) {
		rc = rs->sr_err;
		goto error_return;
	}

	/* check for referrals */
	if ( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
		rc = rs->sr_err;
		goto error_return;
	}

	/* This does not apply to multi-master case */
	if(!( !SLAP_SINGLE_SHADOW( op->o_bd ) || be_isupdate( op ))) {
		/* we SHOULD return a referral in this case */
		BerVarray defref = op->o_bd->be_update_refs
			? op->o_bd->be_update_refs : default_referral; 

		if( defref != NULL ) {
			rs->sr_ref = referral_rewrite( op->o_bd->be_update_refs,
				NULL, NULL, LDAP_SCOPE_DEFAULT );
			if(rs->sr_ref) {
				rs->sr_flags |= REP_REF_MUSTBEFREED;
			} else {
				rs->sr_ref = defref;
			}
			rc = LDAP_REFERRAL;
			goto error_return;

		}

		rs->sr_text = "shadow context; no update referral";
		rc = LDAP_UNWILLING_TO_PERFORM;
		goto error_return;
	}

	/* generate a new password if none was provided */
	if ( qpw->rs_new.bv_len == 0 ) {
		slap_passwd_generate( &qpw->rs_new );
		if ( qpw->rs_new.bv_len ) {
			rsp = slap_passwd_return( &qpw->rs_new );
			freenewpw = 1;
		}
	}
	if ( qpw->rs_new.bv_len == 0 ) {
		rs->sr_text = "password generation failed";
		rc = LDAP_OTHER;
		goto error_return;
	}

	op->o_bd = op_be;

	/* Give the backend a chance to handle this itself */
	if ( op->o_bd->be_extended ) {
		rs->sr_err = op->o_bd->be_extended( op, rs );
		if ( rs->sr_err != LDAP_UNWILLING_TO_PERFORM &&
			rs->sr_err != SLAP_CB_CONTINUE )
		{
			rc = rs->sr_err;
			if ( rsp ) {
				rs->sr_rspdata = rsp;
				rsp = NULL;
			}
			goto error_return;
		}
	}

	/* The backend didn't handle it, so try it here */
	if( op->o_bd && !op->o_bd->be_modify ) {
		rs->sr_text = "operation not supported for current user";
		rc = LDAP_UNWILLING_TO_PERFORM;
		goto error_return;
	}

	if ( qpw->rs_old.bv_val != NULL ) {
		Entry *e = NULL;

		rc = be_entry_get_rw( op, &op->o_req_ndn, NULL,
			slap_schema.si_ad_userPassword, 0, &e );
		if ( rc == LDAP_SUCCESS && e ) {
			Attribute *a = attr_find( e->e_attrs,
				slap_schema.si_ad_userPassword );
			if ( a )
				rc = slap_passwd_check( op, e, a, &qpw->rs_old, &rs->sr_text );
			else
				rc = 1;
			be_entry_release_r( op, e );
			if ( rc == LDAP_SUCCESS )
				goto old_good;
		}
		rs->sr_text = "unwilling to verify old password";
		rc = LDAP_UNWILLING_TO_PERFORM;
		goto error_return;
	}

old_good:
	ml = ch_malloc( sizeof(Modifications) );
	if ( !qpw->rs_modtail ) qpw->rs_modtail = &ml->sml_next;

	if ( default_passwd_hash ) {
		for ( nhash = 0; default_passwd_hash[nhash]; nhash++ );
		hashes = default_passwd_hash;
	} else {
		nhash = 1;
		hashes = (char **)defhash;
	}
	ml->sml_numvals = nhash;
	ml->sml_values = ch_malloc( (nhash+1)*sizeof(struct berval) );
	for ( i=0; hashes[i]; i++ ) {
		slap_passwd_hash_type( &qpw->rs_new, &hash, hashes[i], &rs->sr_text );
		if ( hash.bv_len == 0 ) {
			if ( !rs->sr_text ) {
				rs->sr_text = "password hash failed";
			}
			break;
		}
		ml->sml_values[i] = hash;
	}
	ml->sml_values[i].bv_val = NULL;
	ml->sml_nvalues = NULL;
	ml->sml_desc = slap_schema.si_ad_userPassword;
	ml->sml_type = ml->sml_desc->ad_cname;
	ml->sml_op = LDAP_MOD_REPLACE;
	ml->sml_flags = 0;
	ml->sml_next = qpw->rs_mods;
	qpw->rs_mods = ml;

	if ( hashes[i] ) {
		rs->sr_err = LDAP_OTHER;

	} else {
		slap_callback *sc = op->o_callback;

		op->o_tag = LDAP_REQ_MODIFY;
		op->o_callback = &cb;
		op->orm_modlist = qpw->rs_mods;
		op->orm_no_opattrs = 0;
		
		cb.sc_private = qpw;	/* let Modify know this was pwdMod,
					 * if it cares... */

		rs->sr_err = op->o_bd->be_modify( op, rs );

		/* be_modify() might have shuffled modifications */
		qpw->rs_mods = op->orm_modlist;

		if ( rs->sr_err == LDAP_SUCCESS ) {
			rs->sr_rspdata = rsp;

		} else if ( rsp ) {
			ber_bvfree( rsp );
			rsp = NULL;
		}
		op->o_tag = LDAP_REQ_EXTENDED;
		op->o_callback = sc;
	}

	rc = rs->sr_err;
	op->oq_extended = qext;

error_return:;
	if ( qpw->rs_mods ) {
		slap_mods_free( qpw->rs_mods, 1 );
	}
	if ( freenewpw ) {
		free( qpw->rs_new.bv_val );
	}
	if ( !BER_BVISNULL( &dn ) ) {
		op->o_tmpfree( dn.bv_val, op->o_tmpmemctx );
		BER_BVZERO( &op->o_req_dn );
	}
	if ( !BER_BVISNULL( &ndn ) ) {
		op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );
		BER_BVZERO( &op->o_req_ndn );
	}

	return rc;
}
示例#26
0
int
asyncmeta_handle_search_msg(LDAPMessage *res, a_metaconn_t *mc, bm_context_t *bc, int candidate)
{
	a_metainfo_t	*mi;
	a_metatarget_t	*mt;
	a_metasingleconn_t *msc;
	Operation *op = bc->op;
	SlapReply *rs;
	int	   i, rc = LDAP_SUCCESS, sres;
	SlapReply *candidates;
	char		**references = NULL;
	LDAPControl	**ctrls = NULL;
	a_dncookie dc;
	LDAPMessage *msg;
	ber_int_t id;

	rs = &bc->rs;
	mi = mc->mc_info;
	mt = mi->mi_targets[ candidate ];
	msc = &mc->mc_conns[ candidate ];
	dc.op = op;
	dc.target = mt;
	dc.to_from = MASSAGE_REP;
	id = ldap_msgid(res);


	candidates = bc->candidates;
	i = candidate;

	while (res && !META_BACK_CONN_INVALID(msc)) {
	for (msg = ldap_first_message(msc->msc_ldr, res); msg; msg = ldap_next_message(msc->msc_ldr, msg)) {
		switch(ldap_msgtype(msg)) {
		case LDAP_RES_SEARCH_ENTRY:
			Debug( LDAP_DEBUG_TRACE,
				"%s asyncmeta_handle_search_msg: msc %p entry\n",
				op->o_log_prefix, msc );
			if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
				/* don't retry any more... */
				candidates[ i ].sr_type = REP_RESULT;
			}
			/* count entries returned by target */
			candidates[ i ].sr_nentries++;
			if (bc->c_peer_name.bv_val == op->o_conn->c_peer_name.bv_val && !op->o_abandon) {
				rs->sr_err = asyncmeta_send_entry( &bc->copy_op, rs, mc, i, msg );
			} else {
				goto err_cleanup;
			}
			switch ( rs->sr_err ) {
			case LDAP_SIZELIMIT_EXCEEDED:
				asyncmeta_send_ldap_result(bc, op, rs);
				rs->sr_err = LDAP_SUCCESS;
				goto err_cleanup;
			case LDAP_UNAVAILABLE:
				rs->sr_err = LDAP_OTHER;
				break;
			default:
				break;
			}
			bc->is_ok++;
			break;

		case LDAP_RES_SEARCH_REFERENCE:
			if ( META_BACK_TGT_NOREFS( mt ) ) {
				rs->sr_err = LDAP_OTHER;
				asyncmeta_send_ldap_result(bc, op, rs);
				goto err_cleanup;
			}
			if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
				/* don't retry any more... */
				candidates[ i ].sr_type = REP_RESULT;
			}
			bc->is_ok++;
			rc = ldap_parse_reference( msc->msc_ldr, msg,
				   &references, &rs->sr_ctrls, 0 );

			if ( rc != LDAP_SUCCESS || references == NULL ) {
				rs->sr_err = LDAP_OTHER;
				asyncmeta_send_ldap_result(bc, op, rs);
				goto err_cleanup;
			}

			/* FIXME: merge all and return at the end */

			{
				int cnt;
				for ( cnt = 0; references[ cnt ]; cnt++ )
					;

				rs->sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ),
								 op->o_tmpmemctx );

				for ( cnt = 0; references[ cnt ]; cnt++ ) {
					ber_str2bv_x( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ],
							  op->o_tmpmemctx );
				}
				BER_BVZERO( &rs->sr_ref[ cnt ] );
			}

			{
				dc.memctx = op->o_tmpmemctx;
				( void )asyncmeta_referral_result_rewrite( &dc, rs->sr_ref );
			}

			if ( rs->sr_ref != NULL ) {
				if (!BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) {
					/* ignore return value by now */
					( void )send_search_reference( op, rs );
				}

				ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx );
				rs->sr_ref = NULL;
			}

			/* cleanup */
			if ( references ) {
				ber_memvfree( (void **)references );
			}

			if ( rs->sr_ctrls ) {
				ldap_controls_free( rs->sr_ctrls );
				rs->sr_ctrls = NULL;
			}
			break;

		case LDAP_RES_INTERMEDIATE:
			if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
				/* don't retry any more... */
				candidates[ i ].sr_type = REP_RESULT;
			}
			bc->is_ok++;

			/* FIXME: response controls
			 * are passed without checks */
			rs->sr_err = ldap_parse_intermediate( msc->msc_ldr,
								  msg,
								  (char **)&rs->sr_rspoid,
								  &rs->sr_rspdata,
								  &rs->sr_ctrls,
								  0 );
			if ( rs->sr_err != LDAP_SUCCESS ) {
				candidates[ i ].sr_type = REP_RESULT;
				rs->sr_err = LDAP_OTHER;
				asyncmeta_send_ldap_result(bc, op, rs);
				goto err_cleanup;
			}

			slap_send_ldap_intermediate( op, rs );

			if ( rs->sr_rspoid != NULL ) {
				ber_memfree( (char *)rs->sr_rspoid );
				rs->sr_rspoid = NULL;
			}

			if ( rs->sr_rspdata != NULL ) {
				ber_bvfree( rs->sr_rspdata );
				rs->sr_rspdata = NULL;
			}

			if ( rs->sr_ctrls != NULL ) {
				ldap_controls_free( rs->sr_ctrls );
				rs->sr_ctrls = NULL;
			}
			break;

		case LDAP_RES_SEARCH_RESULT:
			if ( mi->mi_idle_timeout != 0 ) {
				asyncmeta_set_msc_time(msc);
			}
			Debug( LDAP_DEBUG_TRACE,
			       "%s asyncmeta_handle_search_msg: msc %p result\n",
			       op->o_log_prefix, msc );
			candidates[ i ].sr_type = REP_RESULT;
			candidates[ i ].sr_msgid = META_MSGID_IGNORE;
			/* NOTE: ignores response controls
			 * (and intermediate response controls
			 * as well, except for those with search
			 * references); this may not be correct,
			 * but if they're not ignored then
			 * back-meta would need to merge them
			 * consistently (think of pagedResults...)
			 */
			/* FIXME: response controls? */
			rs->sr_err = ldap_parse_result( msc->msc_ldr,
							msg,
							&candidates[ i ].sr_err,
								(char **)&candidates[ i ].sr_matched,
							(char **)&candidates[ i ].sr_text,
							&references,
							&ctrls /* &candidates[ i ].sr_ctrls (unused) */ ,
							0 );
			if ( rs->sr_err != LDAP_SUCCESS ) {
				candidates[ i ].sr_err = rs->sr_err;
				sres = slap_map_api2result( &candidates[ i ] );
				candidates[ i ].sr_type = REP_RESULT;
				goto finish;
			}

			rs->sr_err = candidates[ i ].sr_err;

			/* massage matchedDN if need be */
			if ( candidates[ i ].sr_matched != NULL ) {
				struct berval	match, mmatch;

				ber_str2bv( candidates[ i ].sr_matched,
						0, 0, &match );
				candidates[ i ].sr_matched = NULL;

				dc.memctx = NULL;
				asyncmeta_dn_massage( &dc, &match, &mmatch );
				if ( mmatch.bv_val == match.bv_val ) {
					candidates[ i ].sr_matched
						= ch_strdup( mmatch.bv_val );

				} else {
					candidates[ i ].sr_matched = mmatch.bv_val;
				}

				bc->candidate_match++;
				ldap_memfree( match.bv_val );
			}

			/* add references to array */
			/* RFC 4511: referrals can only appear
			 * if result code is LDAP_REFERRAL */
			if ( references != NULL
				 && references[ 0 ] != NULL
				 && references[ 0 ][ 0 ] != '\0' )
			{
				if ( rs->sr_err != LDAP_REFERRAL ) {
					Debug( LDAP_DEBUG_ANY,
						   "%s asncmeta_search_result[%d]: "
						   "got referrals with err=%d\n",
						   op->o_log_prefix,
						   i, rs->sr_err );

				} else {
					BerVarray	sr_ref;
					int		cnt;

					for ( cnt = 0; references[ cnt ]; cnt++ )
						;

					sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ),
								 op->o_tmpmemctx );

					for ( cnt = 0; references[ cnt ]; cnt++ ) {
						ber_str2bv_x( references[ cnt ], 0, 1, &sr_ref[ cnt ],
								  op->o_tmpmemctx );
					}
					BER_BVZERO( &sr_ref[ cnt ] );

					dc.memctx = op->o_tmpmemctx;
					( void )asyncmeta_referral_result_rewrite( &dc, sr_ref );

					if ( rs->sr_v2ref == NULL ) {
						rs->sr_v2ref = sr_ref;

					} else {
						for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
							ber_bvarray_add_x( &rs->sr_v2ref, &sr_ref[ cnt ],
									   op->o_tmpmemctx );
						}
						ber_memfree_x( sr_ref, op->o_tmpmemctx );
					}
				}

			} else if ( rs->sr_err == LDAP_REFERRAL ) {
				Debug( LDAP_DEBUG_TRACE,
					   "%s asyncmeta_search_result[%d]: "
					   "got err=%d with null "
					   "or empty referrals\n",
					   op->o_log_prefix,
					   i, rs->sr_err );

				rs->sr_err = LDAP_NO_SUCH_OBJECT;
			}

			/* cleanup */
			ber_memvfree( (void **)references );

			sres = slap_map_api2result( rs );

			if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
				Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d] "
				       "match=\"%s\" err=%ld",
				       op->o_log_prefix, i,
				       candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
				       (long) candidates[ i ].sr_err );
			} else {
					Debug( LDAP_DEBUG_ANY,  "%s asyncmeta_search_result[%d] "
				       "match=\"%s\" err=%ld (%s)",
				       op->o_log_prefix, i,
				       candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
					       (long) candidates[ i ].sr_err, ldap_err2string( candidates[ i ].sr_err ) );
			}

			switch ( sres ) {
			case LDAP_NO_SUCH_OBJECT:
				/* is_ok is touched any time a valid
				 * (even intermediate) result is
				 * returned; as a consequence, if
				 * a candidate returns noSuchObject
				 * it is ignored and the candidate
				 * is simply demoted. */
				if ( bc->is_ok ) {
					sres = LDAP_SUCCESS;
				}
				break;

			case LDAP_SUCCESS:
				if ( ctrls != NULL && ctrls[0] != NULL ) {
#ifdef SLAPD_META_CLIENT_PR
					LDAPControl *pr_c;

					pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL );
					if ( pr_c != NULL ) {
						BerElementBuffer berbuf;
						BerElement *ber = (BerElement *)&berbuf;
						ber_tag_t tag;
						ber_int_t prsize;
						struct berval prcookie;

						/* unsolicited, do not accept */
						if ( mt->mt_ps == 0 ) {
							rs->sr_err = LDAP_OTHER;
							goto err_pr;
						}

						ber_init2( ber, &pr_c->ldctl_value, LBER_USE_DER );

						tag = ber_scanf( ber, "{im}", &prsize, &prcookie );
						if ( tag == LBER_ERROR ) {
							rs->sr_err = LDAP_OTHER;
							goto err_pr;
						}

						/* more pages? new search request */
						if ( !BER_BVISNULL( &prcookie ) && !BER_BVISEMPTY( &prcookie ) ) {
							if ( mt->mt_ps > 0 ) {
								/* ignore size if specified */
								prsize = 0;

							} else if ( prsize == 0 ) {
								/* guess the page size from the entries returned so far */
								prsize = candidates[ i ].sr_nentries;
							}

							candidates[ i ].sr_nentries = 0;
							candidates[ i ].sr_msgid = META_MSGID_IGNORE;
							candidates[ i ].sr_type = REP_INTERMEDIATE;

							assert( candidates[ i ].sr_matched == NULL );
							assert( candidates[ i ].sr_text == NULL );
							assert( candidates[ i ].sr_ref == NULL );

							switch ( asyncmeta_back_search_start( &bc->copy_op, rs, mc, bc, i, &prcookie, prsize, 1 ) )
							{
							case META_SEARCH_CANDIDATE:
								assert( candidates[ i ].sr_msgid >= 0 );
								ldap_controls_free( ctrls );
								//	goto free_message;

							case META_SEARCH_ERR:
							case META_SEARCH_NEED_BIND:
err_pr:;
								candidates[ i ].sr_err = rs->sr_err;
								candidates[ i ].sr_type = REP_RESULT;
								if ( META_BACK_ONERR_STOP( mi ) ) {
									asyncmeta_send_ldap_result(bc, op, rs);
									ldap_controls_free( ctrls );
									goto err_cleanup;
								}
								/* fallthru */

							case META_SEARCH_NOT_CANDIDATE:
								/* means that asyncmeta_back_search_start()
								 * failed but onerr == continue */
								candidates[ i ].sr_msgid = META_MSGID_IGNORE;
								candidates[ i ].sr_type = REP_RESULT;
								break;

							default:
								/* impossible */
								assert( 0 );
								break;
							}
							break;
						}
					}
#endif /* SLAPD_META_CLIENT_PR */

					ldap_controls_free( ctrls );
				}
				/* fallthru */

			case LDAP_REFERRAL:
				bc->is_ok++;
				break;

			case LDAP_SIZELIMIT_EXCEEDED:
				/* if a target returned sizelimitExceeded
				 * and the entry count is equal to the
				 * proxy's limit, the target would have
				 * returned more, and the error must be
				 * propagated to the client; otherwise,
				 * the target enforced a limit lower
				 * than what requested by the proxy;
				 * ignore it */
				candidates[ i ].sr_err = rs->sr_err;
				if ( rs->sr_nentries == op->ors_slimit
					 || META_BACK_ONERR_STOP( mi ) )
				{
					const char *save_text;
got_err:
					save_text = rs->sr_text;
					rs->sr_text = candidates[ i ].sr_text;
					asyncmeta_send_ldap_result(bc, op, rs);
					if (candidates[ i ].sr_text != NULL) {
						ch_free( (char *)candidates[ i ].sr_text );
						candidates[ i ].sr_text = NULL;
					}
					rs->sr_text = save_text;
					ldap_controls_free( ctrls );
					goto err_cleanup;
				}
				break;

			default:
				candidates[ i ].sr_err = rs->sr_err;
				if ( META_BACK_ONERR_STOP( mi ) ) {
					goto got_err;
				}
				break;
			}
			/* if this is the last result we will ever receive, send it back  */
			rc = rs->sr_err;
			if (asyncmeta_is_last_result(mc, bc, i) == 0) {
				Debug( LDAP_DEBUG_TRACE,
					"%s asyncmeta_handle_search_msg: msc %p last result\n",
					op->o_log_prefix, msc );
				asyncmeta_search_last_result(mc, bc, i, sres);
err_cleanup:
				rc = rs->sr_err;
				ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
				asyncmeta_drop_bc( mc, bc);
				asyncmeta_clear_bm_context(bc);
				ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );
				ldap_msgfree(res);
				return rc;
			}
finish:
			break;

		default:
			continue;
		}
	}
		ldap_msgfree(res);
		res = NULL;
		if (candidates[ i ].sr_type != REP_RESULT) {
			struct timeval	tv = {0};
			rc = ldap_result( msc->msc_ldr, id, LDAP_MSG_RECEIVED, &tv, &res );
			if (res != NULL) {
				msc->msc_result_time = slap_get_time();
			}
		}
	}
	ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex );
	bc->bc_active--;
	ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex );

	return rc;
}
示例#27
0
文件: ber.c 项目: hoangduit/reactos
/***********************************************************************
 *      ber_bvfree     (WLDAP32.@)
 *
 * Free a berval structure.
 *
 * PARAMS
 *  berval [I] Pointer to a berval structure.
 *
 * RETURNS
 *  Nothing.
 *
 * NOTES
 *  Use this function only to free berval structures allocated by
 *  an LDAP API.
 */
void CDECL WLDAP32_ber_bvfree( BERVAL *berval )
{
#ifdef HAVE_LDAP
    ber_bvfree( berval );
#endif
}
示例#28
0
static int ldap_set_keytab(krb5_context krbctx,
			   const char *ldap_uri,
			   const char *principal_name,
			   krb5_principal princ,
			   const char *binddn,
			   const char *bindpw,
			   const char *mech,
			   const char *ca_cert_file,
			   struct keys_container *keys)
{
	LDAP *ld = NULL;
	BerElement *sctrl = NULL;
	struct berval *control = NULL;
	LDAPControl **srvctrl = NULL;
	int ret;
	int kvno, i;
	ber_tag_t rtag;
	ber_int_t *encs = NULL;
	int successful_keys = 0;

	/* cant' return more than nkeys, sometimes less */
	encs = calloc(keys->nkeys + 1, sizeof(ber_int_t));
	if (!encs) {
		fprintf(stderr, _("Out of Memory!\n"));
		return 0;
	}

	/* build password change control */
	control = create_key_control(keys, principal_name);
	if (!control) {
		fprintf(stderr, _("Failed to create control!\n"));
		goto error_out;
	}

    ret = ipa_ldap_bind(ldap_uri, princ, binddn, bindpw, mech, ca_cert_file, &ld);
    if (ret != LDAP_SUCCESS) {
        fprintf(stderr, _("Failed to bind to server!\n"));
        goto error_out;
    }

    /* perform password change */
    ret = ipa_ldap_extended_op(ld, KEYTAB_SET_OID, control, &srvctrl);
    if (ret != LDAP_SUCCESS) {
        fprintf(stderr, _("Failed to get keytab!\n"));
        goto error_out;
    }

	ber_bvfree(control);
	control = NULL;

	sctrl = get_control_data(srvctrl, KEYTAB_RET_OID);
	if (!sctrl) {
		fprintf(stderr, _("ber_init() failed, Invalid control ?!\n"));
		goto error_out;
	}

	/* Format of response
	 *
	 * KeytabGetRequest ::= SEQUENCE {
	 * 	new_kvno	Int32
	 * 	SEQUENCE OF	KeyTypes
	 * }
	 *
	 * * List of accepted enctypes *
	 * KeyTypes ::= SEQUENCE {
	 * 	enctype		Int32
	 * }
	 */

	rtag = ber_scanf(sctrl, "{i{", &kvno);
	if (rtag == LBER_ERROR) {
		fprintf(stderr, _("ber_scanf() failed, unable to find kvno ?!\n"));
		goto error_out;
	}

	for (i = 0; i < keys->nkeys; i++) {
		ret = ber_scanf(sctrl, "{i}", &encs[i]);
		if (ret == LBER_ERROR) {
			char enc[79]; /* fit std terminal or truncate */
			krb5_error_code krberr;
			krberr = krb5_enctype_to_string(
				keys->ksdata[i].enctype, enc, 79);
			if (krberr) {
				fprintf(stderr, _("Failed to retrieve "
					"encryption type type #%d\n"),
					keys->ksdata[i].enctype);
			} else {
				fprintf(stderr, _("Failed to retrieve "
					"encryption type %1$s (#%2$d)\n"),
					enc, keys->ksdata[i].enctype);
			}
                } else {
			successful_keys++;
		}
	}

	if (successful_keys == 0) {
		fprintf(stderr, _("Failed to retrieve any keys"));
		goto error_out;
	}

	ret = filter_keys(krbctx, keys, encs);
	if (ret == 0) goto error_out;

	ber_free(sctrl, 1);
	ldap_controls_free(srvctrl);
	ldap_unbind_ext(ld, NULL, NULL);
	free(encs);
	return kvno;

error_out:
	if (sctrl) ber_free(sctrl, 1);
	if (srvctrl) ldap_controls_free(srvctrl);
	if (ld) ldap_unbind_ext(ld, NULL, NULL);
	if (control) ber_bvfree(control);
	free(encs);
	return -1;
}
示例#29
0
static int ldap_get_keytab(krb5_context krbctx, bool generate, char *password,
                           const char *enctypes, const char *ldap_uri,
                           const char *svc_princ, krb5_principal bind_princ,
                           const char *bind_dn, const char *bind_pw,
                           const char *mech,
                           const char *ca_cert_file,
                           struct keys_container *keys, int *kvno,
                           char **err_msg)
{
    struct krb_key_salt *es = NULL;
    int num_es = 0;
    struct berval *control = NULL;
    LDAP *ld = NULL;
    LDAPControl **srvctrl = NULL;
    struct berval data;
    bool res;
    int ret;

    *err_msg = NULL;

    if (enctypes) {
        ret = ipa_string_to_enctypes(enctypes, &es, &num_es, err_msg);
        if (ret || num_es == 0) {
            return LDAP_OPERATIONS_ERROR;
        }
    }

    control = create_getkeytab_control(svc_princ, generate,
                                       password, es, num_es);
    if (!control) {
        *err_msg = _("Failed to create control!\n");
        ret = LDAP_OPERATIONS_ERROR;
        goto done;
    }

    ret = ipa_ldap_bind(ldap_uri, bind_princ, bind_dn, bind_pw, mech,
                        ca_cert_file, &ld);
    if (ret != LDAP_SUCCESS) {
        *err_msg = _("Failed to bind to server!\n");
        goto done;
    }

    /* perform extedned opt to get keytab */
    ret = ipa_ldap_extended_op(ld, KEYTAB_GET_OID, control, &srvctrl);
    if (ret != LDAP_SUCCESS) {
        goto done;
    }

    ret = find_control_data(srvctrl, KEYTAB_GET_OID, &data);
    if (ret != LDAP_SUCCESS) goto done;

    res = ipaasn1_dec_getktreply(data.bv_val, data.bv_len, kvno, keys);
    if (!res) {
        *err_msg = _("Failed to decode control reply!\n");
        ret = LDAP_OPERATIONS_ERROR;
        goto done;
    }

    ret = LDAP_SUCCESS;

done:
    if (ld) ldap_unbind_ext(ld, NULL, NULL);
    if (control) ber_bvfree(control);
    free(es);
    if (ret) {
        free_keys_contents(krbctx, keys);
    }
    return ret;
}
示例#30
0
文件: sasl.c 项目: 0x24bin/winexe-1
/* 
   perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
*/
static ADS_STATUS ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
{
	ADS_STATUS status;
	bool ok;
	uint32 minor_status;
	int gss_rc, rc;
	gss_OID_desc krb5_mech_type =
	{9, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
	gss_OID mech_type = &krb5_mech_type;
	gss_OID actual_mech_type = GSS_C_NULL_OID;
	const char *spnego_mechs[] = {OID_KERBEROS5_OLD, OID_KERBEROS5, OID_NTLMSSP, NULL};
	gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
	gss_buffer_desc input_token, output_token;
	uint32 req_flags, ret_flags;
	uint32 req_tmp, ret_tmp;
	DATA_BLOB unwrapped;
	DATA_BLOB wrapped;
	struct berval cred, *scred = NULL;

	input_token.value = NULL;
	input_token.length = 0;

	req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
	switch (ads->ldap.wrap_type) {
	case ADS_SASLWRAP_TYPE_SEAL:
		req_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
		break;
	case ADS_SASLWRAP_TYPE_SIGN:
		req_flags |= GSS_C_INTEG_FLAG;
		break;
	case ADS_SASLWRAP_TYPE_PLAIN:
		break;
	}

	/* Note: here we explicit ask for the krb5 mech_type */
	gss_rc = gss_init_sec_context(&minor_status,
				      GSS_C_NO_CREDENTIAL,
				      &context_handle,
				      serv_name,
				      mech_type,
				      req_flags,
				      0,
				      NULL,
				      &input_token,
				      &actual_mech_type,
				      &output_token,
				      &ret_flags,
				      NULL);
	if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
		status = ADS_ERROR_GSS(gss_rc, minor_status);
		goto failed;
	}

	/*
	 * As some gssapi krb5 mech implementations
	 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
	 * to req_flags internaly, it's not possible to
	 * use plain or signing only connection via
	 * the gssapi interface.
	 *
	 * Because of this we need to check it the ret_flags
	 * has more flags as req_flags and correct the value
	 * of ads->ldap.wrap_type.
	 *
	 * I ads->auth.flags has ADS_AUTH_SASL_FORCE
	 * we need to give an error.
	 */
	req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
	ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);

	if (req_tmp == ret_tmp) {
		/* everythings fine... */

	} else if (req_flags & GSS_C_CONF_FLAG) {
		/*
		 * here we wanted sealing but didn't got it
		 * from the gssapi library
		 */
		status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
		goto failed;

	} else if ((req_flags & GSS_C_INTEG_FLAG) &&
		   !(ret_flags & GSS_C_INTEG_FLAG)) {
		/*
		 * here we wanted siging but didn't got it
		 * from the gssapi library
		 */
		status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
		goto failed;

	} else if (ret_flags & GSS_C_CONF_FLAG) {
		/*
		 * here we didn't want sealing
		 * but the gssapi library forces it
		 * so correct the needed wrap_type if
		 * the caller didn't forced siging only
		 */
		if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
			status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
			goto failed;
		}

		ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
		req_flags = ret_flags;

	} else if (ret_flags & GSS_C_INTEG_FLAG) {
		/*
		 * here we didn't want signing
		 * but the gssapi library forces it
		 * so correct the needed wrap_type if
		 * the caller didn't forced plain
		 */
		if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
			status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
			goto failed;
		}

		ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
		req_flags = ret_flags;
	} else {
		/*
		 * This could (should?) not happen
		 */
		status = ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
		goto failed;
	
	}

	/* and wrap that in a shiny SPNEGO wrapper */
	unwrapped = data_blob_const(output_token.value, output_token.length);
	wrapped = gen_negTokenTarg(spnego_mechs, unwrapped);
	gss_release_buffer(&minor_status, &output_token);
	if (unwrapped.length > wrapped.length) {
		status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
		goto failed;
	}

	cred.bv_val = (char *)wrapped.data;
	cred.bv_len = wrapped.length;

	rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, 
			      &scred);
	data_blob_free(&wrapped);
	if (rc != LDAP_SUCCESS) {
		status = ADS_ERROR(rc);
		goto failed;
	}

	if (scred) {
		wrapped = data_blob_const(scred->bv_val, scred->bv_len);
	} else {
		wrapped = data_blob_null;
	}

	ok = spnego_parse_auth_response(wrapped, NT_STATUS_OK,
					OID_KERBEROS5_OLD,
					&unwrapped);
	if (scred) ber_bvfree(scred);
	if (!ok) {
		status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
		goto failed;
	}

	input_token.value	= unwrapped.data;
	input_token.length	= unwrapped.length;

	/* 
	 * As we asked for mutal authentication
	 * we need to pass the servers response
	 * to gssapi
	 */
	gss_rc = gss_init_sec_context(&minor_status,
				      GSS_C_NO_CREDENTIAL,
				      &context_handle,
				      serv_name,
				      mech_type,
				      req_flags,
				      0,
				      NULL,
				      &input_token,
				      &actual_mech_type,
				      &output_token,
				      &ret_flags,
				      NULL);
	data_blob_free(&unwrapped);
	if (gss_rc) {
		status = ADS_ERROR_GSS(gss_rc, minor_status);
		goto failed;
	}

	gss_release_buffer(&minor_status, &output_token);

	/*
	 * If we the sign and seal options
	 * doesn't match after getting the response
	 * from the server, we don't want to use the connection
	 */
	req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
	ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);

	if (req_tmp != ret_tmp) {
		/* everythings fine... */
		status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
		goto failed;
	}

	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
		uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;

		gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
					     (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
					     GSS_C_QOP_DEFAULT,
					     max_msg_size, &ads->ldap.out.max_unwrapped);
		if (gss_rc) {
			status = ADS_ERROR_GSS(gss_rc, minor_status);
			goto failed;
		}

		ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
		ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
		ads->ldap.in.max_wrapped = max_msg_size;
		status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
		if (!ADS_ERR_OK(status)) {
			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
				ads_errstr(status)));
			goto failed;
		}
		/* make sure we don't free context_handle */
		context_handle = GSS_C_NO_CONTEXT;
	}

	status = ADS_SUCCESS;

failed:
	if (context_handle != GSS_C_NO_CONTEXT)
		gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
	return status;
}