control.c 19 KB

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