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 */ 78int 79ldap_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 93BerElement * 94ldap_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 */ 205int 206ldap_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 241int 242ldap_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 263int 264ldap_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