extended.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  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. #include "portable.h"
  16. #include <stdio.h>
  17. #include <ac/stdlib.h>
  18. #include <ac/socket.h>
  19. #include <ac/string.h>
  20. #include <ac/time.h>
  21. #include "ldap-int.h"
  22. #include "ldap_log.h"
  23. BerElement *
  24. ldap_build_extended_req(
  25. LDAP *ld,
  26. LDAP_CONST char *reqoid,
  27. struct berval *reqdata,
  28. LDAPControl **sctrls,
  29. LDAPControl **cctrls,
  30. ber_int_t *msgidp )
  31. {
  32. BerElement *ber;
  33. int rc;
  34. /* create a message to send */
  35. if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
  36. return( NULL );
  37. }
  38. LDAP_NEXT_MSGID( ld, *msgidp );
  39. if ( reqdata != NULL ) {
  40. rc = ber_printf( ber, "{it{tstON}", /* '}' */
  41. *msgidp, LDAP_REQ_EXTENDED,
  42. LDAP_TAG_EXOP_REQ_OID, reqoid,
  43. LDAP_TAG_EXOP_REQ_VALUE, reqdata );
  44. } else {
  45. rc = ber_printf( ber, "{it{tsN}", /* '}' */
  46. *msgidp, LDAP_REQ_EXTENDED,
  47. LDAP_TAG_EXOP_REQ_OID, reqoid );
  48. }
  49. if( rc == -1 ) {
  50. ld->ld_errno = LDAP_ENCODING_ERROR;
  51. ber_free( ber, 1 );
  52. return( NULL );
  53. }
  54. /* Put Server Controls */
  55. if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
  56. ber_free( ber, 1 );
  57. return( NULL );
  58. }
  59. if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
  60. ld->ld_errno = LDAP_ENCODING_ERROR;
  61. ber_free( ber, 1 );
  62. return( NULL );
  63. }
  64. return( ber );
  65. }
  66. /*
  67. * LDAPv3 Extended Operation Request
  68. * ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
  69. * requestName [0] LDAPOID,
  70. * requestValue [1] OCTET STRING OPTIONAL
  71. * }
  72. *
  73. * LDAPv3 Extended Operation Response
  74. * ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
  75. * COMPONENTS OF LDAPResult,
  76. * responseName [10] LDAPOID OPTIONAL,
  77. * response [11] OCTET STRING OPTIONAL
  78. * }
  79. *
  80. * (Source RFC 4511)
  81. */
  82. int
  83. ldap_extended_operation(
  84. LDAP *ld,
  85. LDAP_CONST char *reqoid,
  86. struct berval *reqdata,
  87. LDAPControl **sctrls,
  88. LDAPControl **cctrls,
  89. int *msgidp )
  90. {
  91. BerElement *ber;
  92. ber_int_t id;
  93. Debug0( LDAP_DEBUG_TRACE, "ldap_extended_operation\n" );
  94. assert( ld != NULL );
  95. assert( LDAP_VALID( ld ) );
  96. assert( reqoid != NULL && *reqoid != '\0' );
  97. assert( msgidp != NULL );
  98. /* must be version 3 (or greater) */
  99. if ( ld->ld_version < LDAP_VERSION3 ) {
  100. ld->ld_errno = LDAP_NOT_SUPPORTED;
  101. return( ld->ld_errno );
  102. }
  103. ber = ldap_build_extended_req( ld, reqoid, reqdata,
  104. sctrls, cctrls, &id );
  105. if ( !ber )
  106. return( ld->ld_errno );
  107. /* send the message */
  108. *msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber, id );
  109. return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
  110. }
  111. int
  112. ldap_extended_operation_s(
  113. LDAP *ld,
  114. LDAP_CONST char *reqoid,
  115. struct berval *reqdata,
  116. LDAPControl **sctrls,
  117. LDAPControl **cctrls,
  118. char **retoidp,
  119. struct berval **retdatap )
  120. {
  121. int rc;
  122. int msgid;
  123. LDAPMessage *res;
  124. Debug0( LDAP_DEBUG_TRACE, "ldap_extended_operation_s\n" );
  125. assert( ld != NULL );
  126. assert( LDAP_VALID( ld ) );
  127. assert( reqoid != NULL && *reqoid != '\0' );
  128. rc = ldap_extended_operation( ld, reqoid, reqdata,
  129. sctrls, cctrls, &msgid );
  130. if ( rc != LDAP_SUCCESS ) {
  131. return( rc );
  132. }
  133. if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) {
  134. return( ld->ld_errno );
  135. }
  136. if ( retoidp != NULL ) *retoidp = NULL;
  137. if ( retdatap != NULL ) *retdatap = NULL;
  138. rc = ldap_parse_extended_result( ld, res, retoidp, retdatap, 0 );
  139. if( rc != LDAP_SUCCESS ) {
  140. ldap_msgfree( res );
  141. return rc;
  142. }
  143. return( ldap_result2error( ld, res, 1 ) );
  144. }
  145. /* Parse an extended result */
  146. int
  147. ldap_parse_extended_result (
  148. LDAP *ld,
  149. LDAPMessage *res,
  150. char **retoidp,
  151. struct berval **retdatap,
  152. int freeit )
  153. {
  154. BerElement *ber;
  155. ber_tag_t rc;
  156. ber_tag_t tag;
  157. ber_len_t len;
  158. struct berval *resdata;
  159. ber_int_t errcode;
  160. char *resoid;
  161. assert( ld != NULL );
  162. assert( LDAP_VALID( ld ) );
  163. assert( res != NULL );
  164. Debug0( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n" );
  165. if( ld->ld_version < LDAP_VERSION3 ) {
  166. ld->ld_errno = LDAP_NOT_SUPPORTED;
  167. return ld->ld_errno;
  168. }
  169. if( res->lm_msgtype != LDAP_RES_EXTENDED ) {
  170. ld->ld_errno = LDAP_PARAM_ERROR;
  171. return ld->ld_errno;
  172. }
  173. if( retoidp != NULL ) *retoidp = NULL;
  174. if( retdatap != NULL ) *retdatap = NULL;
  175. if ( ld->ld_error ) {
  176. LDAP_FREE( ld->ld_error );
  177. ld->ld_error = NULL;
  178. }
  179. if ( ld->ld_matched ) {
  180. LDAP_FREE( ld->ld_matched );
  181. ld->ld_matched = NULL;
  182. }
  183. ber = ber_dup( res->lm_ber );
  184. if ( ber == NULL ) {
  185. ld->ld_errno = LDAP_NO_MEMORY;
  186. return ld->ld_errno;
  187. }
  188. rc = ber_scanf( ber, "{eAA" /*}*/, &errcode,
  189. &ld->ld_matched, &ld->ld_error );
  190. if( rc == LBER_ERROR ) {
  191. ld->ld_errno = LDAP_DECODING_ERROR;
  192. ber_free( ber, 0 );
  193. return ld->ld_errno;
  194. }
  195. resoid = NULL;
  196. resdata = NULL;
  197. tag = ber_peek_tag( ber, &len );
  198. if( tag == LDAP_TAG_REFERRAL ) {
  199. /* skip over referral */
  200. if( ber_scanf( ber, "x" ) == LBER_ERROR ) {
  201. ld->ld_errno = LDAP_DECODING_ERROR;
  202. ber_free( ber, 0 );
  203. return ld->ld_errno;
  204. }
  205. tag = ber_peek_tag( ber, &len );
  206. }
  207. if( tag == LDAP_TAG_EXOP_RES_OID ) {
  208. /* we have a resoid */
  209. if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
  210. ld->ld_errno = LDAP_DECODING_ERROR;
  211. ber_free( ber, 0 );
  212. return ld->ld_errno;
  213. }
  214. assert( resoid[ 0 ] != '\0' );
  215. tag = ber_peek_tag( ber, &len );
  216. }
  217. if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
  218. /* we have a resdata */
  219. if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
  220. ld->ld_errno = LDAP_DECODING_ERROR;
  221. ber_free( ber, 0 );
  222. if( resoid != NULL ) LDAP_FREE( resoid );
  223. return ld->ld_errno;
  224. }
  225. }
  226. ber_free( ber, 0 );
  227. if( retoidp != NULL ) {
  228. *retoidp = resoid;
  229. } else {
  230. LDAP_FREE( resoid );
  231. }
  232. if( retdatap != NULL ) {
  233. *retdatap = resdata;
  234. } else {
  235. ber_bvfree( resdata );
  236. }
  237. ld->ld_errno = errcode;
  238. if( freeit ) {
  239. ldap_msgfree( res );
  240. }
  241. return LDAP_SUCCESS;
  242. }
  243. /* Parse an extended partial */
  244. int
  245. ldap_parse_intermediate (
  246. LDAP *ld,
  247. LDAPMessage *res,
  248. char **retoidp,
  249. struct berval **retdatap,
  250. LDAPControl ***serverctrls,
  251. int freeit )
  252. {
  253. BerElement *ber;
  254. ber_tag_t tag;
  255. ber_len_t len;
  256. struct berval *resdata;
  257. char *resoid;
  258. assert( ld != NULL );
  259. assert( LDAP_VALID( ld ) );
  260. assert( res != NULL );
  261. Debug0( LDAP_DEBUG_TRACE, "ldap_parse_intermediate\n" );
  262. if( ld->ld_version < LDAP_VERSION3 ) {
  263. ld->ld_errno = LDAP_NOT_SUPPORTED;
  264. return ld->ld_errno;
  265. }
  266. if( res->lm_msgtype != LDAP_RES_INTERMEDIATE ) {
  267. ld->ld_errno = LDAP_PARAM_ERROR;
  268. return ld->ld_errno;
  269. }
  270. if( retoidp != NULL ) *retoidp = NULL;
  271. if( retdatap != NULL ) *retdatap = NULL;
  272. if( serverctrls != NULL ) *serverctrls = NULL;
  273. ber = ber_dup( res->lm_ber );
  274. if ( ber == NULL ) {
  275. ld->ld_errno = LDAP_NO_MEMORY;
  276. return ld->ld_errno;
  277. }
  278. tag = ber_scanf( ber, "{" /*}*/ );
  279. if( tag == LBER_ERROR ) {
  280. ld->ld_errno = LDAP_DECODING_ERROR;
  281. ber_free( ber, 0 );
  282. return ld->ld_errno;
  283. }
  284. resoid = NULL;
  285. resdata = NULL;
  286. tag = ber_peek_tag( ber, &len );
  287. /*
  288. * NOTE: accept intermediate and extended response tag values
  289. * as older versions of slapd(8) incorrectly used extended
  290. * response tags.
  291. * Should be removed when 2.2 is moved to Historic.
  292. */
  293. if( tag == LDAP_TAG_IM_RES_OID || tag == LDAP_TAG_EXOP_RES_OID ) {
  294. /* we have a resoid */
  295. if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
  296. ld->ld_errno = LDAP_DECODING_ERROR;
  297. ber_free( ber, 0 );
  298. return ld->ld_errno;
  299. }
  300. assert( resoid[ 0 ] != '\0' );
  301. tag = ber_peek_tag( ber, &len );
  302. }
  303. if( tag == LDAP_TAG_IM_RES_VALUE || tag == LDAP_TAG_EXOP_RES_VALUE ) {
  304. /* we have a resdata */
  305. if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
  306. ld->ld_errno = LDAP_DECODING_ERROR;
  307. ber_free( ber, 0 );
  308. if( resoid != NULL ) LDAP_FREE( resoid );
  309. return ld->ld_errno;
  310. }
  311. }
  312. if ( serverctrls == NULL ) {
  313. ld->ld_errno = LDAP_SUCCESS;
  314. goto free_and_return;
  315. }
  316. if ( ber_scanf( ber, /*{*/ "}" ) == LBER_ERROR ) {
  317. ld->ld_errno = LDAP_DECODING_ERROR;
  318. goto free_and_return;
  319. }
  320. ld->ld_errno = ldap_pvt_get_controls( ber, serverctrls );
  321. free_and_return:
  322. ber_free( ber, 0 );
  323. if( retoidp != NULL ) {
  324. *retoidp = resoid;
  325. } else {
  326. LDAP_FREE( resoid );
  327. }
  328. if( retdatap != NULL ) {
  329. *retdatap = resdata;
  330. } else {
  331. ber_bvfree( resdata );
  332. }
  333. if( freeit ) {
  334. ldap_msgfree( res );
  335. }
  336. return ld->ld_errno;
  337. }