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