control.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* control.c - routines for dealing with LDAPMessage controls */
  42. #include <stdio.h>
  43. #include "slap.h"
  44. /*
  45. * static variables used to track information about supported controls.
  46. * supported_controls is a NULL-terminated array of OIDs.
  47. * supported_controls_ops is an array of bitmaps that hold SLAPI_OPERATION_*
  48. * flags that specify the operation(s) for which a control is supported.
  49. * The elements in the supported_controls_ops array align with the ones
  50. * in the supported_controls array.
  51. */
  52. static char **supported_controls = NULL;
  53. static unsigned long *supported_controls_ops = NULL;
  54. static int supported_controls_count = 0;
  55. static PRRWLock *supported_controls_lock = NULL;
  56. /*
  57. * Register all of the LDAPv3 controls we know about "out of the box."
  58. */
  59. void
  60. init_controls( void )
  61. {
  62. supported_controls_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE,
  63. "supported controls rwlock");
  64. if (NULL == supported_controls_lock) {
  65. /* Out of resources */
  66. slapi_log_error(SLAPI_LOG_FATAL, "startup",
  67. "init_controls: failed to create lock.\n");
  68. exit (1);
  69. }
  70. slapi_register_supported_control( LDAP_CONTROL_MANAGEDSAIT,
  71. SLAPI_OPERATION_SEARCH | SLAPI_OPERATION_COMPARE
  72. | SLAPI_OPERATION_ADD | SLAPI_OPERATION_DELETE
  73. | SLAPI_OPERATION_MODIFY | SLAPI_OPERATION_MODDN );
  74. slapi_register_supported_control( LDAP_CONTROL_PERSISTENTSEARCH,
  75. SLAPI_OPERATION_SEARCH );
  76. slapi_register_supported_control( LDAP_CONTROL_PWEXPIRED,
  77. SLAPI_OPERATION_NONE );
  78. slapi_register_supported_control( LDAP_CONTROL_PWEXPIRING,
  79. SLAPI_OPERATION_NONE );
  80. slapi_register_supported_control( LDAP_CONTROL_SORTREQUEST,
  81. SLAPI_OPERATION_SEARCH );
  82. slapi_register_supported_control( LDAP_CONTROL_VLVREQUEST,
  83. SLAPI_OPERATION_SEARCH );
  84. slapi_register_supported_control( LDAP_CONTROL_AUTH_REQUEST,
  85. SLAPI_OPERATION_BIND );
  86. slapi_register_supported_control( LDAP_CONTROL_AUTH_RESPONSE,
  87. SLAPI_OPERATION_NONE );
  88. slapi_register_supported_control( LDAP_CONTROL_REAL_ATTRS_ONLY,
  89. SLAPI_OPERATION_SEARCH );
  90. slapi_register_supported_control( LDAP_CONTROL_VIRT_ATTRS_ONLY,
  91. SLAPI_OPERATION_SEARCH );
  92. slapi_register_supported_control( LDAP_X_CONTROL_PWPOLICY_REQUEST,
  93. SLAPI_OPERATION_SEARCH | SLAPI_OPERATION_COMPARE
  94. | SLAPI_OPERATION_ADD | SLAPI_OPERATION_DELETE
  95. | SLAPI_OPERATION_MODIFY | SLAPI_OPERATION_MODDN );
  96. /*
  97. We do not register the password policy response because it has
  98. the same oid as the request (and it was being reported twice in
  99. in the root DSE supportedControls attribute)
  100. slapi_register_supported_control( LDAP_X_CONTROL_PWPOLICY_RESPONSE,
  101. SLAPI_OPERATION_SEARCH | SLAPI_OPERATION_COMPARE
  102. | SLAPI_OPERATION_ADD | SLAPI_OPERATION_DELETE
  103. | SLAPI_OPERATION_MODIFY | SLAPI_OPERATION_MODDN );
  104. */
  105. slapi_register_supported_control( LDAP_CONTROL_GET_EFFECTIVE_RIGHTS,
  106. SLAPI_OPERATION_SEARCH );
  107. /* LDAP_CONTROL_PAGEDRESULTS is shared by request and response */
  108. slapi_register_supported_control( LDAP_CONTROL_PAGEDRESULTS,
  109. SLAPI_OPERATION_SEARCH );
  110. }
  111. /*
  112. * register a supported control so it can be returned as part of the root DSE.
  113. */
  114. void
  115. slapi_register_supported_control( char *controloid, unsigned long controlops )
  116. {
  117. if ( controloid != NULL ) {
  118. PR_RWLock_Wlock(supported_controls_lock);
  119. ++supported_controls_count;
  120. charray_add( &supported_controls, slapi_ch_strdup( controloid ));
  121. supported_controls_ops = (unsigned long *)slapi_ch_realloc(
  122. (char *)supported_controls_ops,
  123. supported_controls_count * sizeof( unsigned long ));
  124. supported_controls_ops[ supported_controls_count - 1 ] =
  125. controlops;
  126. PR_RWLock_Unlock(supported_controls_lock);
  127. }
  128. }
  129. /*
  130. * retrieve supported controls OID and/or operations arrays.
  131. * return 0 if successful and -1 if not.
  132. * This function is not MTSafe and should be deprecated.
  133. * slapi_get_supported_controls_copy should be used instead.
  134. */
  135. int
  136. slapi_get_supported_controls( char ***ctrloidsp, unsigned long **ctrlopsp )
  137. {
  138. if ( ctrloidsp != NULL ) {
  139. *ctrloidsp = supported_controls;
  140. }
  141. if ( ctrlopsp != NULL ) {
  142. *ctrlopsp = supported_controls_ops;
  143. }
  144. return( 0 );
  145. }
  146. static
  147. unsigned long *supported_controls_ops_dup(unsigned long *ctrlops)
  148. {
  149. int i;
  150. unsigned long *dup_ops = (unsigned long *)slapi_ch_calloc(
  151. supported_controls_count + 1, sizeof( unsigned long ));
  152. if (NULL != dup_ops) {
  153. for (i=0; i < supported_controls_count; i++)
  154. dup_ops[i] = supported_controls_ops[i];
  155. }
  156. return dup_ops;
  157. }
  158. int slapi_get_supported_controls_copy( char ***ctrloidsp, unsigned long **ctrlopsp )
  159. {
  160. PR_RWLock_Rlock(supported_controls_lock);
  161. if ( ctrloidsp != NULL ) {
  162. *ctrloidsp = charray_dup(supported_controls);
  163. }
  164. if ( ctrlopsp != NULL ) {
  165. *ctrlopsp = supported_controls_ops_dup(supported_controls_ops);
  166. }
  167. PR_RWLock_Unlock(supported_controls_lock);
  168. return (0);
  169. }
  170. /*
  171. * RFC 4511 section 4.1.11. Controls says that the UnbindRequest
  172. * MUST ignore the criticality field of controls
  173. */
  174. int
  175. get_ldapmessage_controls_ext(
  176. Slapi_PBlock *pb,
  177. BerElement *ber,
  178. LDAPControl ***controlsp, /* can be NULL if no need to return */
  179. int ignore_criticality /* some requests must ignore criticality */
  180. )
  181. {
  182. LDAPControl **ctrls, *new;
  183. ber_tag_t tag;
  184. ber_len_t len = -1;
  185. int rc, maxcontrols, curcontrols;
  186. char *last;
  187. int managedsait, pwpolicy_ctrl;
  188. /*
  189. * Each LDAPMessage can have a set of controls appended
  190. * to it. Controls are used to extend the functionality
  191. * of an LDAP operation (e.g., add an attribute size limit
  192. * to the search operation). These controls look like this:
  193. *
  194. * Controls ::= SEQUENCE OF Control
  195. *
  196. * Control ::= SEQUENCE {
  197. * controlType LDAPOID,
  198. * criticality BOOLEAN DEFAULT FALSE,
  199. * controlValue OCTET STRING
  200. * }
  201. */
  202. LDAPDebug( LDAP_DEBUG_TRACE, "=> get_ldapmessage_controls\n", 0, 0, 0 );
  203. ctrls = NULL;
  204. slapi_pblock_set( pb, SLAPI_REQCONTROLS, ctrls );
  205. if ( controlsp != NULL ) {
  206. *controlsp = NULL;
  207. }
  208. rc = LDAP_PROTOCOL_ERROR; /* most popular error we may return */
  209. /*
  210. * check to see if controls were included
  211. */
  212. if ( ber_get_option( ber, LBER_OPT_REMAINING_BYTES, &len ) != 0 ) {
  213. LDAPDebug( LDAP_DEBUG_TRACE,
  214. "<= get_ldapmessage_controls LDAP_OPERATIONS_ERROR\n",
  215. 0, 0, 0 );
  216. return( LDAP_OPERATIONS_ERROR ); /* unexpected error */
  217. }
  218. if ( len == 0 ) {
  219. LDAPDebug( LDAP_DEBUG_TRACE,
  220. "<= get_ldapmessage_controls no controls\n", 0, 0, 0 );
  221. return( LDAP_SUCCESS ); /* no controls */
  222. }
  223. if (( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
  224. if ( tag == LBER_ERROR ) {
  225. LDAPDebug( LDAP_DEBUG_TRACE,
  226. "<= get_ldapmessage_controls LDAP_PROTOCOL_ERROR\n",
  227. 0, 0, 0 );
  228. return( LDAP_PROTOCOL_ERROR ); /* decoding error */
  229. }
  230. /*
  231. * We found something other than controls. This should never
  232. * happen in LDAPv3, but we don't treat this is a hard error --
  233. * we just ignore the extra stuff.
  234. */
  235. LDAPDebug( LDAP_DEBUG_TRACE,
  236. "<= get_ldapmessage_controls ignoring unrecognized data in request (tag 0x%x)\n",
  237. tag, 0, 0 );
  238. return( LDAP_SUCCESS );
  239. }
  240. /*
  241. * A sequence of controls is present. If connection is not LDAPv3
  242. * or better, return a protocol error. Otherwise, parse the controls.
  243. */
  244. if ( pb != NULL && pb->pb_conn != NULL
  245. && pb->pb_conn->c_ldapversion < LDAP_VERSION3 ) {
  246. slapi_log_error( SLAPI_LOG_FATAL, "connection",
  247. "received control(s) on an LDAPv%d connection\n",
  248. pb->pb_conn->c_ldapversion );
  249. return( LDAP_PROTOCOL_ERROR );
  250. }
  251. maxcontrols = curcontrols = 0;
  252. for ( tag = ber_first_element( ber, &len, &last );
  253. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  254. tag = ber_next_element( ber, &len, last ) ) {
  255. len = -1; /* reset */
  256. if ( curcontrols >= maxcontrols - 1 ) {
  257. #define CONTROL_GRABSIZE 6
  258. maxcontrols += CONTROL_GRABSIZE;
  259. ctrls = (LDAPControl **) slapi_ch_realloc( (char *)ctrls,
  260. maxcontrols * sizeof(LDAPControl *) );
  261. }
  262. new = (LDAPControl *) slapi_ch_calloc( 1, sizeof(LDAPControl) );
  263. ctrls[curcontrols++] = new;
  264. ctrls[curcontrols] = NULL;
  265. if ( ber_scanf( ber, "{a", &new->ldctl_oid ) == LBER_ERROR ) {
  266. goto free_and_return;
  267. }
  268. /* the criticality is optional */
  269. if ( ber_peek_tag( ber, &len ) == LBER_BOOLEAN ) {
  270. if ( ber_scanf( ber, "b", &new->ldctl_iscritical )
  271. == LBER_ERROR ) {
  272. goto free_and_return;
  273. }
  274. } else {
  275. /* absent is synonomous with FALSE */
  276. new->ldctl_iscritical = 0;
  277. }
  278. len = -1; /* reset */
  279. /* if we are ignoring criticality, treat as FALSE */
  280. if (ignore_criticality) {
  281. new->ldctl_iscritical = 0;
  282. }
  283. /*
  284. * return an appropriate error if this control is marked
  285. * critical and either:
  286. * a) we do not support it at all OR
  287. * b) it is not supported for this operation
  288. */
  289. if ( new->ldctl_iscritical ) {
  290. int i;
  291. PR_RWLock_Rlock(supported_controls_lock);
  292. for ( i = 0; supported_controls != NULL
  293. && supported_controls[i] != NULL; ++i ) {
  294. if ( strcmp( supported_controls[i],
  295. new->ldctl_oid ) == 0 ) {
  296. break;
  297. }
  298. }
  299. if ( supported_controls == NULL ||
  300. supported_controls[i] == NULL ||
  301. ( 0 == ( supported_controls_ops[i] &
  302. operation_get_type(pb->pb_op) ))) {
  303. rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  304. PR_RWLock_Unlock(supported_controls_lock);
  305. goto free_and_return;
  306. }
  307. PR_RWLock_Unlock(supported_controls_lock);
  308. }
  309. /* the control value is optional */
  310. if ( ber_peek_tag( ber, &len ) == LBER_OCTETSTRING ) {
  311. if ( ber_scanf( ber, "o", &new->ldctl_value )
  312. == LBER_ERROR ) {
  313. goto free_and_return;
  314. }
  315. } else {
  316. (new->ldctl_value).bv_val = NULL;
  317. (new->ldctl_value).bv_len = 0;
  318. }
  319. len = -1; /* reset for next loop iter */
  320. }
  321. if ( (tag != LBER_END_OF_SEQORSET) && (len != -1) ) {
  322. goto free_and_return;
  323. }
  324. slapi_pblock_set( pb, SLAPI_REQCONTROLS, ctrls );
  325. managedsait = slapi_control_present( ctrls,
  326. LDAP_CONTROL_MANAGEDSAIT, NULL, NULL );
  327. slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, &managedsait );
  328. pwpolicy_ctrl = slapi_control_present( ctrls,
  329. LDAP_X_CONTROL_PWPOLICY_REQUEST, NULL, NULL );
  330. slapi_pblock_set( pb, SLAPI_PWPOLICY, &pwpolicy_ctrl );
  331. if ( controlsp != NULL ) {
  332. *controlsp = ctrls;
  333. }
  334. #ifdef SLAPD_ECHO_CONTROL
  335. /*
  336. * XXXmcs: Start of hack: if a control with OID "1.1" was sent by
  337. * the client, echo all controls back to the client unchanged. Note
  338. * that this is just a hack to test control handling in libldap and
  339. * should be removed once we support all interesting controls.
  340. */
  341. if ( slapi_control_present( ctrls, "1.1", NULL, NULL )) {
  342. int i;
  343. for ( i = 0; ctrls[i] != NULL; ++i ) {
  344. slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL,
  345. (void *)ctrls[i] );
  346. }
  347. }
  348. #endif /* SLAPD_ECHO_CONTROL */
  349. LDAPDebug( LDAP_DEBUG_TRACE,
  350. "<= get_ldapmessage_controls %d controls\n", curcontrols, 0, 0 );
  351. return( LDAP_SUCCESS );
  352. free_and_return:;
  353. ldap_controls_free( ctrls );
  354. LDAPDebug( LDAP_DEBUG_TRACE,
  355. "<= get_ldapmessage_controls %i\n", rc, 0, 0 );
  356. return( rc );
  357. }
  358. int
  359. get_ldapmessage_controls(
  360. Slapi_PBlock *pb,
  361. BerElement *ber,
  362. LDAPControl ***controlsp /* can be NULL if no need to return */
  363. )
  364. {
  365. return get_ldapmessage_controls_ext(pb, ber, controlsp, 0 /* do not ignore criticality */);
  366. }
  367. int
  368. slapi_control_present( LDAPControl **controls, char *oid, struct berval **val, int *iscritical )
  369. {
  370. int i;
  371. LDAPDebug( LDAP_DEBUG_TRACE,
  372. "=> slapi_control_present (looking for %s)\n", oid, 0, 0 );
  373. if ( val != NULL ) {
  374. *val = NULL;
  375. }
  376. if ( controls == NULL ) {
  377. LDAPDebug( LDAP_DEBUG_TRACE,
  378. "<= slapi_control_present 0 (NO CONTROLS)\n", 0, 0, 0 );
  379. return( 0 );
  380. }
  381. for ( i = 0; controls[i] != NULL; i++ ) {
  382. if ( strcmp( controls[i]->ldctl_oid, oid ) == 0 ) {
  383. if (NULL != val) {
  384. *val = &controls[i]->ldctl_value;
  385. if (NULL != iscritical) {
  386. *iscritical = (int) controls[i]->ldctl_iscritical;
  387. }
  388. }
  389. LDAPDebug( LDAP_DEBUG_TRACE,
  390. "<= slapi_control_present 1 (FOUND)\n", 0, 0, 0 );
  391. return( 1 );
  392. }
  393. }
  394. LDAPDebug( LDAP_DEBUG_TRACE,
  395. "<= slapi_control_present 0 (NOT FOUND)\n", 0, 0, 0 );
  396. return( 0 );
  397. }
  398. /*
  399. * Write sequence of controls in "ctrls" to "ber".
  400. * Return zero on success and -1 if an error occurs.
  401. */
  402. int
  403. write_controls( BerElement *ber, LDAPControl **ctrls )
  404. {
  405. int i;
  406. unsigned long rc;
  407. rc= ber_start_seq( ber, LDAP_TAG_CONTROLS );
  408. if ( rc == LBER_ERROR ) {
  409. return( -1 );
  410. }
  411. /* if the criticality is false, it should be absent from the encoding */
  412. for ( i = 0; ctrls[ i ] != NULL; ++i ) {
  413. if ( ctrls[ i ]->ldctl_value.bv_val == 0 ) {
  414. if ( ctrls[ i ]->ldctl_iscritical ) {
  415. rc = ber_printf( ber, "{sb}", ctrls[ i ]->ldctl_oid,
  416. ctrls[ i ]->ldctl_iscritical );
  417. } else {
  418. rc = ber_printf( ber, "{s}", ctrls[ i ]->ldctl_oid );
  419. }
  420. } else {
  421. if ( ctrls[ i ]->ldctl_iscritical ) {
  422. rc = ber_printf( ber, "{sbo}", ctrls[ i ]->ldctl_oid,
  423. ctrls[ i ]->ldctl_iscritical,
  424. ctrls[ i ]->ldctl_value.bv_val,
  425. ctrls[ i ]->ldctl_value.bv_len );
  426. } else {
  427. rc = ber_printf( ber, "{so}", ctrls[ i ]->ldctl_oid,
  428. ctrls[ i ]->ldctl_value.bv_val,
  429. ctrls[ i ]->ldctl_value.bv_len );
  430. }
  431. }
  432. if ( rc == LBER_ERROR ) {
  433. return( -1 );
  434. }
  435. }
  436. rc= ber_put_seq( ber );
  437. if ( rc == LBER_ERROR ) {
  438. return( -1 );
  439. }
  440. return( 0 );
  441. }
  442. /*
  443. * duplicate "newctrl" and add it to the array of controls "*ctrlsp"
  444. * note that *ctrlsp may be reset and that it is okay to pass NULL for it.
  445. * IF copy is true, a copy of the passed in control will be added - copy
  446. * made with slapi_dup_control - if copy is false, the control
  447. * will be used directly and may be free'd by ldap_controls_free - so
  448. * make sure it is ok for the control array to own the pointer you
  449. * pass in
  450. */
  451. void
  452. add_control_ext( LDAPControl ***ctrlsp, LDAPControl *newctrl, int copy )
  453. {
  454. int count;
  455. if ( *ctrlsp == NULL ) {
  456. count = 0;
  457. } else {
  458. for ( count = 0; (*ctrlsp)[count] != NULL; ++count ) {
  459. ;
  460. }
  461. }
  462. *ctrlsp = (LDAPControl **)slapi_ch_realloc( (char *)*ctrlsp,
  463. ( count + 2 ) * sizeof(LDAPControl *));
  464. if (copy) {
  465. (*ctrlsp)[ count ] = slapi_dup_control( newctrl );
  466. } else {
  467. (*ctrlsp)[ count ] = newctrl;
  468. }
  469. (*ctrlsp)[ ++count ] = NULL;
  470. }
  471. /*
  472. * duplicate "newctrl" and add it to the array of controls "*ctrlsp"
  473. * note that *ctrlsp may be reset and that it is okay to pass NULL for it.
  474. */
  475. void
  476. add_control( LDAPControl ***ctrlsp, LDAPControl *newctrl )
  477. {
  478. add_control_ext(ctrlsp, newctrl, 1 /* copy */);
  479. }
  480. void
  481. slapi_add_control_ext( LDAPControl ***ctrlsp, LDAPControl *newctrl, int copy )
  482. {
  483. add_control_ext(ctrlsp, newctrl, copy);
  484. }
  485. /*
  486. * return a malloc'd copy of "ctrl"
  487. */
  488. LDAPControl *
  489. slapi_dup_control( LDAPControl *ctrl )
  490. {
  491. LDAPControl *rctrl;
  492. rctrl = (LDAPControl *)slapi_ch_malloc( sizeof( LDAPControl ));
  493. rctrl->ldctl_oid = slapi_ch_strdup( ctrl->ldctl_oid );
  494. rctrl->ldctl_iscritical = ctrl->ldctl_iscritical;
  495. if ( ctrl->ldctl_value.bv_val == NULL ) { /* no value */
  496. rctrl->ldctl_value.bv_len = 0;
  497. rctrl->ldctl_value.bv_val = NULL;
  498. } else if ( ctrl->ldctl_value.bv_len <= 0 ) { /* zero length value */
  499. rctrl->ldctl_value.bv_len = 0;
  500. rctrl->ldctl_value.bv_val = slapi_ch_malloc( 1 );
  501. rctrl->ldctl_value.bv_val[0] = '\0';
  502. } else { /* value with content */
  503. rctrl->ldctl_value.bv_len = ctrl->ldctl_value.bv_len;
  504. rctrl->ldctl_value.bv_val =
  505. slapi_ch_malloc( ctrl->ldctl_value.bv_len );
  506. memcpy( rctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_val,
  507. ctrl->ldctl_value.bv_len );
  508. }
  509. return( rctrl );
  510. }
  511. void
  512. slapi_add_controls( LDAPControl ***ctrlsp, LDAPControl **newctrls, int copy )
  513. {
  514. int ii;
  515. for (ii = 0; newctrls && newctrls[ii]; ++ii) {
  516. slapi_add_control_ext(ctrlsp, newctrls[ii], copy);
  517. }
  518. }
  519. int
  520. slapi_build_control( char *oid, BerElement *ber,
  521. char iscritical, LDAPControl **ctrlp )
  522. {
  523. int rc = 0;
  524. int return_value = LDAP_SUCCESS;
  525. struct berval *bvp = NULL;
  526. PR_ASSERT( NULL != oid && NULL != ctrlp );
  527. if ( NULL == ber ) {
  528. bvp = NULL;
  529. } else {
  530. /* allocate struct berval with contents of the BER encoding */
  531. rc = ber_flatten( ber, &bvp );
  532. if ( -1 == rc ) {
  533. return_value = LDAP_NO_MEMORY;
  534. goto loser;
  535. }
  536. }
  537. /* allocate the new control structure */
  538. *ctrlp = (LDAPControl *)slapi_ch_calloc( 1, sizeof(LDAPControl));
  539. /* fill in the fields of this new control */
  540. (*ctrlp)->ldctl_iscritical = iscritical;
  541. (*ctrlp)->ldctl_oid = slapi_ch_strdup( oid );
  542. if ( NULL == bvp ) {
  543. (*ctrlp)->ldctl_value.bv_len = 0;
  544. (*ctrlp)->ldctl_value.bv_val = NULL;
  545. } else {
  546. (*ctrlp)->ldctl_value = *bvp; /* struct copy */
  547. ldap_memfree(bvp); /* free container, but not contents */
  548. bvp = NULL;
  549. }
  550. loser:
  551. return return_value;
  552. }
  553. #if 0
  554. /*
  555. * rbyrne: This is version of the above using the slapi_build_control_from_berval()
  556. * I'll enable this afterwards.
  557. * Build an allocated LDAPv3 control from a BerElement.
  558. * Returns an LDAP error code.
  559. */
  560. int
  561. slapi_build_control( char *oid, BerElement *ber,
  562. char iscritical, LDAPControl **ctrlp )
  563. {
  564. int rc = 0;
  565. int return_value = LDAP_SUCCESS;
  566. struct berval *bvp = NULL;
  567. PR_ASSERT( NULL != oid && NULL != ctrlp );
  568. if ( NULL == ber ) {
  569. bvp = NULL;
  570. } else {
  571. /* allocate struct berval with contents of the BER encoding */
  572. rc = ber_flatten( ber, &bvp );
  573. if ( -1 == rc ) {
  574. return_value = LDAP_NO_MEMORY;
  575. goto loser;
  576. }
  577. }
  578. return_value = slapi_build_control_from_berval( oid, bvp, iscritical,
  579. ctrlp);
  580. if ( bvp != NULL ) {
  581. ldap_memfree(bvp); /* free container, but not contents */
  582. bvp = NULL;
  583. }
  584. loser:
  585. return return_value;
  586. }
  587. #endif
  588. /*
  589. * Build an allocated LDAPv3 control from a berval. Returns an LDAP error code.
  590. */
  591. int
  592. slapi_build_control_from_berval( char *oid, struct berval *bvp,
  593. char iscritical, LDAPControl **ctrlp )
  594. {
  595. int return_value = LDAP_SUCCESS;
  596. /* allocate the new control structure */
  597. *ctrlp = (LDAPControl *)slapi_ch_calloc( 1, sizeof(LDAPControl));
  598. /* fill in the fields of this new control */
  599. (*ctrlp)->ldctl_iscritical = iscritical;
  600. (*ctrlp)->ldctl_oid = slapi_ch_strdup( oid );
  601. if ( NULL == bvp ) {
  602. (*ctrlp)->ldctl_value.bv_len = 0;
  603. (*ctrlp)->ldctl_value.bv_val = NULL;
  604. } else {
  605. (*ctrlp)->ldctl_value = *bvp; /* struct copy */
  606. }
  607. return return_value;
  608. }