Esempio n. 1
0
/*
 * Parse the value from an LDAPv3 "Persistent Search" control.  They look
 * like this:
 * 
 *    PersistentSearch ::= SEQUENCE {
 *	changeTypes INTEGER,
 *	-- the changeTypes field is the logical OR of 
 *	-- one or more of these values: add (1), delete (2),
 *	-- modify (4), modDN (8).  It specifies which types of
 *	-- changes will cause an entry to be returned.
 *	changesOnly BOOLEAN, -- skip initial search?
 *	returnECs BOOLEAN,   -- return "Entry Change" controls?
 *   }
 *
 * Return an LDAP error code (LDAP_SUCCESS if all goes well).
 *
 * This function is standalone; it does not require initialization of
 * the PS subsystem.
 */
int
ps_parse_control_value( struct berval *psbvp, ber_int_t *changetypesp, int *changesonlyp, int *returnecsp )
{
    int rc= LDAP_SUCCESS;

    if ( psbvp->bv_len == 0 || psbvp->bv_val == NULL )
    {
    	rc= LDAP_PROTOCOL_ERROR;
    }
    else
    {
        BerElement *ber= ber_init( psbvp );
        if ( ber == NULL )
        {
        	rc= LDAP_OPERATIONS_ERROR;
        }
        else
        {
            if ( ber_scanf( ber, "{ibb}", changetypesp, changesonlyp, returnecsp ) == LBER_ERROR )
            {
            	rc= LDAP_PROTOCOL_ERROR;
            }
        	/* the ber encoding is no longer needed */
        	ber_free(ber,1);
        }
    }

    return( rc );
}
Esempio n. 2
0
int
allocate_oid_info_list(struct oid_info_head *list, msgpack_object *o, struct cid_info *ci)
{
	int i;
	struct oid_info *oi;
	char tmp_buf[2048];
	struct ber e;

	for (i = 0; i < o->via.array.size; i++) {
		if (o->via.array.ptr[i].type != MSGPACK_OBJECT_RAW) goto not_good;
		e = ber_init(tmp_buf, 2048);
		if (encode_string_oid(o->via.array.ptr[i].via.raw.ptr, o->via.array.ptr[i].via.raw.size, &e) < 0)	goto not_good;

		oi = malloc(sizeof(*oi));
		if (!oi)
			croak(2, "allocate_oid_info_list: malloc(oid_info)");
		PS.active_oid_infos++;
		PS.total_oid_infos++;
		bzero(oi, sizeof(*oi));
		oi->cid = ci->cid;
		oi->fd  = ci->fd;
		oi->oid = ber_dup(&e);

		TAILQ_INSERT_TAIL(list, oi, oid_list);
	}
	return o->via.array.size;

not_good:
	free_oid_info_list(list);
	return 0;
}
Esempio n. 3
0
int main(int argc, char **argv) {
	BerElement *dummy;
	char *foo = "bar";

	dummy = ber_init(ber_bvstrdup(foo));
	return 0;
}
Esempio n. 4
0
/** Converts the reply into server version and a return code
 *
 * This function takes the reply BER Value and decodes the NMAS server version and return code and if a non
 * null retData buffer was supplied, tries to decode the the return data and length.
 *
 @verbatim
	ResponseBer contents:
		server_version		INTEGER
		error       		INTEGER
		data			OCTET STRING
 @endverbatim
 *
 * @param[in] reply_bv reply data from extended request.
 * @param[out] server_version that responded.
 * @param[out] out data.
 * @param[out] outlen Length of data written to out.
 * @return 0 on success, and < 0 on error.
 */
static int ber_decode_login_data(struct berval *reply_bv, int *server_version, void *out, size_t *outlen)
{
	int rc = 0;
	int err = 0;
	BerElement *reply_ber = NULL;

	rad_assert(out != NULL);
	rad_assert(outlen != NULL);

	if ((reply_ber = ber_init(reply_bv)) == NULL) {
		err = NMAS_E_SYSTEM_RESOURCES;
		goto finish;
	}

	rc = ber_scanf(reply_ber, "{iis}", server_version, &err, out, outlen);
	if (rc == -1) {
		err = NMAS_E_FRAG_FAILURE;
		goto finish;
	}

finish:

	if(reply_ber) ber_free(reply_ber, 1);

	return err;
}
Esempio n. 5
0
/***********************************************************************
 *      ber_init     (WLDAP32.@)
 *
 * Initialise a berelement structure from a berval structure.
 *
 * PARAMS
 *  berval [I] Pointer to a berval structure.
 *
 * RETURNS
 *  Success: Pointer to a berelement structure.
 *  Failure: NULL
 *
 * NOTES
 *  Call ber_free to free the returned berelement structure.
 */
BerElement * CDECL WLDAP32_ber_init( BERVAL *berval )
{
#ifdef HAVE_LDAP
    return ber_init( berval );
#else
    return NULL;
#endif
}
Esempio n. 6
0
static BerElement *get_control_data(LDAPControl **list, const char *repoid)
{
    struct berval data;
    int ret;

    ret = find_control_data(list, repoid, &data);
    if (ret != LDAP_SUCCESS) return NULL;

    return ber_init(&data);
}
Esempio n. 7
0
int ldap_parse_virtuallist_control(LDAP *ld, LDAPControl **ctrls,
	unsigned long *target_posp, unsigned long *list_sizep, int *errcodep)
{
	BerElement *ber;
	int i, foundListControl;
	LDAPControl *listCtrlp;

	if (NULL == ld)
		return (LDAP_PARAM_ERROR);

	/* only ldapv3 or higher can do virtual lists. */
	if (ld->ld_version != LDAP_VERSION3) {
		ld->ld_errno = LDAP_NOT_SUPPORTED;
		return (LDAP_NOT_SUPPORTED);
	}

	/* find the listControl in the list of controls if it exists */
	if (ctrls == NULL) {
		ld->ld_errno = LDAP_NOT_SUPPORTED;
		return (LDAP_NOT_SUPPORTED);
	}

	foundListControl = 0;
	for (i = 0; ((ctrls[i] != NULL) && (!foundListControl)); i++) {
		foundListControl = !(strcmp(ctrls[i]->ldctl_oid,
			LDAP_CONTROL_VLVRESPONSE));
	}
	if (!foundListControl) {
		ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
		return (LDAP_CONTROL_NOT_FOUND);
	} else {
		/* let local var point to the listControl */
		listCtrlp = ctrls[i-1];
	}

	/* allocate a Ber element with the contents of the list_control's */
	/* struct berval */
	if ((ber = ber_init(&listCtrlp->ldctl_value)) == NULL) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return (LDAP_NO_MEMORY);
	}

	/* decode the result from the Berelement */
	if (LBER_ERROR == ber_scanf(ber, "{iie}", target_posp, list_sizep,
		errcodep)) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		ber_free(ber, 1);
		return (LDAP_DECODING_ERROR);
	}

	/* the ber encoding is no longer needed */
	ber_free(ber, 1);

	return (LDAP_SUCCESS);
}
Esempio n. 8
0
File: dds.c Progetto: 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;
}
Esempio n. 9
0
int ipapwd_get_cur_kvno(Slapi_Entry *target)
{
    Slapi_Attr *krbPrincipalKey = NULL;
    Slapi_ValueSet *svs;
    Slapi_Value *sv;
    BerElement *be = NULL;
    const struct berval *cbval;
    ber_tag_t tag, tmp;
    ber_int_t tkvno;
    int hint;
    int kvno;
    int ret;

    /* retrieve current kvno and and keys */
    ret = slapi_entry_attr_find(target, "krbPrincipalKey", &krbPrincipalKey);
    if (ret != 0) {
        return 0;
    }

    kvno = 0;

    slapi_attr_get_valueset(krbPrincipalKey, &svs);
    hint = slapi_valueset_first_value(svs, &sv);
    while (hint != -1) {
        cbval = slapi_value_get_berval(sv);
        if (!cbval) {
            LOG_TRACE("Error retrieving berval from Slapi_Value\n");
            goto next;
        }
        be = ber_init(discard_const(cbval));
        if (!be) {
            LOG_TRACE("ber_init() failed!\n");
            goto next;
        }

        tag = ber_scanf(be, "{xxt[i]", &tmp, &tkvno);
        if (tag == LBER_ERROR) {
            LOG_TRACE("Bad OLD key encoding ?!\n");
            ber_free(be, 1);
            goto next;
        }

        if (tkvno > kvno) {
            kvno = tkvno;
        }

        ber_free(be, 1);
next:
        hint = slapi_valueset_next_value(svs, hint, &sv);
    }

    return kvno;
}
Esempio n. 10
0
static inline void vfss_init(VFSS_TYPE* vfss)
{
    vfss->volume.process = INVALID_HANDLE;
    vfss->io = io_create(FAT_SECTOR_SIZE + sizeof(STORAGE_STACK));
    vfss->io_size = FAT_SECTOR_SIZE;
#if (VFS_BER)
    ber_init(vfss);
#endif //VFS_BER

#if (VFS_NO_FS == 0)
#if (VFS_SFS)
    sfs_init(vfss);
#else
    fat16_init(vfss);
#endif  // VFS_SFS
#endif // VFS_NO_FS
}
Esempio n. 11
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;
}
Esempio n. 12
0
int
ldap_parse_pageresponse_control(
	LDAP *ld,
	LDAPControl *ctrl,
	ber_int_t *countp,
	struct berval *cookie )
{
	BerElement *ber;
	ber_tag_t tag;
	ber_int_t count;

