1/* $OpenLDAP$ */
2/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 *
4 * Copyright 1998-2011 The OpenLDAP Foundation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
9 * Public License.
10 *
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
14 */
15/* Portions Copyright (c) 1990 Regents of the University of Michigan.
16 * All rights reserved.
17 */
18
19#include "portable.h"
20
21#include <stdio.h>
22#include <ac/stdlib.h>
23
24#include <ac/socket.h>
25#include <ac/string.h>
26#include <ac/time.h>
27
28#include "ldap-int.h"
29
30char *
31ldap_first_attribute( LDAP *ld, LDAPMessage *entry, BerElement **berout )
32{
33	int rc;
34	ber_tag_t tag;
35	ber_len_t len = 0;
36	char *attr;
37	BerElement *ber;
38
39	Debug( LDAP_DEBUG_TRACE, "ldap_first_attribute\n", 0, 0, 0 );
40
41	assert( ld != NULL );
42	assert( LDAP_VALID( ld ) );
43	assert( entry != NULL );
44	assert( berout != NULL );
45
46	*berout = NULL;
47
48	ber = ldap_alloc_ber_with_options( ld );
49	if( ber == NULL ) {
50		return NULL;
51	}
52
53	*ber = *entry->lm_ber;
54
55	/*
56	 * Skip past the sequence, dn, sequence of sequence leaving
57	 * us at the first attribute.
58	 */
59
60	tag = ber_scanf( ber, "{xl{" /*}}*/, &len );
61	if( tag == LBER_ERROR ) {
62		ld->ld_errno = LDAP_DECODING_ERROR;
63		ber_free( ber, 0 );
64		return NULL;
65	}
66
67	/* set the length to avoid overrun */
68	rc = ber_set_option( ber, LBER_OPT_REMAINING_BYTES, &len );
69	if( rc != LBER_OPT_SUCCESS ) {
70		ld->ld_errno = LDAP_LOCAL_ERROR;
71		ber_free( ber, 0 );
72		return NULL;
73	}
74
75	if ( ber_pvt_ber_remaining( ber ) == 0 ) {
76		assert( len == 0 );
77		ber_free( ber, 0 );
78		return NULL;
79	}
80	assert( len != 0 );
81
82	/* snatch the first attribute */
83	tag = ber_scanf( ber, "{ax}", &attr );
84	if( tag == LBER_ERROR ) {
85		ld->ld_errno = LDAP_DECODING_ERROR;
86		ber_free( ber, 0 );
87		return NULL;
88	}
89
90	*berout = ber;
91	return attr;
92}
93
94/* ARGSUSED */
95char *
96ldap_next_attribute( LDAP *ld, LDAPMessage *entry, BerElement *ber )
97{
98	ber_tag_t tag;
99	char *attr;
100
101	Debug( LDAP_DEBUG_TRACE, "ldap_next_attribute\n", 0, 0, 0 );
102
103	assert( ld != NULL );
104	assert( LDAP_VALID( ld ) );
105	assert( entry != NULL );
106	assert( ber != NULL );
107
108	if ( ber_pvt_ber_remaining( ber ) == 0 ) {
109		return NULL;
110	}
111
112	/* skip sequence, snarf attribute type, skip values */
113	tag = ber_scanf( ber, "{ax}", &attr );
114	if( tag == LBER_ERROR ) {
115		ld->ld_errno = LDAP_DECODING_ERROR;
116		return NULL;
117	}
118
119	return attr;
120}
121
122/* Fetch attribute type and optionally fetch values. The type
123 * and values are referenced in-place from the BerElement, they are
124 * not dup'd into malloc'd memory.
125 */
126/* ARGSUSED */
127int
128ldap_get_attribute_ber( LDAP *ld, LDAPMessage *entry, BerElement *ber,
129	BerValue *attr, BerVarray *vals )
130{
131	ber_tag_t tag;
132	int rc = LDAP_SUCCESS;
133
134	Debug( LDAP_DEBUG_TRACE, "ldap_get_attribute_ber\n", 0, 0, 0 );
135
136	assert( ld != NULL );
137	assert( LDAP_VALID( ld ) );
138	assert( entry != NULL );
139	assert( ber != NULL );
140	assert( attr != NULL );
141
142	attr->bv_val = NULL;
143	attr->bv_len = 0;
144
145	if ( ber_pvt_ber_remaining( ber ) ) {
146		ber_len_t siz = sizeof( BerValue );
147
148		/* skip sequence, snarf attribute type */
149		tag = ber_scanf( ber, vals ? "{mM}" : "{mx}", attr, vals,
150			&siz, 0 );
151		if( tag == LBER_ERROR ) {
152			rc = ld->ld_errno = LDAP_DECODING_ERROR;
153		}
154	}
155
156	return rc;
157}
158