xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/add.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: add.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* add.c */
4 /* OpenLDAP: pkg/ldap/libraries/libldap/add.c,v 1.27.2.5 2009/01/22 00:00:54 kurt Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2009 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* Portions Copyright (c) 1990 Regents of the University of Michigan.
19  * All rights reserved.
20  */
21 
22 #include "portable.h"
23 
24 #include <stdio.h>
25 
26 #include <ac/socket.h>
27 #include <ac/string.h>
28 #include <ac/time.h>
29 
30 #include "ldap-int.h"
31 
32 /* An LDAP Add Request/Response looks like this:
33  *        AddRequest ::= [APPLICATION 8] SEQUENCE {
34  *            entry           LDAPDN,
35  *            attributes      AttributeList }
36  *
37  *        AttributeList ::= SEQUENCE OF attribute Attribute
38  *
39  *        Attribute ::= PartialAttribute(WITH COMPONENTS {
40  *             ...,
41  *             vals (SIZE(1..MAX))})
42  *
43  *        PartialAttribute ::= SEQUENCE {
44  *             type       AttributeDescription,
45  *             vals       SET OF value AttributeValue }
46  *
47  *        AttributeDescription ::= LDAPString
48  *             -- Constrained to <attributedescription> [RFC4512]
49  *
50  *        AttributeValue ::= OCTET STRING
51  *
52  *        AddResponse ::= [APPLICATION 9] LDAPResult
53  * (Source: RFC 4511)
54  */
55 
56 /*
57  * ldap_add - initiate an ldap add operation.  Parameters:
58  *
59  *	ld		LDAP descriptor
60  *	dn		DN of the entry to add
61  *	mods		List of attributes for the entry.  This is a null-
62  *			terminated array of pointers to LDAPMod structures.
63  *			only the type and values in the structures need be
64  *			filled in.
65  *
66  * Example:
67  *	LDAPMod	*attrs[] = {
68  *			{ 0, "cn", { "babs jensen", "babs", 0 } },
69  *			{ 0, "sn", { "jensen", 0 } },
70  *			{ 0, "objectClass", { "person", 0 } },
71  *			0
72  *		}
73  *	msgid = ldap_add( ld, dn, attrs );
74  */
75 int
76 ldap_add( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs )
77 {
78 	int rc;
79 	int msgid;
80 
81 	rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid );
82 
83 	if ( rc != LDAP_SUCCESS )
84 		return -1;
85 
86 	return msgid;
87 }
88 
89 
90 /*
91  * ldap_add_ext - initiate an ldap extended add operation.  Parameters:
92  *
93  *	ld		LDAP descriptor
94  *	dn		DN of the entry to add
95  *	mods		List of attributes for the entry.  This is a null-
96  *			terminated array of pointers to LDAPMod structures.
97  *			only the type and values in the structures need be
98  *			filled in.
99  *	sctrl	Server Controls
100  *	cctrl	Client Controls
101  *	msgidp	Message ID pointer
102  *
103  * Example:
104  *	LDAPMod	*attrs[] = {
105  *			{ 0, "cn", { "babs jensen", "babs", 0 } },
106  *			{ 0, "sn", { "jensen", 0 } },
107  *			{ 0, "objectClass", { "person", 0 } },
108  *			0
109  *		}
110  *	rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid );
111  */
112 int
113 ldap_add_ext(
114 	LDAP *ld,
115 	LDAP_CONST char *dn,
116 	LDAPMod **attrs,
117 	LDAPControl **sctrls,
118 	LDAPControl **cctrls,
119 	int	*msgidp )
120 {
121 	BerElement	*ber;
122 	int		i, rc;
123 	ber_int_t	id;
124 
125 	Debug( LDAP_DEBUG_TRACE, "ldap_add_ext\n", 0, 0, 0 );
126 	assert( ld != NULL );
127 	assert( LDAP_VALID( ld ) );
128 	assert( dn != NULL );
129 	assert( msgidp != NULL );
130 
131 	/* check client controls */
132 	rc = ldap_int_client_controls( ld, cctrls );
133 	if( rc != LDAP_SUCCESS ) return rc;
134 
135 	/* create a message to send */
136 	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
137 		ld->ld_errno = LDAP_NO_MEMORY;
138 		return ld->ld_errno;
139 	}
140 
141 	LDAP_NEXT_MSGID(ld, id);
142 	rc = ber_printf( ber, "{it{s{", /* '}}}' */
143 		id, LDAP_REQ_ADD, dn );
144 
145 	if ( rc == -1 ) {
146 		ld->ld_errno = LDAP_ENCODING_ERROR;
147 		ber_free( ber, 1 );
148 		return ld->ld_errno;
149 	}
150 
151 	/* allow attrs to be NULL ("touch"; should fail...) */
152 	if ( attrs ) {
153 		/* for each attribute in the entry... */
154 		for ( i = 0; attrs[i] != NULL; i++ ) {
155 			if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
156 				int j;
157 
158 				if ( attrs[i]->mod_bvalues == NULL ) {
159 					ld->ld_errno = LDAP_PARAM_ERROR;
160 					ber_free( ber, 1 );
161 					return ld->ld_errno;
162 				}
163 
164 				for ( j = 0; attrs[i]->mod_bvalues[ j ] != NULL; j++ ) {
165 					if ( attrs[i]->mod_bvalues[ j ]->bv_val == NULL ) {
166 						ld->ld_errno = LDAP_PARAM_ERROR;
167 						ber_free( ber, 1 );
168 						return ld->ld_errno;
169 					}
170 				}
171 
172 				rc = ber_printf( ber, "{s[V]N}", attrs[i]->mod_type,
173 				    attrs[i]->mod_bvalues );
174 
175 			} else {
176 				if ( attrs[i]->mod_values == NULL ) {
177 					ld->ld_errno = LDAP_PARAM_ERROR;
178 					ber_free( ber, 1 );
179 					return ld->ld_errno;
180 				}
181 
182 				rc = ber_printf( ber, "{s[v]N}", attrs[i]->mod_type,
183 				    attrs[i]->mod_values );
184 			}
185 			if ( rc == -1 ) {
186 				ld->ld_errno = LDAP_ENCODING_ERROR;
187 				ber_free( ber, 1 );
188 				return ld->ld_errno;
189 			}
190 		}
191 	}
192 
193 	if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {
194 		ld->ld_errno = LDAP_ENCODING_ERROR;
195 		ber_free( ber, 1 );
196 		return ld->ld_errno;
197 	}
198 
199 	/* Put Server Controls */
200 	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
201 		ber_free( ber, 1 );
202 		return ld->ld_errno;
203 	}
204 
205 	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
206 		ld->ld_errno = LDAP_ENCODING_ERROR;
207 		ber_free( ber, 1 );
208 		return ld->ld_errno;
209 	}
210 
211 	/* send the message */
212 	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_ADD, dn, ber, id );
213 
214 	if(*msgidp < 0)
215 		return ld->ld_errno;
216 
217 	return LDAP_SUCCESS;
218 }
219 
220 int
221 ldap_add_ext_s(
222 	LDAP *ld,
223 	LDAP_CONST char *dn,
224 	LDAPMod **attrs,
225 	LDAPControl **sctrls,
226 	LDAPControl **cctrls )
227 {
228 	int		msgid, rc;
229 	LDAPMessage	*res;
230 
231 	rc = ldap_add_ext( ld, dn, attrs, sctrls, cctrls, &msgid );
232 
233 	if ( rc != LDAP_SUCCESS )
234 		return( rc );
235 
236 	if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res )
237 		return( ld->ld_errno );
238 
239 	return( ldap_result2error( ld, res, 1 ) );
240 }
241 
242 int
243 ldap_add_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs )
244 {
245 	return ldap_add_ext_s( ld, dn, attrs, NULL, NULL );
246 }
247 
248