1 /*        $NetBSD: add.c,v 1.3 2021/08/14 16:14:59 christos Exp $     */
2 
3 /* add.c - ldap backend add function */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1999-2021 The OpenLDAP Foundation.
8  * Portions Copyright 2000-2003 Pierangelo Masarati.
9  * Portions Copyright 1999-2003 Howard Chu.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted only as authorized by the OpenLDAP
14  * Public License.
15  *
16  * A copy of this license is available in the file LICENSE in the
17  * top-level directory of the distribution or, alternatively, at
18  * <http://www.OpenLDAP.org/license.html>.
19  */
20 /* ACKNOWLEDGEMENTS:
21  * This work was initially developed by the Howard Chu for inclusion
22  * in OpenLDAP Software and subsequently enhanced by Pierangelo
23  * Masarati.
24  */
25 
26 #include <sys/cdefs.h>
27 __RCSID("$NetBSD: add.c,v 1.3 2021/08/14 16:14:59 christos Exp $");
28 
29 #include "portable.h"
30 
31 #include <stdio.h>
32 
33 #include <ac/string.h>
34 #include <ac/socket.h>
35 
36 #include "slap.h"
37 #include "back-ldap.h"
38 
39 int
ldap_back_add(Operation * op,SlapReply * rs)40 ldap_back_add(
41           Operation *op,
42           SlapReply *rs )
43 {
44           ldapinfo_t                    *li = (ldapinfo_t *)op->o_bd->be_private;
45 
46           ldapconn_t                    *lc = NULL;
47           int                           i = 0,
48                                         j = 0;
49           Attribute           *a;
50           LDAPMod                       **attrs = NULL,
51                                         *attrs2 = NULL;
52           ber_int_t           msgid;
53           int                           isupdate;
54           ldap_back_send_t    retrying = LDAP_BACK_RETRYING;
55           LDAPControl                   **ctrls = NULL;
56 
57           rs->sr_err = LDAP_SUCCESS;
58 
59           Debug( LDAP_DEBUG_ARGS, "==> ldap_back_add(\"%s\")\n",
60                               op->o_req_dn.bv_val );
61 
62           if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
63                     lc = NULL;
64                     goto cleanup;
65           }
66 
67           /* Count number of attributes in entry */
68           for ( i = 1, a = op->oq_add.rs_e->e_attrs; a; i++, a = a->a_next )
69                     /* just count attrs */ ;
70 
71           /* Create array of LDAPMods for ldap_add() */
72           attrs = (LDAPMod **)ch_malloc( sizeof( LDAPMod * )*i
73                               + sizeof( LDAPMod )*( i - 1 ) );
74           attrs2 = ( LDAPMod * )&attrs[ i ];
75 
76           isupdate = be_shadow_update( op );
77           for ( i = 0, a = op->oq_add.rs_e->e_attrs; a; a = a->a_next ) {
78                     if ( !isupdate && !get_relax( op ) && a->a_desc->ad_type->sat_no_user_mod  )
79                     {
80                               continue;
81                     }
82 
83                     attrs[ i ] = &attrs2[ i ];
84                     attrs[ i ]->mod_op = LDAP_MOD_BVALUES;
85                     attrs[ i ]->mod_type = a->a_desc->ad_cname.bv_val;
86 
87                     for ( j = 0; a->a_vals[ j ].bv_val; j++ )
88                               /* just count vals */ ;
89                     attrs[i]->mod_vals.modv_bvals =
90                               ch_malloc( ( j + 1 )*sizeof( struct berval * ) );
91                     for ( j = 0; a->a_vals[ j ].bv_val; j++ ) {
92                               attrs[ i ]->mod_vals.modv_bvals[ j ] = &a->a_vals[ j ];
93                     }
94                     attrs[ i ]->mod_vals.modv_bvals[ j ] = NULL;
95                     i++;
96           }
97           attrs[ i ] = NULL;
98 
99 retry:
100           ctrls = op->o_ctrls;
101           rs->sr_err = ldap_back_controls_add( op, rs, lc, &ctrls );
102           if ( rs->sr_err != LDAP_SUCCESS ) {
103                     send_ldap_result( op, rs );
104                     goto cleanup;
105           }
106 
107           rs->sr_err = ldap_add_ext( lc->lc_ld, op->o_req_dn.bv_val, attrs,
108                               ctrls, NULL, &msgid );
109           rs->sr_err = ldap_back_op_result( lc, op, rs, msgid,
110                     li->li_timeout[ SLAP_OP_ADD ],
111                     ( LDAP_BACK_SENDRESULT | retrying ) );
112           if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
113                     retrying &= ~LDAP_BACK_RETRYING;
114                     if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
115                               /* if the identity changed, there might be need to re-authz */
116                               (void)ldap_back_controls_free( op, rs, &ctrls );
117                               goto retry;
118                     }
119           }
120 
121           ldap_pvt_thread_mutex_lock( &li->li_counter_mutex );
122           ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_ADD ], 1 );
123           ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex );
124 
125 cleanup:
126           (void)ldap_back_controls_free( op, rs, &ctrls );
127 
128           if ( attrs ) {
129                     for ( --i; i >= 0; --i ) {
130                               ch_free( attrs[ i ]->mod_vals.modv_bvals );
131                     }
132                     ch_free( attrs );
133           }
134 
135           if ( lc ) {
136                     ldap_back_release_conn( li, lc );
137           }
138 
139           Debug( LDAP_DEBUG_ARGS, "<== ldap_back_add(\"%s\"): %d\n",
140                               op->o_req_dn.bv_val, rs->sr_err );
141 
142           return rs->sr_err;
143 }
144 
145