control.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  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. /* control.c - routines for dealing with LDAPMessage controls */
  39. #include <stdio.h>
  40. #include "slap.h"
  41. /*
  42. * static variables used to track information about supported controls.
  43. * supported_controls is a NULL-terminated array of OIDs.
  44. * supported_controls_ops is an array of bitmaps that hold SLAPI_OPERATION_*
  45. * flags that specify the operation(s) for which a control is supported.
  46. * The elements in the supported_controls_ops array align with the ones
  47. * in the supported_controls array.
  48. */
  49. static char **supported_controls = NULL;
  50. static unsigned long *supported_controls_ops = NULL;
  51. static int supported_controls_count = 0;
  52. static PRRWLock *supported_controls_lock = NULL;
  53. /*
  54. * Register all of the LDAPv3 controls we know about "out of the box."
  55. */
  56. void
  57. init_controls( void )
  58. {
  59. supported_controls_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE,
  60. "supported controls rwlock");
  61. if (NULL == supported_controls_lock) {
  62. /* Out of resources */
  63. slapi_log_error(SLAPI_LOG_FATAL, "startup",
  64. "init_controls: failed to create lock.\n");
  65. exit (1);
  66. }
  67. slapi_register_supported_control( LDAP_CONTROL_MANAGEDSAIT,
  68. SLAPI_OPERATION_SEARCH | SLAPI_OPERATION_COMPARE
  69. | SLAPI_OPERATION_ADD | SLAPI_OPERATION_DELETE
  70. | SLAPI_OPERATION_MODIFY | SLAPI_OPERATION_MODDN );
  71. slapi_register_supported_control( LDAP_CONTROL_PERSISTENTSEARCH,
  72. SLAPI_OPERATION_SEARCH );
  73. slapi_register_supported_control( LDAP_CONTROL_PWEXPIRED,
  74. SLAPI_OPERATION_NONE );
  75. slapi_register_supported_control( LDAP_CONTROL_PWEXPIRING,
  76. SLAPI_OPERATION_NONE );
  77. slapi_register_supported_control( LDAP_CONTROL_SORTREQUEST,
  78. SLAPI_OPERATION_SEARCH );
  79. slapi_register_supported_control( LDAP_CONTROL_VLVREQUEST,
  80. SLAPI_OPERATION_SEARCH );
  81. slapi_register_supported_control( LDAP_CONTROL_AUTH_REQUEST,
  82. SLAPI_OPERATION_BIND );
  83. slapi_register_supported_control( LDAP_CONTROL_AUTH_RESPONSE,
  84. SLAPI_OPERATION_NONE );
  85. slapi_register_supported_control( LDAP_CONTROL_REAL_ATTRS_ONLY,
  86. SLAPI_OPERATION_SEARCH );
  87. slapi_register_supported_control( LDAP_CONTROL_VIRT_ATTRS_ONLY,
  88. SLAPI_OPERATION_SEARCH );
  89. slapi_register_supported_control( LDAP_X_CONTROL_PWPOLICY_REQUEST,
  90. SLAPI_OPERATION_SEARCH | SLAPI_OPERATION_COMPARE
  91. | SLAPI_OPERATION_ADD | SLAPI_OPERATION_DELETE
  92. | SLAPI_OPERATION_MODIFY | SLAPI_OPERATION_MODDN );
  93. /*
  94. We do not register the password policy response because it has
  95. the same oid as the request (and it was being reported twice in
  96. in the root DSE supportedControls attribute)
  97. slapi_register_supported_control( LDAP_X_CONTROL_PWPOLICY_RESPONSE,
  98. SLAPI_OPERATION_SEARCH | SLAPI_OPERATION_COMPARE
  99. | SLAPI_OPERATION_ADD | SLAPI_OPERATION_DELETE
  100. | SLAPI_OPERATION_MODIFY | SLAPI_OPERATION_MODDN );
  101. */
  102. slapi_register_supported_control( LDAP_CONTROL_GET_EFFECTIVE_RIGHTS,
  103. SLAPI_OPERATION_SEARCH );
  104. }
  105. /*
  106. * register a supported control so it can be returned as part of the root DSE.
  107. */
  108. void
  109. slapi_register_supported_control( char *controloid, unsigned long controlops )
  110. {
  111. if ( controloid != NULL ) {
  112. PR_RWLock_Wlock(supported_controls_lock);
  113. ++supported_controls_count;
  114. charray_add( &supported_controls,
  115. slapi_ch_strdup( controloid ));
  116. supported_controls_ops = (unsigned long *)slapi_ch_realloc(
  117. (char *)supported_controls_ops,
  118. supported_controls_count * sizeof( unsigned long ));
  119. supported_controls_ops[ supported_controls_count - 1 ] =
  120. controlops;
  121. PR_RWLock_Unlock(supported_controls_lock);
  122. }
  123. }
  124. /*
  125. * retrieve supported controls OID and/or operations arrays.
  126. * return 0 if successful and -1 if not.
  127. * This function is not MTSafe and should be deprecated.
  128. * slapi_get_supported_controls_copy should be used instead.
  129. */
  130. int
  131. slapi_get_supported_controls( char ***ctrloidsp, unsigned long **ctrlopsp )
  132. {
  133. if ( ctrloidsp != NULL ) {
  134. *ctrloidsp = supported_controls;
  135. }
  136. if ( ctrlopsp != NULL ) {
  137. *ctrlopsp = supported_controls_ops;
  138. }
  139. return( 0 );
  140. }
  141. static
  142. unsigned long *supported_controls_ops_dup(unsigned long *ctrlops)
  143. {
  144. int i;
  145. unsigned long *dup_ops = (unsigned long *)slapi_ch_calloc(
  146. supported_controls_count + 1, sizeof( unsigned long ));
  147. if (NULL != dup_ops) {
  148. for (i=0; i < supported_controls_count; i++)
  149. dup_ops[i] = supported_controls_ops[i];
  150. }
  151. return dup_ops;
  152. }
  153. int slapi_get_supported_controls_copy( char ***ctrloidsp, unsigned long **ctrlopsp )
  154. {
  155. PR_RWLock_Rlock(supported_controls_lock);
  156. if ( ctrloidsp != NULL ) {
  157. *ctrloidsp = charray_dup(supported_controls);
  158. }
  159. if ( ctrlopsp != NULL ) {
  160. *ctrlopsp = supported_controls_ops_dup(supported_controls_ops);
  161. }
  162. PR_RWLock_Unlock(supported_controls_lock);
  163. return (0);
  164. }
  165. int
  166. get_ldapmessage_controls(
  167. Slapi_PBlock *pb,
  168. BerElement *ber,
  169. LDAPControl ***controlsp /* can be NULL if no need to return */
  170. )
  171. {
  172. LDAPControl **ctrls, *new;
  173. ber_tag_t tag;
  174. ber_len_t len;
  175. int rc, maxcontrols, curcontrols;
  176. char *last;
  177. int managedsait, pwpolicy_ctrl;
  178. /*
  179. * Each LDAPMessage can have a set of controls appended
  180. * to it. Controls are used to extend the functionality
  181. * of an LDAP operation (e.g., add an attribute size limit
  182. * to the search operation). These controls look like this:
  183. *
  184. * Controls ::= SEQUENCE OF Control
  185. *
  186. * Control ::= SEQUENCE {
  187. * controlType LDAPOID,
  188. * criticality BOOLEAN DEFAULT FALSE,
  189. * controlValue OCTET STRING
  190. * }
  191. */
  192. LDAPDebug( LDAP_DEBUG_TRACE, "=> get_ldapmessage_controls\n", 0, 0, 0 );
  193. ctrls = NULL;
  194. slapi_pblock_set( pb, SLAPI_REQCONTROLS, ctrls );
  195. if ( controlsp != NULL ) {
  196. *controlsp = NULL;
  197. }
  198. rc = LDAP_PROTOCOL_ERROR; /* most popular error we may return */
  199. /*
  200. * check to see if controls were included
  201. */
  202. if ( ber_get_option( ber, LBER_OPT_REMAINING_BYTES, &len ) != 0 ) {
  203. LDAPDebug( LDAP_DEBUG_TRACE,
  204. "<= get_ldapmessage_controls LDAP_OPERATIONS_ERROR\n",
  205. 0, 0, 0 );
  206. return( LDAP_OPERATIONS_ERROR ); /* unexpected error */
  207. }
  208. if ( len == 0 ) {
  209. LDAPDebug( LDAP_DEBUG_TRACE,
  210. "<= get_ldapmessage_controls no controls\n", 0, 0, 0 );
  211. return( LDAP_SUCCESS ); /* no controls */
  212. }
  213. if (( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
  214. if ( tag == LBER_ERROR ) {
  215. LDAPDebug( LDAP_DEBUG_TRACE,
  216. "<= get_ldapmessage_controls LDAP_PROTOCOL_ERROR\n",
  217. 0, 0, 0 );
  218. return( LDAP_PROTOCOL_ERROR ); /* decoding error */
  219. }
  220. /*
  221. * We found something other than controls. This should never
  222. * happen in LDAPv3, but we don't treat this is a hard error --
  223. * we just ignore the extra stuff.
  224. */
  225. LDAPDebug( LDAP_DEBUG_TRACE,
  226. "<= get_ldapmessage_controls ignoring unrecognized data in request (tag 0x%x)\n",
  227. tag, 0, 0 );
  228. return( LDAP_SUCCESS );
  229. }
  230. /*
  231. * A sequence of controls is present. If connection is not LDAPv3
  232. * or better, return a protocol error. Otherwise, parse the controls.
  233. */
  234. if ( pb != NULL && pb->pb_conn != NULL
  235. && pb->pb_conn->c_ldapversion < LDAP_VERSION3 ) {
  236. slapi_log_error( SLAPI_LOG_FATAL, "connection",
  237. "received control(s) on an LDAPv%d connection\n",
  238. pb->pb_conn->c_ldapversion );
  239. return( LDAP_PROTOCOL_ERROR );
  240. }
  241. maxcontrols = curcontrols = 0;
  242. for ( tag = ber_first_element( ber, &len, &last );
  243. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  244. tag = ber_next_element( ber, &len, last ) ) {
  245. if ( curcontrols >= maxcontrols - 1 ) {
  246. #define CONTROL_GRABSIZE 6
  247. maxcontrols += CONTROL_GRABSIZE;
  248. ctrls = (LDAPControl **) slapi_ch_realloc( (char *)ctrls,
  249. maxcontrols * sizeof(LDAPControl *) );
  250. }
  251. new = (LDAPControl *) slapi_ch_calloc( 1, sizeof(LDAPControl) );
  252. ctrls[curcontrols++] = new;
  253. ctrls[curcontrols] = NULL;
  254. if ( ber_scanf( ber, "{a", &new->ldctl_oid ) == LBER_ERROR ) {
  255. goto free_and_return;
  256. }
  257. /* the criticality is optional */
  258. if ( ber_peek_tag( ber, &len ) == LBER_BOOLEAN ) {
  259. if ( ber_scanf( ber, "b", &new->ldctl_iscritical )
  260. == LBER_ERROR ) {
  261. goto free_and_return;
  262. }
  263. } else {
  264. /* absent is synonomous with FALSE */
  265. new->ldctl_iscritical = 0;
  266. }
  267. /*
  268. * return an appropriate error if this control is marked
  269. * critical and either:
  270. * a) we do not support it at all OR
  271. * b) it is not supported for this operation
  272. */
  273. if ( new->ldctl_iscritical ) {
  274. int i;
  275. PR_RWLock_Rlock(supported_controls_lock);
  276. for ( i = 0; supported_controls != NULL
  277. && supported_controls[i] != NULL; ++i ) {
  278. if ( strcmp( supported_controls[i],
  279. new->ldctl_oid ) == 0 ) {
  280. break;
  281. }
  282. }
  283. if ( supported_controls == NULL ||
  284. supported_controls[i] == NULL ||
  285. ( 0 == ( supported_controls_ops[i] &
  286. operation_get_type(pb->pb_op) ))) {
  287. rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  288. PR_RWLock_Unlock(supported_controls_lock);
  289. goto free_and_return;
  290. }
  291. PR_RWLock_Unlock(supported_controls_lock);
  292. }
  293. /* the control value is optional */
  294. if ( ber_peek_tag( ber, &len ) == LBER_OCTETSTRING ) {
  295. if ( ber_scanf( ber, "o", &new->ldctl_value )
  296. == LBER_ERROR ) {
  297. goto free_and_return;
  298. }
  299. } else {
  300. (new->ldctl_value).bv_val = NULL;
  301. (new->ldctl_value).bv_len = 0;
  302. }
  303. }
  304. if ( tag == LBER_ERROR ) {
  305. goto free_and_return;
  306. }
  307. slapi_pblock_set( pb, SLAPI_REQCONTROLS, ctrls );
  308. managedsait = slapi_control_present( ctrls,
  309. LDAP_CONTROL_MANAGEDSAIT, NULL, NULL );
  310. slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, &managedsait );
  311. pwpolicy_ctrl = slapi_control_present( ctrls,
  312. LDAP_X_CONTROL_PWPOLICY_REQUEST, NULL, NULL );
  313. slapi_pblock_set( pb, SLAPI_PWPOLICY, &pwpolicy_ctrl );
  314. if ( controlsp != NULL ) {
  315. *controlsp = ctrls;
  316. }
  317. #ifdef SLAPD_ECHO_CONTROL
  318. /*
  319. * XXXmcs: Start of hack: if a control with OID "1.1" was sent by
  320. * the client, echo all controls back to the client unchanged. Note
  321. * that this is just a hack to test control handling in libldap and
  322. * should be removed once we support all interesting controls.
  323. */
  324. if ( slapi_control_present( ctrls, "1.1", NULL, NULL )) {
  325. int i;
  326. for ( i = 0; ctrls[i] != NULL; ++i ) {
  327. slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL,
  328. (void *)ctrls[i] );
  329. }
  330. }
  331. #endif /* SLAPD_ECHO_CONTROL */
  332. LDAPDebug( LDAP_DEBUG_TRACE,
  333. "<= get_ldapmessage_controls %d controls\n", curcontrols, 0, 0 );
  334. return( LDAP_SUCCESS );
  335. free_and_return:;
  336. ldap_controls_free( ctrls );
  337. LDAPDebug( LDAP_DEBUG_TRACE,
  338. "<= get_ldapmessage_controls %i\n", rc, 0, 0 );
  339. return( rc );
  340. }
  341. int
  342. slapi_control_present( LDAPControl **controls, char *oid, struct berval **val, int *iscritical )
  343. {
  344. int i;
  345. LDAPDebug( LDAP_DEBUG_TRACE,
  346. "=> slapi_control_present (looking for %s)\n", oid, 0, 0 );
  347. if ( val != NULL ) {
  348. *val = NULL;
  349. }
  350. if ( controls == NULL ) {
  351. LDAPDebug( LDAP_DEBUG_TRACE,
  352. "<= slapi_control_present 0 (NO CONTROLS)\n", 0, 0, 0 );
  353. return( 0 );
  354. }
  355. for ( i = 0; controls[i] != NULL; i++ ) {
  356. if ( strcmp( controls[i]->ldctl_oid, oid ) == 0 ) {
  357. if ( val != NULL ) {
  358. if (NULL != val) {
  359. *val = &controls[i]->ldctl_value;
  360. }
  361. if (NULL != iscritical) {
  362. *iscritical = (int) controls[i]->ldctl_iscritical;
  363. }
  364. }
  365. LDAPDebug( LDAP_DEBUG_TRACE,
  366. "<= slapi_control_present 1 (FOUND)\n", 0, 0, 0 );
  367. return( 1 );
  368. }
  369. }
  370. LDAPDebug( LDAP_DEBUG_TRACE,
  371. "<= slapi_control_present 0 (NOT FOUND)\n", 0, 0, 0 );
  372. return( 0 );
  373. }
  374. /*
  375. * Write sequence of controls in "ctrls" to "ber".
  376. * Return zero on success and -1 if an error occurs.
  377. */
  378. int
  379. write_controls( BerElement *ber, LDAPControl **ctrls )
  380. {
  381. int i;
  382. unsigned long rc;
  383. rc= ber_start_seq( ber, LDAP_TAG_CONTROLS );
  384. if ( rc == LBER_ERROR ) {
  385. return( -1 );
  386. }
  387. /* if the criticality is false, it should be absent from the encoding */
  388. for ( i = 0; ctrls[ i ] != NULL; ++i ) {
  389. if ( ctrls[ i ]->ldctl_value.bv_val == 0 ) {
  390. if ( ctrls[ i ]->ldctl_iscritical ) {
  391. rc = ber_printf( ber, "{sb}", ctrls[ i ]->ldctl_oid,
  392. ctrls[ i ]->ldctl_iscritical );
  393. } else {
  394. rc = ber_printf( ber, "{s}", ctrls[ i ]->ldctl_oid );
  395. }
  396. } else {
  397. if ( ctrls[ i ]->ldctl_iscritical ) {
  398. rc = ber_printf( ber, "{sbo}", ctrls[ i ]->ldctl_oid,
  399. ctrls[ i ]->ldctl_iscritical,
  400. ctrls[ i ]->ldctl_value.bv_val,
  401. ctrls[ i ]->ldctl_value.bv_len );
  402. } else {
  403. rc = ber_printf( ber, "{so}", ctrls[ i ]->ldctl_oid,
  404. ctrls[ i ]->ldctl_value.bv_val,
  405. ctrls[ i ]->ldctl_value.bv_len );
  406. }
  407. }
  408. if ( rc == LBER_ERROR ) {
  409. return( -1 );
  410. }
  411. }
  412. rc= ber_put_seq( ber );
  413. if ( rc == LBER_ERROR ) {
  414. return( -1 );
  415. }
  416. return( 0 );
  417. }
  418. /*
  419. * duplicate "newctrl" and add it to the array of controls "*ctrlsp"
  420. * note that *ctrlsp may be reset and that it is okay to pass NULL for it.
  421. */
  422. void
  423. add_control( LDAPControl ***ctrlsp, LDAPControl *newctrl )
  424. {
  425. int count;
  426. if ( *ctrlsp == NULL ) {
  427. count = 0;
  428. } else {
  429. for ( count = 0; (*ctrlsp)[count] != NULL; ++count ) {
  430. ;
  431. }
  432. }
  433. *ctrlsp = (LDAPControl **)slapi_ch_realloc( (char *)*ctrlsp,
  434. ( count + 2 ) * sizeof(LDAPControl *));
  435. (*ctrlsp)[ count ] = slapi_dup_control( newctrl );
  436. (*ctrlsp)[ ++count ] = NULL;
  437. }
  438. /*
  439. * return a malloc'd copy of "ctrl"
  440. */
  441. LDAPControl *
  442. slapi_dup_control( LDAPControl *ctrl )
  443. {
  444. LDAPControl *rctrl;
  445. rctrl = (LDAPControl *)slapi_ch_malloc( sizeof( LDAPControl ));
  446. rctrl->ldctl_oid = slapi_ch_strdup( ctrl->ldctl_oid );
  447. rctrl->ldctl_iscritical = ctrl->ldctl_iscritical;
  448. if ( ctrl->ldctl_value.bv_val == NULL ) { /* no value */
  449. rctrl->ldctl_value.bv_len = 0;
  450. rctrl->ldctl_value.bv_val = NULL;
  451. } else if ( ctrl->ldctl_value.bv_len <= 0 ) { /* zero length value */
  452. rctrl->ldctl_value.bv_len = 0;
  453. rctrl->ldctl_value.bv_val = slapi_ch_malloc( 1 );
  454. rctrl->ldctl_value.bv_val[0] = '\0';
  455. } else { /* value with content */
  456. rctrl->ldctl_value.bv_len = ctrl->ldctl_value.bv_len;
  457. rctrl->ldctl_value.bv_val =
  458. slapi_ch_malloc( ctrl->ldctl_value.bv_len );
  459. memcpy( rctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_val,
  460. ctrl->ldctl_value.bv_len );
  461. }
  462. return( rctrl );
  463. }
  464. int
  465. slapi_build_control( char *oid, BerElement *ber,
  466. char iscritical, LDAPControl **ctrlp )
  467. {
  468. int rc = 0;
  469. int return_value = LDAP_SUCCESS;
  470. struct berval *bvp = NULL;
  471. PR_ASSERT( NULL != oid && NULL != ctrlp );
  472. if ( NULL == ber ) {
  473. bvp = NULL;
  474. } else {
  475. /* allocate struct berval with contents of the BER encoding */
  476. rc = ber_flatten( ber, &bvp );
  477. if ( -1 == rc ) {
  478. return_value = LDAP_NO_MEMORY;
  479. goto loser;
  480. }
  481. }
  482. /* allocate the new control structure */
  483. *ctrlp = (LDAPControl *)slapi_ch_calloc( 1, sizeof(LDAPControl));
  484. /* fill in the fields of this new control */
  485. (*ctrlp)->ldctl_iscritical = iscritical;
  486. (*ctrlp)->ldctl_oid = slapi_ch_strdup( oid );
  487. if ( NULL == bvp ) {
  488. (*ctrlp)->ldctl_value.bv_len = 0;
  489. (*ctrlp)->ldctl_value.bv_val = NULL;
  490. } else {
  491. (*ctrlp)->ldctl_value = *bvp; /* struct copy */
  492. ldap_memfree(bvp); /* free container, but not contents */
  493. bvp = NULL;
  494. }
  495. loser:
  496. return return_value;
  497. }
  498. #if 0
  499. /*
  500. * rbyrne: This is version of the above using the slapi_build_control_from_berval()
  501. * I'll enable this afterwards.
  502. * Build an allocated LDAPv3 control from a BerElement.
  503. * Returns an LDAP error code.
  504. */
  505. int
  506. slapi_build_control( char *oid, BerElement *ber,
  507. char iscritical, LDAPControl **ctrlp )
  508. {
  509. int rc = 0;
  510. int return_value = LDAP_SUCCESS;
  511. struct berval *bvp = NULL;
  512. PR_ASSERT( NULL != oid && NULL != ctrlp );
  513. if ( NULL == ber ) {
  514. bvp = NULL;
  515. } else {
  516. /* allocate struct berval with contents of the BER encoding */
  517. rc = ber_flatten( ber, &bvp );
  518. if ( -1 == rc ) {
  519. return_value = LDAP_NO_MEMORY;
  520. goto loser;
  521. }
  522. }
  523. return_value = slapi_build_control_from_berval( oid, bvp, iscritical,
  524. ctrlp);
  525. if ( bvp != NULL ) {
  526. ldap_memfree(bvp); /* free container, but not contents */
  527. bvp = NULL;
  528. }
  529. loser:
  530. return return_value;
  531. }
  532. #endif
  533. /*
  534. * Build an allocated LDAPv3 control from a berval. Returns an LDAP error code.
  535. */
  536. int
  537. slapi_build_control_from_berval( char *oid, struct berval *bvp,
  538. char iscritical, LDAPControl **ctrlp )
  539. {
  540. int return_value = LDAP_SUCCESS;
  541. /* allocate the new control structure */
  542. *ctrlp = (LDAPControl *)slapi_ch_calloc( 1, sizeof(LDAPControl));
  543. /* fill in the fields of this new control */
  544. (*ctrlp)->ldctl_iscritical = iscritical;
  545. (*ctrlp)->ldctl_oid = slapi_ch_strdup( oid );
  546. if ( NULL == bvp ) {
  547. (*ctrlp)->ldctl_value.bv_len = 0;
  548. (*ctrlp)->ldctl_value.bv_val = NULL;
  549. } else {
  550. (*ctrlp)->ldctl_value = *bvp; /* struct copy */
  551. }
  552. return return_value;
  553. }