controls.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. /* $OpenLDAP$ */
  2. /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  3. *
  4. * Copyright 1998-2022 The OpenLDAP Foundation.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted only as authorized by the OpenLDAP
  9. * Public License.
  10. *
  11. * A copy of this license is available in the file LICENSE in the
  12. * top-level directory of the distribution or, alternatively, at
  13. * <http://www.OpenLDAP.org/license.html>.
  14. */
  15. /* This notice applies to changes, created by or for Novell, Inc.,
  16. * to preexisting works for which notices appear elsewhere in this file.
  17. *
  18. * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
  19. *
  20. * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
  21. * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
  22. * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
  23. * HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
  24. * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
  25. * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
  26. * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
  27. * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
  28. *---
  29. * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
  30. * can be found in the file "build/LICENSE-2.0.1" in this distribution
  31. * of OpenLDAP Software.
  32. */
  33. #include "portable.h"
  34. #include <ac/stdlib.h>
  35. #include <ac/time.h>
  36. #include <ac/string.h>
  37. #include "ldap-int.h"
  38. /* LDAPv3 Controls (RFC 4511)
  39. *
  40. * Controls ::= SEQUENCE OF control Control
  41. *
  42. * Control ::= SEQUENCE {
  43. * controlType LDAPOID,
  44. * criticality BOOLEAN DEFAULT FALSE,
  45. * controlValue OCTET STRING OPTIONAL
  46. * }
  47. */
  48. int
  49. ldap_pvt_put_control(
  50. const LDAPControl *c,
  51. BerElement *ber )
  52. {
  53. if ( ber_printf( ber, "{s" /*}*/, c->ldctl_oid ) == -1 ) {
  54. return LDAP_ENCODING_ERROR;
  55. }
  56. if ( c->ldctl_iscritical /* only if true */
  57. && ( ber_printf( ber, "b",
  58. (ber_int_t) c->ldctl_iscritical ) == -1 ) )
  59. {
  60. return LDAP_ENCODING_ERROR;
  61. }
  62. if ( !BER_BVISNULL( &c->ldctl_value ) /* only if we have a value */
  63. && ( ber_printf( ber, "O", &c->ldctl_value ) == -1 ) )
  64. {
  65. return LDAP_ENCODING_ERROR;
  66. }
  67. if ( ber_printf( ber, /*{*/"N}" ) == -1 ) {
  68. return LDAP_ENCODING_ERROR;
  69. }
  70. return LDAP_SUCCESS;
  71. }
  72. /*
  73. * ldap_int_put_controls
  74. */
  75. int
  76. ldap_int_put_controls(
  77. LDAP *ld,
  78. LDAPControl *const *ctrls,
  79. BerElement *ber )
  80. {
  81. LDAPControl *const *c;
  82. assert( ld != NULL );
  83. assert( LDAP_VALID( ld ) );
  84. assert( ber != NULL );
  85. if( ctrls == NULL ) {
  86. /* use default server controls */
  87. ctrls = ld->ld_sctrls;
  88. }
  89. if( ctrls == NULL || *ctrls == NULL ) {
  90. return LDAP_SUCCESS;
  91. }
  92. if ( ld->ld_version < LDAP_VERSION3 ) {
  93. /* LDAPv2 doesn't support controls,
  94. * error if any control is critical
  95. */
  96. for( c = ctrls ; *c != NULL; c++ ) {
  97. if( (*c)->ldctl_iscritical ) {
  98. ld->ld_errno = LDAP_NOT_SUPPORTED;
  99. return ld->ld_errno;
  100. }
  101. }
  102. return LDAP_SUCCESS;
  103. }
  104. /* Controls are encoded as a sequence of sequences */
  105. if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) {
  106. ld->ld_errno = LDAP_ENCODING_ERROR;
  107. return ld->ld_errno;
  108. }
  109. for( c = ctrls ; *c != NULL; c++ ) {
  110. ld->ld_errno = ldap_pvt_put_control( *c, ber );
  111. if ( ld->ld_errno != LDAP_SUCCESS ) {
  112. return ld->ld_errno;
  113. }
  114. }
  115. if( ber_printf( ber, /*{*/ "}" ) == -1 ) {
  116. ld->ld_errno = LDAP_ENCODING_ERROR;
  117. return ld->ld_errno;
  118. }
  119. return LDAP_SUCCESS;
  120. }
  121. int ldap_pvt_get_controls(
  122. BerElement *ber,
  123. LDAPControl ***ctrls )
  124. {
  125. int nctrls;
  126. ber_tag_t tag;
  127. ber_len_t len;
  128. char *opaque;
  129. assert( ber != NULL );
  130. if( ctrls == NULL ) {
  131. return LDAP_SUCCESS;
  132. }
  133. *ctrls = NULL;
  134. len = ber_pvt_ber_remaining( ber );
  135. if( len == 0) {
  136. /* no controls */
  137. return LDAP_SUCCESS;
  138. }
  139. if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
  140. if( tag == LBER_ERROR ) {
  141. /* decoding error */
  142. return LDAP_DECODING_ERROR;
  143. }
  144. /* ignore unexpected input */
  145. return LDAP_SUCCESS;
  146. }
  147. /* set through each element */
  148. nctrls = 0;
  149. *ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
  150. if( *ctrls == NULL ) {
  151. return LDAP_NO_MEMORY;
  152. }
  153. *ctrls[nctrls] = NULL;
  154. for( tag = ber_first_element( ber, &len, &opaque );
  155. tag != LBER_ERROR;
  156. tag = ber_next_element( ber, &len, opaque ) )
  157. {
  158. LDAPControl *tctrl;
  159. LDAPControl **tctrls;
  160. tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
  161. /* allocate pointer space for current controls (nctrls)
  162. * + this control + extra NULL
  163. */
  164. tctrls = (tctrl == NULL) ? NULL :
  165. LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
  166. if( tctrls == NULL ) {
  167. /* one of the above allocation failed */
  168. if( tctrl != NULL ) {
  169. LDAP_FREE( tctrl );
  170. }
  171. ldap_controls_free(*ctrls);
  172. *ctrls = NULL;
  173. return LDAP_NO_MEMORY;
  174. }
  175. tctrls[nctrls++] = tctrl;
  176. tctrls[nctrls] = NULL;
  177. tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
  178. if( tag == LBER_ERROR ) {
  179. *ctrls = NULL;
  180. ldap_controls_free( tctrls );
  181. return LDAP_DECODING_ERROR;
  182. }
  183. tag = ber_peek_tag( ber, &len );
  184. if( tag == LBER_BOOLEAN ) {
  185. ber_int_t crit;
  186. tag = ber_scanf( ber, "b", &crit );
  187. tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
  188. tag = ber_peek_tag( ber, &len );
  189. }
  190. if( tag == LBER_OCTETSTRING ) {
  191. tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
  192. } else {
  193. BER_BVZERO( &tctrl->ldctl_value );
  194. }
  195. *ctrls = tctrls;
  196. }
  197. return LDAP_SUCCESS;
  198. }
  199. /*
  200. * Free a LDAPControl
  201. */
  202. void
  203. ldap_control_free( LDAPControl *c )
  204. {
  205. LDAP_MEMORY_DEBUG_ASSERT( c != NULL );
  206. if ( c != NULL ) {
  207. if( c->ldctl_oid != NULL) {
  208. LDAP_FREE( c->ldctl_oid );
  209. }
  210. if( c->ldctl_value.bv_val != NULL ) {
  211. LDAP_FREE( c->ldctl_value.bv_val );
  212. }
  213. LDAP_FREE( c );
  214. }
  215. }
  216. /*
  217. * Free an array of LDAPControl's
  218. */
  219. void
  220. ldap_controls_free( LDAPControl **controls )
  221. {
  222. LDAP_MEMORY_DEBUG_ASSERT( controls != NULL );
  223. if ( controls != NULL ) {
  224. int i;
  225. for( i=0; controls[i] != NULL; i++) {
  226. ldap_control_free( controls[i] );
  227. }
  228. LDAP_FREE( controls );
  229. }
  230. }
  231. /*
  232. * Duplicate an array of LDAPControl
  233. */
  234. LDAPControl **
  235. ldap_controls_dup( LDAPControl *const *controls )
  236. {
  237. LDAPControl **new;
  238. int i;
  239. if ( controls == NULL ) {
  240. return NULL;
  241. }
  242. /* count the controls */
  243. for(i=0; controls[i] != NULL; i++) /* empty */ ;
  244. if( i < 1 ) {
  245. /* no controls to duplicate */
  246. return NULL;
  247. }
  248. new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
  249. if( new == NULL ) {
  250. /* memory allocation failure */
  251. return NULL;
  252. }
  253. /* duplicate the controls */
  254. for(i=0; controls[i] != NULL; i++) {
  255. new[i] = ldap_control_dup( controls[i] );
  256. if( new[i] == NULL ) {
  257. ldap_controls_free( new );
  258. return NULL;
  259. }
  260. }
  261. new[i] = NULL;
  262. return new;
  263. }
  264. /*
  265. * Duplicate a LDAPControl
  266. */
  267. LDAPControl *
  268. ldap_control_dup( const LDAPControl *c )
  269. {
  270. LDAPControl *new;
  271. if ( c == NULL || c->ldctl_oid == NULL ) {
  272. return NULL;
  273. }
  274. new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
  275. if( new == NULL ) {
  276. return NULL;
  277. }
  278. new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
  279. if(new->ldctl_oid == NULL) {
  280. LDAP_FREE( new );
  281. return NULL;
  282. }
  283. if( c->ldctl_value.bv_val != NULL ) {
  284. new->ldctl_value.bv_val =
  285. (char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
  286. if(new->ldctl_value.bv_val == NULL) {
  287. if(new->ldctl_oid != NULL) {
  288. LDAP_FREE( new->ldctl_oid );
  289. }
  290. LDAP_FREE( new );
  291. return NULL;
  292. }
  293. new->ldctl_value.bv_len = c->ldctl_value.bv_len;
  294. AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val,
  295. c->ldctl_value.bv_len );
  296. new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
  297. } else {
  298. new->ldctl_value.bv_len = 0;
  299. new->ldctl_value.bv_val = NULL;
  300. }
  301. new->ldctl_iscritical = c->ldctl_iscritical;
  302. return new;
  303. }
  304. /*
  305. * Find a LDAPControl - deprecated
  306. */
  307. LDAPControl *
  308. ldap_find_control(
  309. LDAP_CONST char *oid,
  310. LDAPControl **ctrls )
  311. {
  312. if( ctrls == NULL || *ctrls == NULL ) {
  313. return NULL;
  314. }
  315. for( ; *ctrls != NULL; ctrls++ ) {
  316. if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
  317. return *ctrls;
  318. }
  319. }
  320. return NULL;
  321. }
  322. /*
  323. * Find a LDAPControl
  324. */
  325. LDAPControl *
  326. ldap_control_find(
  327. LDAP_CONST char *oid,
  328. LDAPControl **ctrls,
  329. LDAPControl ***nextctrlp )
  330. {
  331. if ( oid == NULL || ctrls == NULL || *ctrls == NULL ) {
  332. return NULL;
  333. }
  334. for( ; *ctrls != NULL; ctrls++ ) {
  335. if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
  336. if ( nextctrlp != NULL ) {
  337. *nextctrlp = ctrls + 1;
  338. }
  339. return *ctrls;
  340. }
  341. }
  342. if ( nextctrlp != NULL ) {
  343. *nextctrlp = NULL;
  344. }
  345. return NULL;
  346. }
  347. /*
  348. * Create a LDAPControl, optionally from ber - deprecated
  349. */
  350. int
  351. ldap_create_control(
  352. LDAP_CONST char *requestOID,
  353. BerElement *ber,
  354. int iscritical,
  355. LDAPControl **ctrlp )
  356. {
  357. LDAPControl *ctrl;
  358. assert( requestOID != NULL );
  359. assert( ctrlp != NULL );
  360. ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
  361. if ( ctrl == NULL ) {
  362. return LDAP_NO_MEMORY;
  363. }
  364. BER_BVZERO(&ctrl->ldctl_value);
  365. if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) {
  366. LDAP_FREE( ctrl );
  367. return LDAP_NO_MEMORY;
  368. }
  369. ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
  370. ctrl->ldctl_iscritical = iscritical;
  371. if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
  372. ldap_control_free( ctrl );
  373. return LDAP_NO_MEMORY;
  374. }
  375. *ctrlp = ctrl;
  376. return LDAP_SUCCESS;
  377. }
  378. /*
  379. * Create a LDAPControl, optionally from value
  380. */
  381. int
  382. ldap_control_create(
  383. LDAP_CONST char *requestOID,
  384. int iscritical,
  385. struct berval *value,
  386. int dupval,
  387. LDAPControl **ctrlp )
  388. {
  389. LDAPControl *ctrl;
  390. assert( requestOID != NULL );
  391. assert( ctrlp != NULL );
  392. ctrl = (LDAPControl *) LDAP_CALLOC( sizeof(LDAPControl), 1 );
  393. if ( ctrl == NULL ) {
  394. return LDAP_NO_MEMORY;
  395. }
  396. ctrl->ldctl_iscritical = iscritical;
  397. if ( requestOID != NULL ) {
  398. ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
  399. if ( ctrl->ldctl_oid == NULL ) {
  400. ldap_control_free( ctrl );
  401. return LDAP_NO_MEMORY;
  402. }
  403. }
  404. if ( value && !BER_BVISNULL( value ) ) {
  405. if ( dupval ) {
  406. ber_dupbv( &ctrl->ldctl_value, value );
  407. if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
  408. ldap_control_free( ctrl );
  409. return LDAP_NO_MEMORY;
  410. }
  411. } else {
  412. ctrl->ldctl_value = *value;
  413. }
  414. }
  415. *ctrlp = ctrl;
  416. return LDAP_SUCCESS;
  417. }
  418. /*
  419. * check for critical client controls and bitch if present
  420. * if we ever support critical controls, we'll have to
  421. * find a means for maintaining per API call control
  422. * information.
  423. */
  424. int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
  425. {
  426. LDAPControl *const *c;
  427. assert( ld != NULL );
  428. assert( LDAP_VALID( ld ) );
  429. if( ctrls == NULL ) {
  430. /* use default client controls */
  431. ctrls = ld->ld_cctrls;
  432. }
  433. if( ctrls == NULL || *ctrls == NULL ) {
  434. return LDAP_SUCCESS;
  435. }
  436. for( c = ctrls ; *c != NULL; c++ ) {
  437. if( (*c)->ldctl_iscritical ) {
  438. ld->ld_errno = LDAP_NOT_SUPPORTED;
  439. return ld->ld_errno;
  440. }
  441. }
  442. return LDAP_SUCCESS;
  443. }