	if ( ld == NULL || ctrl == NULL || cookie == NULL ) {
		if ( ld )
			ld->ld_errno = LDAP_PARAM_ERROR;
		return LDAP_PARAM_ERROR;
	}

	/* Create a BerElement from the berval returned in the control. */
	ber = ber_init( &ctrl->ldctl_value );

	if ( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	/* Extract the count and cookie from the control. */
	tag = ber_scanf( ber, "{io}", &count, cookie );
        ber_free( ber, 1 );

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

		if ( countp != NULL ) {
			*countp = (unsigned long)count;
		}
	}

	return ld->ld_errno;
}
Esempio n. 13
0
int ldap_parse_page_control(LDAP *ld, LDAPControl **controls, unsigned int *totalcount, struct berval **cookie)
{
	int i, rc;
	BerElement *theBer;
	LDAPControl *listCtrlp;
	
	for (i = 0; controls[i] != NULL; i++){
		if (strcmp(controls[i]->ldctl_oid, "1.2.840.113556.1.4.319") == 0) {
			listCtrlp = controls[i];
			if ((theBer = ber_init(&listCtrlp->ldctl_value)) == NULLBER){
				return (LDAP_NO_MEMORY);
			}
			if ((rc = ber_scanf(theBer, "{iO}", totalcount, cookie)) == LBER_ERROR){
				ber_free(theBer, 1);
				return (LDAP_DECODING_ERROR);
			}
			ber_free(theBer, 1);
			return (LDAP_SUCCESS);
		}
	}
	return (LDAP_CONTROL_NOT_FOUND);
}
Esempio n. 14
0
/***********************************************************************
 *      ldap_parse_page_controlW      (WLDAP32.@)
 */
ULONG CDECL ldap_parse_page_controlW( WLDAP32_LDAP *ld, PLDAPControlW *ctrls,
    ULONG *count, struct WLDAP32_berval **cookie )
{
    ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
#ifdef HAVE_LDAP
    LDAPControlW *control = NULL;
    BerElement *ber;
    ber_tag_t tag;
    ULONG i;

    TRACE( "(%p, %p, %p, %p)\n", ld, ctrls, count, cookie );

    if (!ld || !ctrls || !count || !cookie)
        return WLDAP32_LDAP_PARAM_ERROR;

    for (i = 0; ctrls[i]; i++)
    {
        if (!lstrcmpW( LDAP_PAGED_RESULT_OID_STRING_W, ctrls[i]->ldctl_oid ))
            control = ctrls[i];
    }

    if (!control)
        return WLDAP32_LDAP_CONTROL_NOT_FOUND; 
            
    ber = ber_init( &((LDAPControl *)control)->ldctl_value );
    if (!ber)
        return WLDAP32_LDAP_NO_MEMORY;

    tag = ber_scanf( ber, "{iO}", count, cookie );
    if ( tag == LBER_ERROR )
        ret = WLDAP32_LDAP_DECODING_ERROR;
    else
        ret = WLDAP32_LDAP_SUCCESS;

    ber_free( ber, 1 );
    
#endif
    return ret;
}
Esempio n. 15
0
struct oid_info *
allocate_oid_info(msgpack_object *o, struct cid_info *ci)
{
	struct oid_info *oi;
	char tmp_buf[2048];
	struct ber e;

	if (o->type != MSGPACK_OBJECT_RAW) return NULL;
	e = ber_init(tmp_buf, 2048);
	if (encode_string_oid(o->via.raw.ptr, o->via.raw.size, &e) < 0)	return NULL;

	oi = malloc(sizeof(*oi));
	if (!oi)
		croak(2, "allocate_oid_info: malloc(oid_info)");
	PS.active_oid_infos++;
	PS.total_oid_infos++;
	bzero(oi, sizeof(*oi));
	oi->cid = ci->cid;
	oi->fd  = ci->fd;
	oi->oid = ber_dup(&e);

	return oi;
}
Esempio n. 16
0
static int berDecodeLoginData(
    struct berval *replyBV,
    int      *serverVersion,
    size_t   *retDataLen,
    void     *retData )
{
    int err = 0;
    BerElement *replyBer = NULL;
    char    *retOctStr = NULL;
    size_t  retOctStrLen = 0;

    if ((replyBer = ber_init(replyBV)) == NULL) {
        err = LDAP_OPERATIONS_ERROR;
        goto Cleanup;
    }

    if (retData) {
        retOctStrLen = *retDataLen + 1;
        retOctStr = SMB_MALLOC_ARRAY(char, retOctStrLen);
        if (!retOctStr) {
            err = LDAP_OPERATIONS_ERROR;
            goto Cleanup;
        }

        if (ber_scanf(replyBer, "{iis}", serverVersion, &err, retOctStr, &retOctStrLen) != -1) {
            if (*retDataLen >= retOctStrLen) {
                memcpy(retData, retOctStr, retOctStrLen);
            } else if (!err) {
                err = LDAP_NO_MEMORY;
            }

            *retDataLen = retOctStrLen;
        } else if (!err) {
            err = LDAP_DECODING_ERROR;
        }
    } else {
        if (ber_scanf(replyBer, "{ii}", serverVersion, &err) == -1) {
Esempio n. 17
0
int
ldap_parse_passwordpolicy_control(
	LDAP           *ld,
	LDAPControl    *ctrl,
	ber_int_t      *expirep,
	ber_int_t      *gracep,
	LDAPPasswordPolicyError *errorp )
{
	BerElement  *ber;
	int exp = -1, grace = -1;
	ber_tag_t tag;
	ber_len_t berLen;
        char *last;
	int err = PP_noError;
        
	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( ctrl != NULL );

	/* Create a BerElement from the berval returned in the control. */
	ber = ber_init(&ctrl->ldctl_value);

	if (ber == NULL) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return(ld->ld_errno);
	}

	tag = ber_peek_tag( ber, &berLen );
	if (tag != LBER_SEQUENCE) goto exit;

	for( tag = ber_first_element( ber, &berLen, &last );
		tag != LBER_DEFAULT;
		tag = ber_next_element( ber, &berLen, last ) )
	{
		switch (tag) {
		case PPOLICY_WARNING:
			ber_skip_tag(ber, &berLen );
			tag = ber_peek_tag( ber, &berLen );
			switch( tag ) {
			case PPOLICY_EXPIRE:
				if (ber_get_int( ber, &exp ) == LBER_DEFAULT) goto exit;
				break;
			case PPOLICY_GRACE:
				if (ber_get_int( ber, &grace ) == LBER_DEFAULT) goto exit;
				break;
			default:
				goto exit;
			}
			break;
		case PPOLICY_ERROR:
			if (ber_get_enum( ber, &err ) == LBER_DEFAULT) goto exit;
			break;
		default:
			goto exit;
		}
	}

	ber_free(ber, 1);

	/* Return data to the caller for items that were requested. */
	if (expirep) *expirep = exp;
	if (gracep) *gracep = grace;
	if (errorp) *errorp = err;
        
	ld->ld_errno = LDAP_SUCCESS;
	return(ld->ld_errno);

  exit:
	ber_free(ber, 1);
	ld->ld_errno = LDAP_DECODING_ERROR;
	return(ld->ld_errno);
}
Esempio n. 18
0
int
ldap_parse_vlvresponse_control(
	LDAP *ld,
	LDAPControl *ctrl,
	ber_int_t *target_posp,
	ber_int_t *list_countp,
	struct berval  **contextp,
	ber_int_t *errcodep )
{
	BerElement  *ber;
	ber_int_t pos, count, err;
	ber_tag_t tag, berTag;
	ber_len_t berLen;

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

	if (contextp) {
		*contextp = NULL;	 /* Make sure we return a NULL if error occurs. */
	}

	if (ctrl == NULL) {
		ld->ld_errno = LDAP_PARAM_ERROR;
		return(ld->ld_errno);
	}

	if (strcmp(LDAP_CONTROL_VLVRESPONSE, ctrl->ldctl_oid) != 0) {
		/* Not VLV Response control */
		ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
		return(ld->ld_errno);
	}

	/* Create a BerElement from the berval returned in the control. */
	ber = ber_init(&ctrl->ldctl_value);

	if (ber == NULL) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return(ld->ld_errno);
	}

	/* Extract the data returned in the control. */
	tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);

	if( tag == LBER_ERROR) {
		ber_free(ber, 1);
		ld->ld_errno = LDAP_DECODING_ERROR;
		return(ld->ld_errno);
	}


	/* Since the context is the last item encoded, if caller doesn't want
	   it returned, don't decode it. */
	if (contextp) {
		if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
			tag = ber_scanf(ber, "tO", &berTag, contextp);

			if( tag == LBER_ERROR) {
				ber_free(ber, 1);
				ld->ld_errno = LDAP_DECODING_ERROR;
				return(ld->ld_errno);
			}
		}
	}

	ber_free(ber, 1);

	/* Return data to the caller for items that were requested. */
	if (target_posp) *target_posp = pos;
	if (list_countp) *list_countp = count;
	if (errcodep) *errcodep = err;

	ld->ld_errno = LDAP_SUCCESS;
	return(ld->ld_errno);
}
Esempio n. 19
0
int
ldap_parse_session_tracking_control(
	LDAP *ld,
	LDAPControl *ctrl,
	struct berval *ip,
	struct berval *name,
	struct berval *oid,
	struct berval *id )
{
	BerElement	*ber;
	ber_tag_t	tag;
	ber_len_t	len;

