control.c 18 KB

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