Home | History | Annotate | Line # | Download | only in libldap
      1 /*	$NetBSD: add.c,v 1.4 2025/09/05 21:16:20 christos Exp $	*/
      2 
      3 /* add.c */
      4 /* $OpenLDAP$ */
      5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  *
      7  * Copyright 1998-2024 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.4 2025/09/05 21:16:20 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
     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 *
     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
    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
    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
    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