	if ( ld == NULL ||
		ctrl == NULL ||
		ip == NULL ||
		name == NULL ||
		oid == NULL ||
		id == NULL )
	{
		if ( ld ) {
			ld->ld_errno = LDAP_PARAM_ERROR;
		}

		/* NOTE: we want the caller to get all or nothing;
		 * we could allow some of the pointers to be NULL,
		 * if one does not want part of the data */
		return LDAP_PARAM_ERROR;
	}

	BER_BVZERO( ip );
	BER_BVZERO( name );
	BER_BVZERO( oid );
	BER_BVZERO( id );

	ber = ber_init( &ctrl->ldctl_value );

	if ( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	tag = ber_skip_tag( ber, &len );
	if ( tag != LBER_SEQUENCE ) {
		tag = LBER_ERROR;
		goto error;
	}

	/* sessionSourceIp */
	tag = ber_peek_tag( ber, &len );
	if ( tag == LBER_DEFAULT ) {
		tag = LBER_ERROR;
		goto error;
	}

	if ( len == 0 ) {
		tag = ber_skip_tag( ber, &len );

	} else {
		if ( len > 128 ) {
			/* should be LDAP_DECODING_ERROR,
			 * but we're liberal in what we accept */
		}
		tag = ber_scanf( ber, "o", ip );
	}

	/* sessionSourceName */
	tag = ber_peek_tag( ber, &len );
	if ( tag == LBER_DEFAULT ) {
		tag = LBER_ERROR;
		goto error;
	}

	if ( len == 0 ) {
		tag = ber_skip_tag( ber, &len );

	} else {
		if ( len > 65536 ) {
			/* should be LDAP_DECODING_ERROR,
			 * but we're liberal in what we accept */
		}
		tag = ber_scanf( ber, "o", name );
	}

	/* formatOID */
	tag = ber_peek_tag( ber, &len );
	if ( tag == LBER_DEFAULT ) {
		tag = LBER_ERROR;
		goto error;
	}

	if ( len == 0 ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		goto error;

	} else {
		if ( len > 1024 ) {
			/* should be LDAP_DECODING_ERROR,
			 * but we're liberal in what we accept */
		}
		tag = ber_scanf( ber, "o", oid );
	}

	/* FIXME: should check if it is an OID... leave it to the caller */

	/* sessionTrackingIdentifier */
	tag = ber_peek_tag( ber, &len );
	if ( tag == LBER_DEFAULT ) {
		tag = LBER_ERROR;
		goto error;
	}

	if ( len == 0 ) {
		tag = ber_skip_tag( ber, &len );

	} else {
#if 0
		if ( len > 65536 ) {
			/* should be LDAP_DECODING_ERROR,
			 * but we're liberal in what we accept */
		}
#endif
		tag = ber_scanf( ber, "o", id );
	}

	/* closure */
	tag = ber_skip_tag( ber, &len );
	if ( tag == LBER_DEFAULT && len == 0 ) {
		tag = 0;
	}

error:;
	(void)ber_free( ber, 1 );

	if ( tag == LBER_ERROR ) {
		return LDAP_DECODING_ERROR;
	}

	return ld->ld_errno;
}
Esempio n. 20
0
/*
 * handle the LDAP_RES_SEARCH_RESULT response
 */
static int
ldap_sync_search_result( ldap_sync_t *ls, LDAPMessage *res )
{
	int		err;
	char		*matched = NULL,
			*msg = NULL;
	LDAPControl	**ctrls = NULL;
	int		rc;
	int		refreshDeletes = -1;

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

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

	/* should not happen in refreshAndPersist... */
	rc = ldap_parse_result( ls->ls_ld,
		res, &err, &matched, &msg, NULL, &ctrls, 0 );
#ifdef LDAP_SYNC_TRACE
	fprintf( stderr,
		"\tldap_parse_result(%d, \"%s\", \"%s\") == %d\n",
		err,
		matched ? matched : "",
		msg ? msg : "",
		rc );
#endif /* LDAP_SYNC_TRACE */
	if ( rc == LDAP_SUCCESS ) {
		rc = err;
	}

	ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE;

	switch ( rc ) {
	case LDAP_SUCCESS: {
		int		i;
		BerElement	*ber = NULL;
		ber_len_t	len;
		struct berval	cookie = { 0 };

		rc = LDAP_OTHER;

		/* deal with control; then fallthru to handler */
		if ( ctrls == NULL ) {
			goto done;
		}

		/* lookup the sync state control */
		for ( i = 0; ctrls[ i ] != NULL; i++ ) {
			if ( strcmp( ctrls[ i ]->ldctl_oid,
				LDAP_CONTROL_SYNC_DONE ) == 0 )
			{
				break;
			}
		}

		/* control must be present; there might be other... */
		if ( ctrls[ i ] == NULL ) {
			goto done;
		}

		/* extract data */
		ber = ber_init( &ctrls[ i ]->ldctl_value );
		if ( ber == NULL ) {
			goto done;
		}

		if ( ber_scanf( ber, "{" /*"}"*/) == LBER_ERROR ) {
			goto ber_done;
		}
		if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
			if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) {
				goto ber_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 */
		}

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

		if ( ber_scanf( ber, /*"{"*/ "}" ) != LBER_ERROR ) {
			rc = LDAP_SUCCESS;
		}

	ber_done:;
		ber_free( ber, 1 );
		if ( rc != LDAP_SUCCESS ) {
			break;
		}

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

		/* FIXME: what should we do with the refreshDelete? */
		switch ( refreshDeletes ) {
		case 0:
			ls->ls_refreshPhase = LDAP_SYNC_CAPI_PRESENTS;
			break;

		default:
			ls->ls_refreshPhase = LDAP_SYNC_CAPI_DELETES;
			break;
		}

		} /* fallthru */

	case LDAP_SYNC_REFRESH_REQUIRED:
		/* TODO: check for Sync Done Control */
		/* FIXME: perhaps the handler should be called
		 * also in case of failure; we'll deal with this
		 * later when implementing refreshOnly */
		if ( ls->ls_search_result ) {
			err = ls->ls_search_result( ls, res, refreshDeletes );
		}
		break;
	}

done:;
	if ( matched != NULL ) {
		ldap_memfree( matched );
	}

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

