/* add.c */1/* $OpenLDAP$ */2/* This work is part of OpenLDAP Software <http://www.openldap.org/>.3*4* Copyright 1998-2024 The OpenLDAP Foundation.5* All rights reserved.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted only as authorized by the OpenLDAP9* Public License.10*11* A copy of this license is available in the file LICENSE in the12* top-level directory of the distribution or, alternatively, at13* <http://www.OpenLDAP.org/license.html>.14*/15/* Portions Copyright (c) 1990 Regents of the University of Michigan.16* All rights reserved.17*/1819#include "portable.h"2021#include <stdio.h>2223#include <ac/socket.h>24#include <ac/string.h>25#include <ac/time.h>2627#include "ldap-int.h"2829/* An LDAP Add Request/Response looks like this:30* AddRequest ::= [APPLICATION 8] SEQUENCE {31* entry LDAPDN,32* attributes AttributeList }33*34* AttributeList ::= SEQUENCE OF attribute Attribute35*36* Attribute ::= PartialAttribute(WITH COMPONENTS {37* ...,38* vals (SIZE(1..MAX))})39*40* PartialAttribute ::= SEQUENCE {41* type AttributeDescription,42* vals SET OF value AttributeValue }43*44* AttributeDescription ::= LDAPString45* -- Constrained to <attributedescription> [RFC4512]46*47* AttributeValue ::= OCTET STRING48*49* AddResponse ::= [APPLICATION 9] LDAPResult50* (Source: RFC 4511)51*/5253/*54* ldap_add - initiate an ldap add operation. Parameters:55*56* ld LDAP descriptor57* dn DN of the entry to add58* mods List of attributes for the entry. This is a null-59* terminated array of pointers to LDAPMod structures.60* only the type and values in the structures need be61* filled in.62*63* Example:64* LDAPMod *attrs[] = {65* { 0, "cn", { "babs jensen", "babs", 0 } },66* { 0, "sn", { "jensen", 0 } },67* { 0, "objectClass", { "person", 0 } },68* 069* }70* msgid = ldap_add( ld, dn, attrs );71*/72int73ldap_add( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs )74{75int rc;76int msgid;7778rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid );7980if ( rc != LDAP_SUCCESS )81return -1;8283return msgid;84}858687BerElement *88ldap_build_add_req(89LDAP *ld,90const char *dn,91LDAPMod **attrs,92LDAPControl **sctrls,93LDAPControl **cctrls,94ber_int_t *msgidp )95{96BerElement *ber;97int i, rc;9899/* create a message to send */100if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {101return( NULL );102}103104LDAP_NEXT_MSGID(ld, *msgidp);105rc = ber_printf( ber, "{it{s{", /* '}}}' */106*msgidp, LDAP_REQ_ADD, dn );107108if ( rc == -1 ) {109ld->ld_errno = LDAP_ENCODING_ERROR;110ber_free( ber, 1 );111return( NULL );112}113114/* allow attrs to be NULL ("touch"; should fail...) */115if ( attrs ) {116/* for each attribute in the entry... */117for ( i = 0; attrs[i] != NULL; i++ ) {118if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {119int j;120121if ( attrs[i]->mod_bvalues == NULL ) {122ld->ld_errno = LDAP_PARAM_ERROR;123ber_free( ber, 1 );124return( NULL );125}126127for ( j = 0; attrs[i]->mod_bvalues[ j ] != NULL; j++ ) {128if ( attrs[i]->mod_bvalues[ j ]->bv_val == NULL ) {129ld->ld_errno = LDAP_PARAM_ERROR;130ber_free( ber, 1 );131return( NULL );132}133}134135rc = ber_printf( ber, "{s[V]N}", attrs[i]->mod_type,136attrs[i]->mod_bvalues );137138} else {139if ( attrs[i]->mod_values == NULL ) {140ld->ld_errno = LDAP_PARAM_ERROR;141ber_free( ber, 1 );142return( NULL );143}144145rc = ber_printf( ber, "{s[v]N}", attrs[i]->mod_type,146attrs[i]->mod_values );147}148if ( rc == -1 ) {149ld->ld_errno = LDAP_ENCODING_ERROR;150ber_free( ber, 1 );151return( NULL );152}153}154}155156if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {157ld->ld_errno = LDAP_ENCODING_ERROR;158ber_free( ber, 1 );159return( NULL );160}161162/* Put Server Controls */163if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {164ber_free( ber, 1 );165return( NULL );166}167168if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {169ld->ld_errno = LDAP_ENCODING_ERROR;170ber_free( ber, 1 );171return( NULL );172}173174return( ber );175}176177/*178* ldap_add_ext - initiate an ldap extended add operation. Parameters:179*180* ld LDAP descriptor181* dn DN of the entry to add182* mods List of attributes for the entry. This is a null-183* terminated array of pointers to LDAPMod structures.184* only the type and values in the structures need be185* filled in.186* sctrl Server Controls187* cctrl Client Controls188* msgidp Message ID pointer189*190* Example:191* LDAPMod *attrs[] = {192* { 0, "cn", { "babs jensen", "babs", 0 } },193* { 0, "sn", { "jensen", 0 } },194* { 0, "objectClass", { "person", 0 } },195* 0196* }197* rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid );198*/199int200ldap_add_ext(201LDAP *ld,202LDAP_CONST char *dn,203LDAPMod **attrs,204LDAPControl **sctrls,205LDAPControl **cctrls,206int *msgidp )207{208BerElement *ber;209int rc;210ber_int_t id;211212Debug0( LDAP_DEBUG_TRACE, "ldap_add_ext\n" );213assert( ld != NULL );214assert( LDAP_VALID( ld ) );215assert( dn != NULL );216assert( msgidp != NULL );217218/* check client controls */219rc = ldap_int_client_controls( ld, cctrls );220if( rc != LDAP_SUCCESS ) return rc;221222ber = ldap_build_add_req( ld, dn, attrs, sctrls, cctrls, &id );223if( !ber )224return ld->ld_errno;225226/* send the message */227*msgidp = ldap_send_initial_request( ld, LDAP_REQ_ADD, dn, ber, id );228229if(*msgidp < 0)230return ld->ld_errno;231232return LDAP_SUCCESS;233}234235int236ldap_add_ext_s(237LDAP *ld,238LDAP_CONST char *dn,239LDAPMod **attrs,240LDAPControl **sctrls,241LDAPControl **cctrls )242{243int msgid, rc;244LDAPMessage *res;245246rc = ldap_add_ext( ld, dn, attrs, sctrls, cctrls, &msgid );247248if ( rc != LDAP_SUCCESS )249return( rc );250251if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res )252return( ld->ld_errno );253254return( ldap_result2error( ld, res, 1 ) );255}256257int258ldap_add_s( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs )259{260return ldap_add_ext_s( ld, dn, attrs, NULL, NULL );261}262263264