	if ( ctrls != NULL ) {
		ldap_controls_free( ctrls );
	}

	ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE;

	return rc;
}
Esempio n. 21
0
static struct ipapwd_krbcfg *ipapwd_getConfig(void)
{
    krb5_error_code krberr;
    struct ipapwd_krbcfg *config = NULL;
    krb5_keyblock *kmkey = NULL;
    Slapi_Entry *realm_entry = NULL;
    Slapi_Entry *config_entry = NULL;
    Slapi_Attr *a;
    Slapi_Value *v;
    BerElement *be = NULL;
    ber_tag_t tag, tvno;
    ber_int_t ttype;
    const struct berval *bval;
    struct berval *mkey = NULL;
    char **encsalts;
    char **tmparray;
    char *tmpstr;
    int i, ret;

    config = calloc(1, sizeof(struct ipapwd_krbcfg));
    if (!config) {
        LOG_OOM();
        goto free_and_error;
    }
    kmkey = calloc(1, sizeof(krb5_keyblock));
    if (!kmkey) {
        LOG_OOM();
        goto free_and_error;
    }
    config->kmkey = kmkey;

    krberr = krb5_init_context(&config->krbctx);
    if (krberr) {
        LOG_FATAL("krb5_init_context failed\n");
        goto free_and_error;
    }

    ret = krb5_get_default_realm(config->krbctx, &config->realm);
    if (ret) {
        LOG_FATAL("Failed to get default realm?!\n");
        goto free_and_error;
    }

    /* get the Realm Container entry */
    ret = ipapwd_getEntry(ipa_realm_dn, &realm_entry, NULL);
    if (ret != LDAP_SUCCESS) {
        LOG_FATAL("No realm Entry?\n");
        goto free_and_error;
    }

    /*** get the Kerberos Master Key ***/

    ret = slapi_entry_attr_find(realm_entry, "krbMKey", &a);
    if (ret == -1) {
        LOG_FATAL("No master key??\n");
        goto free_and_error;
    }

    /* there should be only one value here */
    ret = slapi_attr_first_value(a, &v);
    if (ret == -1) {
        LOG_FATAL("No master key??\n");
        goto free_and_error;
    }

    bval = slapi_value_get_berval(v);
    if (!bval) {
        LOG_FATAL("Error retrieving master key berval\n");
        goto free_and_error;
    }

    be = ber_init(discard_const(bval));
    if (!be) {
        LOG_FATAL("ber_init() failed!\n");
        goto free_and_error;
    }

    tag = ber_scanf(be, "{i{iO}}", &tvno, &ttype, &mkey);
    if (tag == LBER_ERROR) {
        LOG_FATAL("Bad Master key encoding ?!\n");
        goto free_and_error;
    }

    config->mkvno = tvno;
    kmkey->magic = KV5M_KEYBLOCK;
    kmkey->enctype = ttype;
    kmkey->length = mkey->bv_len;
    kmkey->contents = malloc(mkey->bv_len);
    if (!kmkey->contents) {
        LOG_OOM();
        goto free_and_error;
    }
    memcpy(kmkey->contents, mkey->bv_val, mkey->bv_len);
    ber_bvfree(mkey);
    ber_free(be, 1);
    mkey = NULL;
    be = NULL;

    /*** get the Supported Enc/Salt types ***/

    encsalts = slapi_entry_attr_get_charray(realm_entry,
                                            "krbSupportedEncSaltTypes");
    if (encsalts) {
        for (i = 0; encsalts[i]; i++) /* count */ ;
        ret = parse_bval_key_salt_tuples(config->krbctx,
                                         (const char * const *)encsalts, i,
                                         &config->supp_encsalts,
                                         &config->num_supp_encsalts);
        slapi_ch_array_free(encsalts);
    } else {
        LOG("No configured salt types use defaults\n");
        for (i = 0; ipapwd_def_encsalts[i]; i++) /* count */ ;
        ret = parse_bval_key_salt_tuples(config->krbctx,
                                         ipapwd_def_encsalts, i,
                                         &config->supp_encsalts,
                                         &config->num_supp_encsalts);
    }
    if (ret) {
        LOG_FATAL("Can't get Supported EncSalt Types\n");
        goto free_and_error;
    }

    /*** get the Preferred Enc/Salt types ***/

    encsalts = slapi_entry_attr_get_charray(realm_entry,
                                            "krbDefaultEncSaltTypes");
    if (encsalts) {
        for (i = 0; encsalts[i]; i++) /* count */ ;
        ret = parse_bval_key_salt_tuples(config->krbctx,
                                         (const char * const *)encsalts, i,
                                         &config->pref_encsalts,
                                         &config->num_pref_encsalts);
        slapi_ch_array_free(encsalts);
    } else {
        LOG("No configured salt types use defaults\n");
        for (i = 0; ipapwd_def_encsalts[i]; i++) /* count */ ;
        ret = parse_bval_key_salt_tuples(config->krbctx,
                                         ipapwd_def_encsalts, i,
                                         &config->pref_encsalts,
                                         &config->num_pref_encsalts);
    }
    if (ret) {
        LOG_FATAL("Can't get Preferred EncSalt Types\n");
        goto free_and_error;
    }

    slapi_entry_free(realm_entry);

    /* get the Realm Container entry */
    ret = ipapwd_getEntry(ipa_pwd_config_dn, &config_entry, NULL);
    if (ret != LDAP_SUCCESS) {
        LOG_FATAL("No config Entry? Impossible!\n");
        goto free_and_error;
    }
    config->passsync_mgrs =
            slapi_entry_attr_get_charray(config_entry, "passSyncManagersDNs");
    /* now add Directory Manager, it is always added by default */
    tmpstr = slapi_ch_strdup("cn=Directory Manager");
    slapi_ch_array_add(&config->passsync_mgrs, tmpstr);
    if (config->passsync_mgrs == NULL) {
        LOG_OOM();
        goto free_and_error;
    }
    for (i = 0; config->passsync_mgrs[i]; i++) /* count */ ;
    config->num_passsync_mgrs = i;

    slapi_entry_free(config_entry);

    /* get the ipa etc/ipaConfig entry */
    config->allow_nt_hash = false;
    ret = ipapwd_getEntry(ipa_etc_config_dn, &config_entry, NULL);
    if (ret != LDAP_SUCCESS) {
        LOG_FATAL("No config Entry?\n");
        goto free_and_error;
    } else {
        tmparray = slapi_entry_attr_get_charray(config_entry,
                                                "ipaConfigString");
        for (i = 0; tmparray && tmparray[i]; i++) {
            if (strcasecmp(tmparray[i], "AllowNThash") == 0) {
                config->allow_nt_hash = true;
                continue;
            }
        }
        if (tmparray) slapi_ch_array_free(tmparray);
    }

    slapi_entry_free(config_entry);

    return config;

free_and_error:
    if (mkey) ber_bvfree(mkey);
    if (be) ber_free(be, 1);
    if (kmkey) {
        free(kmkey->contents);
        free(kmkey);
    }
    if (config) {
        if (config->krbctx) {
            if (config->realm)
                krb5_free_default_realm(config->krbctx, config->realm);
            krb5_free_context(config->krbctx);
        }
        free(config->pref_encsalts);
        free(config->supp_encsalts);
        slapi_ch_array_free(config->passsync_mgrs);
        free(config);
    }
    slapi_entry_free(config_entry);
    slapi_entry_free(realm_entry);
    return NULL;
}
Esempio n. 22
0
int
LDAP_CALL
ldap_parse_sort_control ( 	
     LDAP *ld, 
     LDAPControl **ctrlp,  
     unsigned long *result,
     char **attribute
)
{
	BerElement *ber;
	int i, foundSortControl;
	LDAPControl *sortCtrlp;
	unsigned long len, tag;
	char *attr;

	if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || result == NULL ||
		attribute == NULL ) {
	    return( LDAP_PARAM_ERROR );
	}


	/* find the sortControl in the list of controls if it exists */
	if ( ctrlp == NULL ) {
		LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL );
		return ( LDAP_CONTROL_NOT_FOUND );
	} 
	foundSortControl = 0;
	for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundSortControl )); i++ ) {
		foundSortControl = !strcmp( ctrlp[i]->ldctl_oid, LDAP_CONTROL_SORTRESPONSE );
	}
	if ( !foundSortControl ) {
		LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL );
		return ( LDAP_CONTROL_NOT_FOUND );
	} else {
		/* let local var point to the sortControl */
		sortCtrlp = ctrlp[i-1];			
	}

	/*  allocate a Ber element with the contents of the sort_control's struct berval */
	if ( ( ber = ber_init( &sortCtrlp->ldctl_value ) ) == NULL ) {
		LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
		return( LDAP_NO_MEMORY );
	}		

	/* decode the result from the Berelement */
	if ( ber_scanf( ber, "{i", result ) == LBER_ERROR ) {
		LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
		ber_free( ber, 1 );
		return( LDAP_DECODING_ERROR );
	}

	/* if the server returned one, decode the attribute from the Ber element */
	if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SR_ATTRTYPE ) {
		if ( ber_scanf( ber, "ta", &tag, &attr ) == LBER_ERROR ) {
			LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
			ber_free( ber, 1 );
			return( LDAP_DECODING_ERROR );
		}
		*attribute = attr;		  
	} else {
		*attribute = NULL;
	}

	if ( ber_scanf( ber, "}" ) == LBER_ERROR ) {
		LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
		ber_free( ber, 1 );
		return( LDAP_DECODING_ERROR );
	}

	/* the ber encoding is no longer needed */
	ber_free(ber,1);

	return( LDAP_SUCCESS );
}
Esempio n. 23
0
static int
proxyOld_parse(
	Operation *op,
	SlapReply *rs,
	LDAPControl *ctrl )
{
	int rc;
	BerElement	*ber;
	ber_tag_t	tag;
	struct berval dn = BER_BVNULL;
	struct berval authzDN = BER_BVNULL;


	/* We hijack the flag for the new control. Clearly only one or the
	 * other can be used at any given time.
	 */
	if ( op->o_proxy_authz != SLAP_CONTROL_NONE ) {
		rs->sr_text = "proxy authorization control specified multiple times";
		return LDAP_PROTOCOL_ERROR;
	}

	op->o_proxy_authz = ctrl->ldctl_iscritical
		? SLAP_CONTROL_CRITICAL
		: SLAP_CONTROL_NONCRITICAL;

	/* Parse the control value
	 *  proxyAuthzControlValue ::= SEQUENCE {
	 *		proxyDN	LDAPDN
	 *	}
	 */
	ber = ber_init( &ctrl->ldctl_value );
	if ( ber == NULL ) {
		rs->sr_text = "ber_init failed";
		return LDAP_OTHER;
	}

	tag = ber_scanf( ber, "{m}", &dn );

	if ( tag == LBER_ERROR ) {
		rs->sr_text = "proxyOld control could not be decoded";
		rc = LDAP_OTHER;
		goto done;
	}
	if ( BER_BVISEMPTY( &dn )) {
		Debug( LDAP_DEBUG_TRACE,
			"proxyOld_parse: conn=%lu anonymous\n",
				op->o_connid, 0, 0 );
		authzDN.bv_val = ch_strdup("");
	} else {
		Debug( LDAP_DEBUG_ARGS,
			"proxyOld_parse: conn %lu ctrl DN=\"%s\"\n",
				op->o_connid, dn.bv_val, 0 );
		rc = dnNormalize( 0, NULL, NULL, &dn, &authzDN, op->o_tmpmemctx );
		if ( rc != LDAP_SUCCESS ) {
			goto done;
		}
		rc = slap_sasl_authorized( op, &op->o_ndn, &authzDN );
		if ( rc ) {
			op->o_tmpfree( authzDN.bv_val, op->o_tmpmemctx );
			rs->sr_text = "not authorized to assume identity";
			/* new spec uses LDAP_PROXY_AUTHZ_FAILURE */
			rc = LDAP_INSUFFICIENT_ACCESS;
			goto done;
		}
	}
	free( op->o_ndn.bv_val );
	free( op->o_dn.bv_val );
	op->o_ndn = authzDN;
	ber_dupbv( &op->o_dn, &authzDN );

	Statslog( LDAP_DEBUG_STATS, "conn=%lu op=%lu PROXYOLD dn=\"%s\"\n",
		op->o_connid, op->o_opid,
		authzDN.bv_len ? authzDN.bv_val : "anonymous", 0, 0 );
	rc = LDAP_SUCCESS;
done:
	ber_free( ber, 1 );
	return rc;
}
Esempio n. 24
0
int
ldap_parse_sortresponse_control(
	LDAP *ld,
	LDAPControl *ctrl,
	ber_int_t *returnCode,
	char **attribute )
{
	BerElement *ber;
	ber_tag_t tag, berTag;
	ber_len_t berLen;

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

	if (ld == NULL) {
		return LDAP_PARAM_ERROR;
	}

	if (ctrl == NULL) {
		ld->ld_errno =  LDAP_PARAM_ERROR;
		return(ld->ld_errno);
	}

	if (attribute) {
		*attribute = NULL;
	}

	if ( strcmp(LDAP_CONTROL_SORTRESPONSE, ctrl->ldctl_oid) != 0 ) {
		/* Not sort result control */
		ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
		return(ld->ld_errno);
	}

	/* Create a BerElement from the berval returned in the control. */
	ber = ber_init(&ctrl->ldctl_value);

	if (ber == NULL) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return(ld->ld_errno);
	}

	/* Extract the result code from the control. */
	tag = ber_scanf(ber, "{e" /*}*/, returnCode);

	if( tag == LBER_ERROR ) {
		ber_free(ber, 1);
		ld->ld_errno = LDAP_DECODING_ERROR;
		return(ld->ld_errno);
	}

	/* If caller wants the attribute name, and if it's present in the control,
	   extract the attribute name which caused the error. */
	if (attribute && (LDAP_ATTRTYPES_IDENTIFIER == ber_peek_tag(ber, &berLen)))
	{
		tag = ber_scanf(ber, "ta", &berTag, attribute);

		if (tag == LBER_ERROR ) {
			ber_free(ber, 1);
			ld->ld_errno = LDAP_DECODING_ERROR;
			return(ld->ld_errno);
		}
	}

	ber_free(ber,1);

	ld->ld_errno = LDAP_SUCCESS;
	return(ld->ld_errno);
}
Esempio n. 25
0
/*
 * handle the LDAP_RES_SEARCH_ENTRY response
 */
static int
ldap_sync_search_entry( ldap_sync_t *ls, LDAPMessage *res )
{
	LDAPControl		**ctrls = NULL;
	int			rc = LDAP_OTHER,
				i;
	BerElement		*ber = NULL;
	struct berval		entryUUID = { 0 },
				cookie = { 0 };
	int			state = -1;
	ber_len_t		len;
	ldap_sync_refresh_t	phase;

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

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

	phase = ls->ls_refreshPhase;

	/* OK */

	/* extract:
	 * - data
	 * - entryUUID
	 *
	 * check that:
	 * - Sync State Control is "add"
	 */

	/* the control MUST be present */

	/* extract controls */
	ldap_get_entry_controls( ls->ls_ld, res, &ctrls );
	if ( ctrls == NULL ) {
		goto done;
	}

	/* lookup the sync state control */
	for ( i = 0; ctrls[ i ] != NULL; i++ ) {
		if ( strcmp( ctrls[ i ]->ldctl_oid, LDAP_CONTROL_SYNC_STATE ) == 0 ) {
			break;
		}
	}

	/* control must be present; there might be other... */
	if ( ctrls[ i ] == NULL ) {
		goto done;
	}

	/* extract data */
	ber = ber_init( &ctrls[ i ]->ldctl_value );
	if ( ber == NULL ) {
		goto done;
	}
	/* scan entryUUID in-place ("m") */
	if ( ber_scanf( ber, "{em" /*"}"*/, &state, &entryUUID ) == LBER_ERROR
		|| entryUUID.bv_len == 0 )
	{
		goto done;
	}

	if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
		/* scan cookie in-place ("m") */
		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 */
	}

	switch ( state ) {
	case LDAP_SYNC_PRESENT:
	case LDAP_SYNC_DELETE:
	case LDAP_SYNC_ADD:
	case LDAP_SYNC_MODIFY:
		/* NOTE: ldap_sync_refresh_t is defined
		 * as the corresponding LDAP_SYNC_*
		 * for the 4 above cases */
		phase = state;
#ifdef LDAP_SYNC_TRACE
		fprintf( stderr, "\t\tgot syncState=%s\n", ldap_sync_state2str( state ) );
#endif /* LDAP_SYNC_TRACE */
		break;

	default:
#ifdef LDAP_SYNC_TRACE
		fprintf( stderr, "\t\tgot unknown syncState=%d\n", state );
#endif /* LDAP_SYNC_TRACE */
		goto done;
	}

	rc = ls->ls_search_entry
		? ls->ls_search_entry( ls, res, &entryUUID, phase )
		: LDAP_SUCCESS;

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

	if ( ctrls != NULL ) {
		ldap_controls_free( ctrls );
	}

	return rc;
}
Esempio n. 26
0
File: vc.c Progetto: Joywar/openldap
int ldap_parse_verify_credentials(
	LDAP *ld,
	LDAPMessage *res,
	int * code,
	char ** diagmsg,
    struct berval **cookie,
	struct berval **screds,
	LDAPControl ***ctrls)
{
	int rc;
	char *retoid = NULL;
	struct berval *retdata = NULL;

	assert(ld != NULL);
	assert(LDAP_VALID(ld));
	assert(res != NULL);
	assert(code != NULL);
	assert(diagmsg != NULL);

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

	if( rc != LDAP_SUCCESS ) {
		ldap_perror(ld, "ldap_parse_verify_credentials");
		return rc;
	}

	if (retdata) {
		ber_tag_t tag;
		ber_len_t len;
		ber_int_t i;
		BerElement * ber = ber_init(retdata);
		struct berval diagmsg_bv = BER_BVNULL;
		if (!ber) {
		    rc = ld->ld_errno = LDAP_NO_MEMORY;
			goto done;
		}

		ber_scanf(ber, "{im" /*"}"*/, &i, &diagmsg_bv);
		if ( diagmsg != NULL ) {
			*diagmsg = LDAP_MALLOC( diagmsg_bv.bv_len + 1 );
			AC_MEMCPY( *diagmsg, diagmsg_bv.bv_val, diagmsg_bv.bv_len );
			(*diagmsg)[diagmsg_bv.bv_len] = '\0';
		}
		*code = i;

		tag = ber_peek_tag(ber, &len);
		if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE) {
			ber_scanf(ber, "O", cookie);
		    tag = ber_peek_tag(ber, &len);
		}

		if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_SCREDS) {
			ber_scanf(ber, "O", screds);
		    tag = ber_peek_tag(ber, &len);
		}

		if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS) {
		    int nctrls = 0;
			char * opaque;

		    *ctrls = LDAP_MALLOC(1 * sizeof(LDAPControl *));

			if (!*ctrls) {
				rc = LDAP_NO_MEMORY;
				goto done;
			}

			*ctrls[nctrls] = NULL;

			for(tag = ber_first_element(ber, &len, &opaque);
				tag != LBER_ERROR;
				tag = ber_next_element(ber, &len, opaque))
		    {
				LDAPControl *tctrl;
				LDAPControl **tctrls;

				tctrl = LDAP_CALLOC(1, sizeof(LDAPControl));

				/* allocate pointer space for current controls (nctrls)
				 * + this control + extra NULL
				 */
				tctrls = !tctrl ? NULL : LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));

				if (!tctrls) {
					/* allocation failure */
					if (tctrl) LDAP_FREE(tctrl);
					ldap_controls_free(*ctrls);
					*ctrls = NULL;
				    rc = LDAP_NO_MEMORY;
				    goto done;
				}

				tctrls[nctrls++] = tctrl;
				tctrls[nctrls] = NULL;

				tag = ber_scanf(ber, "{a" /*"}"*/, &tctrl->ldctl_oid);
				if (tag == LBER_ERROR) {
					*ctrls = NULL;
					ldap_controls_free(tctrls);
					rc = LDAP_DECODING_ERROR;
					goto done;
				}

				tag = ber_peek_tag(ber, &len);
				if (tag == LBER_BOOLEAN) {
					ber_int_t crit;
					tag = ber_scanf(ber, "b", &crit);
					tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
				    tag = ber_peek_tag(ber, &len);
				}

			    if (tag == LBER_OCTETSTRING) {
                    tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
                } else {
                    BER_BVZERO( &tctrl->ldctl_value );
                }

                *ctrls = tctrls;
			}
	    }

	    ber_free(ber, 1);
    }

done:
	ber_bvfree(retdata);
	ber_memfree(retoid);
	return rc;
}
Esempio n. 27
0
/*
 * 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;
}
Esempio n. 28
0
static int
_ger_parse_control (
	Slapi_PBlock *pb,
	char **subjectndn,
	int *iscritical,
	char **errbuf
	)
{
	LDAPControl **requestcontrols;
	struct berval *subjectber;
	BerElement *ber;
	size_t subjectndnlen = 0;
	char *orig = NULL;
	char *normed = NULL;

	if (NULL == subjectndn)
	{
		return LDAP_OPERATIONS_ERROR;
	}

	*subjectndn = NULL;

	/*
	 * Get the control
	 */
	slapi_pblock_get ( pb, SLAPI_REQCONTROLS, (void *) &requestcontrols );
	slapi_control_present ( requestcontrols,
							LDAP_CONTROL_GET_EFFECTIVE_RIGHTS,
							&subjectber,
							iscritical );
	if ( subjectber == NULL || subjectber->bv_val == NULL ||
		 subjectber->bv_len == 0 )
	{
		aclutil_str_append ( errbuf, "get-effective-rights: missing subject" );
		slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_parse_control - %s\n", *errbuf );
                if (iscritical)
                    return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* RFC 4511 4.1.11 */
                else
                    return LDAP_INVALID_SYNTAX;
	}

	if ( strncasecmp ( "dn:", subjectber->bv_val, 3 ) == 0 )
	{
		/*
		 * This is a non-standard support to allow the subject being a plain
		 * or base64 encoding string. Hence users using -J option in
		 * ldapsearch don't have to do BER encoding for the subject.
		 */
		orig = slapi_ch_malloc ( subjectber->bv_len + 1 );
		strncpy ( orig, subjectber->bv_val, subjectber->bv_len );
		*(orig + subjectber->bv_len) = '\0';
	}
	else
	{
		ber = ber_init (subjectber);
		if ( ber == NULL )
		{
			aclutil_str_append ( errbuf, "get-effective-rights: ber_init failed for the subject" );
			slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_parse_control - %s\n", *errbuf );
                        if (iscritical)
                            return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* RFC 4511 4.1.11 */
                        else
                            return LDAP_OPERATIONS_ERROR;
		}
		/* "a" means to allocate storage as needed for octet string */
		if ( ber_scanf (ber, "a", &orig) == LBER_ERROR )
		{
			aclutil_str_append ( errbuf, "get-effective-rights: invalid ber tag in the subject" );
			slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_parse_control - %s\n", *errbuf );
			ber_free ( ber, 1 );
                        if (iscritical)
                            return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* RFC 4511 4.1.11 */
                        else
                            return LDAP_INVALID_SYNTAX;
		}
		ber_free ( ber, 1 );
	}

	/*
	 * The current implementation limits the subject to authorization ID
	 * (see section 9 of RFC 2829) only. It also only supports the "dnAuthzId"
	 * flavor, which looks like "dn:<DN>" where null <DN> is for anonymous.
	 */
	subjectndnlen = orig ? strlen(orig) : 0;
	if ( NULL == orig || subjectndnlen < 3 || strncasecmp ( "dn:", orig, 3 ) != 0 )
	{
		aclutil_str_append ( errbuf, "get-effective-rights: subject is not dnAuthzId" );
		slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_parse_control - %s\n", *errbuf );
		slapi_ch_free_string(&orig);
                if (iscritical)
                    return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* RFC 4511 4.1.11 */
                else
                    return LDAP_INVALID_SYNTAX;
	}

	/* memmove is safe for overlapping copy */
	normed = slapi_create_dn_string("%s", orig + 3);
	if (NULL == normed) {
		aclutil_str_append (errbuf, "get-effective-rights: failed to normalize dn: ");
		aclutil_str_append (errbuf, orig);
		slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_parse_control - %s\n", *errbuf);
		slapi_ch_free_string(&orig);
                if (iscritical)
                    return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;  /* RFC 4511 4.1.11 */
                else
                    return LDAP_INVALID_SYNTAX;
	}
	slapi_ch_free_string(&orig);
	*subjectndn = normed;
	slapi_dn_ignore_case(*subjectndn);
	return LDAP_SUCCESS;
}
int LDAP_CALL ldap_parse_userstatus_control(LDAP *ld, LDAPControl **ctrlp,
                                            LDAPuserstatus *us) {
  BerElement *ber = NULL;
  int i, foundUSControl;
  LDAPControl *USCtrlp = NULL;
  ber_tag_t tag;

  if (!NSLDAPI_VALID_LDAP_POINTER(ld) || us == NULL) {
    return (LDAP_PARAM_ERROR);
  }

  /* find the control in the list of controls if it exists */
  if (ctrlp == NULL) {
    LDAP_SET_LDERRNO(ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL);
    return (LDAP_CONTROL_NOT_FOUND);
  }
  foundUSControl = 0;
  for (i = 0; ((ctrlp[i] != NULL) && (!foundUSControl)); i++) {
    foundUSControl = !strcmp(ctrlp[i]->ldctl_oid, LDAP_CONTROL_ACCOUNT_USABLE);
  }
  if (!foundUSControl) {
    LDAP_SET_LDERRNO(ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL);
    return (LDAP_CONTROL_NOT_FOUND);
  } else {
    /* let local var point to the control */
    USCtrlp = ctrlp[i - 1];
  }

  /*  allocate a Ber element with the contents of the control's struct berval */
  if ((ber = ber_init(&USCtrlp->ldctl_value)) == NULL) {
    LDAP_SET_LDERRNO(ld, LDAP_NO_MEMORY, NULL, NULL);
    return (LDAP_NO_MEMORY);
  }

  memset(us, 0, sizeof(struct LDAPuserstatus));

  /*
   * The control value should look like this:
   *
   *  ACCOUNT_USABLE_RESPONSE::= CHOICE {
   *    is_available      [0] INTEGER, ** seconds before expiration **
   *    is_not_available  [1] More_info
   *  }
   *  More_info::= SEQUENCE {
   *    inactive               [0] BOOLEAN DEFAULT FALSE,
   *    reset                  [1] BOOLEAN DEFAULT FALSE,
   *    expired                [2] BOOLEAN DEFAULT FALSE,
   *    remaining_grace        [3] INTEGER OPTIONAL,
   *    seconds_before_unlock  [4] INTEGER OPTIONAL
   *  }
   */

  if ((ber_scanf(ber, "t", &tag)) == LBER_ERROR) {
    LDAP_SET_LDERRNO(ld, LDAP_DECODING_ERROR, NULL, NULL);
    ber_free(ber, 1);
    return (LDAP_DECODING_ERROR);
  }

  tag = ((tag & LBER_CONSTRUCTED) == LBER_CONSTRUCTED) ? 1 : 0;

  if (!tag) {
    us->us_available = 1;
    if (ber_scanf(ber, "i", &us->us_expire) == LBER_ERROR) {
      LDAP_SET_LDERRNO(ld, LDAP_DECODING_ERROR, NULL, NULL);
      ber_free(ber, 1);
      return (LDAP_DECODING_ERROR);
    }
  } else {
    us->us_available = 0;
    tag = 0;
    if ((ber_scanf(ber, "{t", &tag)) == LBER_ERROR) {
      LDAP_SET_LDERRNO(ld, LDAP_DECODING_ERROR, NULL, NULL);
      ber_free(ber, 1);
      return (LDAP_DECODING_ERROR);
    }
    while (tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET) {
      tag = tag & (~LBER_CLASS_CONTEXT);
      switch (tag) {
        case 0:
          if (ber_scanf(ber, "b", &us->us_inactive) == LBER_ERROR) {
            LDAP_SET_LDERRNO(ld, LDAP_DECODING_ERROR, NULL, NULL);
            ber_free(ber, 1);
            return (LDAP_DECODING_ERROR);
          }
          us->us_inactive = (us->us_inactive != 0) ? 1 : 0;
          break;
        case 1:
          if (ber_scanf(ber, "b", &us->us_reset) == LBER_ERROR) {
            LDAP_SET_LDERRNO(ld, LDAP_DECODING_ERROR, NULL, NULL);
            ber_free(ber, 1);
            return (LDAP_DECODING_ERROR);
          }
          us->us_reset = (us->us_reset != 0) ? 1 : 0;
          break;
        case 2:
          if (ber_scanf(ber, "b", &us->us_expired) == LBER_ERROR) {
            LDAP_SET_LDERRNO(ld, LDAP_DECODING_ERROR, NULL, NULL);
            ber_free(ber, 1);
            return (LDAP_DECODING_ERROR);
          }
          us->us_expired = (us->us_expired != 0) ? 1 : 0;
          break;
        case 3:
          if (ber_scanf(ber, "i", &us->us_remaining) == LBER_ERROR) {
            LDAP_SET_LDERRNO(ld, LDAP_DECODING_ERROR, NULL, NULL);
            ber_free(ber, 1);
            return (LDAP_DECODING_ERROR);
          }
          break;
        case 4:
          if (ber_scanf(ber, "i", &us->us_seconds) == LBER_ERROR) {
            LDAP_SET_LDERRNO(ld, LDAP_DECODING_ERROR, NULL, NULL);
            ber_free(ber, 1);
            return (LDAP_DECODING_ERROR);
          }
          break;
        default:
          LDAP_SET_LDERRNO(ld, LDAP_DECODING_ERROR, NULL, NULL);
          ber_free(ber, 1);
          return (LDAP_DECODING_ERROR);
      }
      ber_scanf(ber, "t", &tag);
    }
  }

  /* the ber encoding is no longer needed */
  ber_free(ber, 1);
  return (LDAP_SUCCESS);
}
Esempio n. 30
0
int
main( int argc, char *argv[] )
{
	int rc;
	char	*user = NULL;

	LDAP	       *ld = NULL;
	struct berval bv = {0, NULL};
	BerElement  *ber = NULL;

	int id, code = LDAP_OTHER;
	LDAPMessage *res;
	char *matcheddn = NULL, *text = NULL, **refs = NULL;
	char	*retoid = NULL;
	struct berval *retdata = NULL;

	prog = lutil_progname( "ldappasswd", argc, argv );

	/* LDAPv3 only */
	protocol = LDAP_VERSION3;

	tool_args( argc, argv );

	if( argc - optind > 1 ) {
		usage();
	} else if ( argc - optind == 1 ) {
		user = strdup( argv[optind] );
	} else {
		user = NULL;
	}

	if( oldpwfile ) {
		rc = lutil_get_filed_password( prog, &oldpw );
		if( rc ) return EXIT_FAILURE;
	}

	if( want_oldpw && oldpw.bv_val == NULL ) {
		/* prompt for old password */
		char *ckoldpw;
		oldpw.bv_val = strdup(getpassphrase("Old password: "******"Re-enter old password: "******"passwords do not match\n" );
			return EXIT_FAILURE;
		}

		oldpw.bv_len = strlen( oldpw.bv_val );
	}

	if( newpwfile ) {
		rc = lutil_get_filed_password( prog, &newpw );
		if( rc ) return EXIT_FAILURE;
	}

	if( want_newpw && newpw.bv_val == NULL ) {
		/* prompt for new password */
		char *cknewpw;
		newpw.bv_val = strdup(getpassphrase("New password: "******"Re-enter new password: "******"passwords do not match\n" );
			return EXIT_FAILURE;
		}

		newpw.bv_len = strlen( newpw.bv_val );
	}

	if( want_bindpw && passwd.bv_val == NULL ) {
		/* handle bind password */
		if ( pw_file ) {
			rc = lutil_get_filed_password( pw_file, &passwd );
			if( rc ) return EXIT_FAILURE;
		} else {
			passwd.bv_val = getpassphrase( "Enter LDAP Password: "******"ber_alloc_t" );
			ldap_unbind( ld );
			return EXIT_FAILURE;
		}

		ber_printf( ber, "{" /*}*/ );

		if( user != NULL ) {
			ber_printf( ber, "ts",
				LDAP_TAG_EXOP_MODIFY_PASSWD_ID, user );
			free(user);
		}

		if( oldpw.bv_val != NULL ) {
			ber_printf( ber, "tO",
				LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &oldpw );
			free(oldpw.bv_val);
		}

		if( newpw.bv_val != NULL ) {
			ber_printf( ber, "tO",
				LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &newpw );
			free(newpw.bv_val);
		}

		ber_printf( ber, /*{*/ "N}" );

		rc = ber_flatten2( ber, &bv, 0 );

		if( rc < 0 ) {
			perror( "ber_flatten2" );
			ldap_unbind( ld );
			return EXIT_FAILURE;
		}
	}

	if ( not ) {
		rc = LDAP_SUCCESS;
		goto skip;
	}

	rc = ldap_extended_operation( ld,
		LDAP_EXOP_MODIFY_PASSWD, bv.bv_val ? &bv : NULL, 
		NULL, NULL, &id );

	ber_free( ber, 1 );

	if( rc != LDAP_SUCCESS ) {
		ldap_perror( ld, "ldap_extended_operation" );
		ldap_unbind( ld );
		return EXIT_FAILURE;
	}

	rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
	if ( rc < 0 ) {
		ldap_perror( ld, "ldappasswd: ldap_result" );
		return rc;
	}

	rc = ldap_parse_result( ld, res,
		&code, &matcheddn, &text, &refs, NULL, 0 );

	if( rc != LDAP_SUCCESS ) {
		ldap_perror( ld, "ldap_parse_result" );
		return rc;
	}

	rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 );

	if( rc != LDAP_SUCCESS ) {
		ldap_perror( ld, "ldap_parse_result" );
		return rc;
	}

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

		if( ber == NULL ) {
			perror( "ber_init" );
			ldap_unbind( ld );
			return EXIT_FAILURE;
		}

		/* we should check the tag */
		tag = ber_scanf( ber, "{a}", &s);

		if( tag == LBER_ERROR ) {
			perror( "ber_scanf" );
		} else {
			printf("New password: %s\n", s);
			free( s );
		}

		ber_free( ber, 1 );
	}

	if( verbose || code != LDAP_SUCCESS || matcheddn || text || refs ) {
		printf( "Result: %s (%d)\n", ldap_err2string( code ), code );

		if( text && *text ) {
			printf( "Additional info: %s\n", text );
		}

		if( matcheddn && *matcheddn ) {
			printf( "Matched DN: %s\n", matcheddn );
		}

		if( refs ) {
			int i;
			for( i=0; refs[i]; i++ ) {
				printf("Referral: %s\n", refs[i] );
			}
		}
	}

	ber_memfree( text );
	ber_memfree( matcheddn );
	ber_memvfree( (void **) refs );
	ber_memfree( retoid );
	ber_bvfree( retdata );

skip:
	/* disconnect from server */
	ldap_unbind (ld);

	return code == LDAP_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE;
}