sasl_io.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2005 Red Hat, Inc.
  3. * All rights reserved.
  4. *
  5. * License: GPL (version 3 or any later version).
  6. * See LICENSE for details.
  7. * END COPYRIGHT BLOCK **/
  8. #ifdef HAVE_CONFIG_H
  9. # include <config.h>
  10. #endif
  11. #include "slap.h"
  12. #include "slapi-plugin.h"
  13. #include "fe.h"
  14. #include <sasl.h>
  15. #include <arpa/inet.h>
  16. #ifndef USE_OPENLDAP
  17. #include "mozldap.h"
  18. #if LDAP_VENDOR_VERSION > 604
  19. /* garbage to cause build to fail */
  20. MOZLDAP is newer than expected, if the ber structure has not changed
  21. (see ldap/server/slapd/mozldap.h), please bump the version number(604 -> new version)
  22. #endif
  23. #endif
  24. /*
  25. * I/O Shim Layer for SASL Encryption
  26. * The 'handle' is a pointer to a sasl_connection structure.
  27. */
  28. #define SASL_IO_BUFFER_SIZE 1024
  29. #define SASL_IO_BUFFER_NOT_ENCRYPTED -99
  30. #define SASL_IO_BUFFER_START_SIZE 7
  31. /*
  32. * SASL sends its encrypted PDU's with an embedded 4-byte length
  33. * at the beginning (in network byte order). We peek inside the
  34. * received data off the wire to find this length, and use it
  35. * to determine when we have read an entire SASL PDU.
  36. * So when we have that there is no need for the SASL layer
  37. * to do any fancy buffering with it, we always hand it
  38. * a full packet.
  39. */
  40. struct PRFilePrivate {
  41. char *decrypted_buffer;
  42. size_t decrypted_buffer_size;
  43. size_t decrypted_buffer_count;
  44. size_t decrypted_buffer_offset;
  45. char *encrypted_buffer;
  46. size_t encrypted_buffer_size;
  47. size_t encrypted_buffer_count;
  48. size_t encrypted_buffer_offset;
  49. Connection *conn; /* needed for connid and sasl_conn context */
  50. PRBool send_encrypted; /* can only send encrypted data after the first read -
  51. that is, we cannot send back an encrypted response
  52. to the bind request that established the sasl io */
  53. const char *send_buffer; /* encrypted buffer to send to client */
  54. unsigned int send_size; /* size of the encrypted buffer */
  55. unsigned int send_offset; /* number of bytes sent so far */
  56. };
  57. typedef PRFilePrivate sasl_io_private;
  58. static PRInt32 PR_CALLBACK
  59. sasl_io_recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
  60. PRIntervalTime timeout);
  61. static void
  62. debug_print_layers(PRFileDesc *fd)
  63. {
  64. #if 0
  65. PR_ASSERT(fd->higher == NULL); /* this is the topmost layer */
  66. while (fd) {
  67. PRSocketOptionData sod;
  68. PRInt32 err;
  69. LDAPDebug2Args( LDAP_DEBUG_CONNS,
  70. "debug_print_layers: fd %d sasl_io_recv = %p\n",
  71. PR_FileDesc2NativeHandle(fd), sasl_io_recv );
  72. LDAPDebug( LDAP_DEBUG_CONNS,
  73. "debug_print_layers: fd name %s type = %d recv = %p\n",
  74. PR_GetNameForIdentity(fd->identity),
  75. PR_GetDescType(fd),
  76. fd->methods->recv ? fd->methods->recv : NULL );
  77. sod.option = PR_SockOpt_Nonblocking;
  78. if (PR_FAILURE == PR_GetSocketOption(fd, &sod)) {
  79. err = PR_GetError();
  80. LDAPDebug2Args( LDAP_DEBUG_CONNS,
  81. "debug_print_layers: error getting nonblocking option: %d %s\n",
  82. err, slapd_pr_strerror(err) );
  83. } else {
  84. LDAPDebug1Arg( LDAP_DEBUG_CONNS,
  85. "debug_print_layers: non blocking %d\n", sod.value.non_blocking );
  86. }
  87. sod.option = PR_SockOpt_Reuseaddr;
  88. if (PR_FAILURE == PR_GetSocketOption(fd, &sod)) {
  89. err = PR_GetError();
  90. LDAPDebug2Args( LDAP_DEBUG_CONNS,
  91. "debug_print_layers: error getting reuseaddr option: %d %s\n",
  92. err, slapd_pr_strerror(err) );
  93. } else {
  94. LDAPDebug1Arg( LDAP_DEBUG_CONNS,
  95. "debug_print_layers: reuseaddr %d\n", sod.value.reuse_addr );
  96. }
  97. sod.option = PR_SockOpt_RecvBufferSize;
  98. if (PR_FAILURE == PR_GetSocketOption(fd, &sod)) {
  99. err = PR_GetError();
  100. LDAPDebug2Args( LDAP_DEBUG_CONNS,
  101. "debug_print_layers: error getting recvbuffer option: %d %s\n",
  102. err, slapd_pr_strerror(err) );
  103. } else {
  104. LDAPDebug1Arg( LDAP_DEBUG_CONNS,
  105. "debug_print_layers: recvbuffer %d\n", sod.value.recv_buffer_size );
  106. }
  107. fd = fd->lower;
  108. }
  109. #endif
  110. }
  111. static void
  112. sasl_io_init_buffers(sasl_io_private *sp)
  113. {
  114. sp->decrypted_buffer = slapi_ch_malloc(SASL_IO_BUFFER_SIZE);
  115. sp->decrypted_buffer_size = SASL_IO_BUFFER_SIZE;
  116. sp->encrypted_buffer = slapi_ch_malloc(SASL_IO_BUFFER_SIZE);
  117. sp->encrypted_buffer_size = SASL_IO_BUFFER_SIZE;
  118. }
  119. static void sasl_io_resize_encrypted_buffer(sasl_io_private *sp, size_t requested_size)
  120. {
  121. if (requested_size > sp->encrypted_buffer_size) {
  122. sp->encrypted_buffer = slapi_ch_realloc(sp->encrypted_buffer, requested_size);
  123. sp->encrypted_buffer_size = requested_size;
  124. }
  125. }
  126. static void sasl_io_resize_decrypted_buffer(sasl_io_private *sp, size_t requested_size)
  127. {
  128. if (requested_size > sp->decrypted_buffer_size) {
  129. sp->decrypted_buffer = slapi_ch_realloc(sp->decrypted_buffer, requested_size);
  130. sp->decrypted_buffer_size = requested_size;
  131. }
  132. }
  133. static int
  134. sasl_io_reading_packet(sasl_io_private *sp)
  135. {
  136. return (sp->encrypted_buffer_count > 0);
  137. }
  138. static int
  139. sasl_io_finished_packet(sasl_io_private *sp)
  140. {
  141. return (sp->encrypted_buffer_count && (sp->encrypted_buffer_offset == sp->encrypted_buffer_count) );
  142. }
  143. static const char* const sasl_LayerName = "SASL";
  144. static PRDescIdentity sasl_LayerID;
  145. static PRIOMethods sasl_IoMethods;
  146. static PRCallOnceType sasl_callOnce = {0,0};
  147. static sasl_io_private *
  148. sasl_get_io_private(PRFileDesc *fd)
  149. {
  150. sasl_io_private *sp;
  151. PR_ASSERT(fd != NULL);
  152. PR_ASSERT(fd->methods->file_type == PR_DESC_LAYERED);
  153. PR_ASSERT(fd->identity == sasl_LayerID);
  154. sp = (sasl_io_private *)fd->secret;
  155. return sp;
  156. }
  157. /*
  158. * return values:
  159. * 0 - connection was closed
  160. * 1 - success
  161. * -1 - error
  162. */
  163. static PRInt32
  164. sasl_io_start_packet(PRFileDesc *fd, PRIntn flags, PRIntervalTime timeout, PRInt32 *err)
  165. {
  166. unsigned char buffer[SASL_IO_BUFFER_START_SIZE];
  167. sasl_io_private *sp = sasl_get_io_private(fd);
  168. Connection *c = sp->conn;
  169. PRInt32 amount = sizeof(buffer);
  170. PRInt32 ret = 0;
  171. size_t packet_length = 0;
  172. size_t saslio_limit;
  173. *err = 0;
  174. debug_print_layers(fd);
  175. /* first we need the length bytes */
  176. ret = PR_Recv(fd->lower, buffer, amount, flags, timeout);
  177. LDAPDebug( LDAP_DEBUG_CONNS,
  178. "sasl_io_start_packet: read sasl packet length returned %d on connection %" NSPRIu64 "\n",
  179. ret, c->c_connid, 0 );
  180. if (ret <= 0) {
  181. *err = PR_GetError();
  182. if (ret == 0) {
  183. LDAPDebug1Arg( LDAP_DEBUG_CONNS,
  184. "sasl_io_start_packet: connection closed while reading sasl packet length on connection %" NSPRIu64 "\n",
  185. c->c_connid );
  186. } else {
  187. LDAPDebug( LDAP_DEBUG_CONNS,
  188. "sasl_io_start_packet: error reading sasl packet length on connection %" NSPRIu64 " %d:%s\n",
  189. c->c_connid, *err, slapd_pr_strerror(*err) );
  190. }
  191. return ret;
  192. }
  193. /*
  194. * Read the bytes and add them to sp->encrypted_buffer
  195. * - if offset < 7, tell caller we didn't read enough bytes yet
  196. * - if offset >= 7, decode the length and proceed.
  197. */
  198. if((ret + sp->encrypted_buffer_offset) > sp->encrypted_buffer_size){
  199. sasl_io_resize_encrypted_buffer(sp, ret + sp->encrypted_buffer_offset);
  200. }
  201. memcpy(sp->encrypted_buffer + sp->encrypted_buffer_offset, buffer, ret);
  202. sp->encrypted_buffer_offset += ret;
  203. if (sp->encrypted_buffer_offset < sizeof(buffer)) {
  204. LDAPDebug2Args( LDAP_DEBUG_CONNS,
  205. "sasl_io_start_packet: read only %d bytes of sasl packet "
  206. "length on connection %" NSPRIu64 "\n", ret, c->c_connid );
  207. #if defined(EWOULDBLOCK)
  208. errno = EWOULDBLOCK;
  209. #elif defined(EAGAIN)
  210. errno = EAGAIN;
  211. #endif
  212. PR_SetError(PR_WOULD_BLOCK_ERROR, errno);
  213. return PR_FAILURE;
  214. }
  215. /*
  216. * Check if an LDAP operation was sent unencrypted
  217. */
  218. if(!sp->send_encrypted && *sp->encrypted_buffer == LDAP_TAG_MESSAGE){
  219. struct berval bv;
  220. #ifdef USE_OPENLDAP
  221. BerElement *ber = NULL;
  222. struct berval tmp_bv;
  223. #else
  224. MozElement *ber = NULL;
  225. #endif
  226. ber_len_t maxbersize = config_get_maxbersize();
  227. ber_len_t ber_len = 0;
  228. ber_tag_t tag = 0;
  229. slapi_log_error( SLAPI_LOG_CONNS, "sasl_io_start_packet", "conn=%" NSPRIu64 " fd=%d "
  230. "Sent an LDAP message that was not encrypted.\n", c->c_connid,
  231. c->c_sd);
  232. /* Build a berval so we can get the length before reading in the entire packet */
  233. bv.bv_val = sp->encrypted_buffer;
  234. bv.bv_len = sp->encrypted_buffer_offset;
  235. if((ber_len = slapi_berval_get_msg_len(&bv, 0)) == -1){
  236. goto done;
  237. }
  238. /* Is the ldap operation too large? */
  239. if(ber_len > maxbersize){
  240. slapi_log_error( SLAPI_LOG_FATAL, "connection",
  241. "conn=%" NSPRIu64 " fd=%d Incoming BER Element was too long, max allowable "
  242. "is %" BERLEN_T " bytes. Change the nsslapd-maxbersize attribute in "
  243. "cn=config to increase.\n",
  244. c->c_connid, c->c_sd, maxbersize );
  245. PR_SetError(PR_IO_ERROR, 0);
  246. return PR_FAILURE;
  247. }
  248. /*
  249. * Bump the ber length by 2 for the tag/length we skipped over when calculating the berval length.
  250. * We now have the total "packet" size, so we know exactly what is left to read in.
  251. */
  252. ber_len += 2;
  253. /*
  254. * Read in the rest of the packet.
  255. *
  256. * sp->encrypted_buffer_offset is the total number of bytes that have been written
  257. * to the buffer. Once we have the complete LDAP packet we'll set it back to zero,
  258. * and adjust the sp->encrypted_buffer_count.
  259. */
  260. while(sp->encrypted_buffer_offset < ber_len){
  261. unsigned char mybuf[SASL_IO_BUFFER_SIZE];
  262. ret = PR_Recv(fd->lower, mybuf, SASL_IO_BUFFER_SIZE, flags, timeout);
  263. if (ret == PR_WOULD_BLOCK_ERROR || (ret == 0 && sp->encrypted_buffer_offset < ber_len)){
  264. /*
  265. * Need more data, go back and try to get more data from connection_read_operation()
  266. * We can return and continue to update sp->encrypted_buffer because we have
  267. * maintained the current size in encrypted_buffer_offset.
  268. */
  269. #if defined(EWOULDBLOCK)
  270. errno = EWOULDBLOCK;
  271. #elif defined(EAGAIN)
  272. errno = EAGAIN;
  273. #endif
  274. PR_SetError(PR_WOULD_BLOCK_ERROR, errno);
  275. return PR_FAILURE;
  276. } else if (ret > 0) {
  277. LDAPDebug( LDAP_DEBUG_CONNS,
  278. "Continued: read sasl packet length returned %d on connection %" NSPRIu64 "\n",
  279. ret, c->c_connid, 0 );
  280. if((ret + sp->encrypted_buffer_offset) > sp->encrypted_buffer_size){
  281. sasl_io_resize_encrypted_buffer(sp, ret + sp->encrypted_buffer_offset);
  282. }
  283. memcpy(sp->encrypted_buffer + sp->encrypted_buffer_offset, mybuf, ret );
  284. sp->encrypted_buffer_offset += ret;
  285. } else if (ret < 0){
  286. *err = PR_GetError();
  287. LDAPDebug( LDAP_DEBUG_CONNS, "sasl_io_start_packet: error reading sasl packet length on connection "
  288. "%" NSPRIu64 " %d:%s\n", c->c_connid, *err, slapd_pr_strerror(*err) );
  289. return ret;
  290. }
  291. }
  292. /*
  293. * Reset the berval with the updated buffer, and create the berElement
  294. */
  295. bv.bv_val = sp->encrypted_buffer;
  296. bv.bv_len = sp->encrypted_buffer_offset;
  297. #ifdef USE_OPENLDAP
  298. if ( (ber = ber_init(&bv)) == NULL){
  299. #else
  300. if ( (ber = (MozElement *)ber_init(&bv)) == NULL){
  301. #endif
  302. goto done;
  303. }
  304. /*
  305. * Start parsing the berElement. First skip this tag, and move on to the
  306. * tag msgid
  307. */
  308. #ifdef USE_OPENLDAP
  309. ber_skip_tag(ber, &ber_len);
  310. if( ber_peek_tag( ber, &ber_len ) == LDAP_TAG_MSGID) {
  311. #else
  312. ber_skip_tag((BerElement*)ber, &ber_len);
  313. if( ber_peek_tag( (BerElement*)ber, &ber_len ) == LDAP_TAG_MSGID) {
  314. #endif
  315. /*
  316. * Skip the entire msgid element, so we can get to the LDAP op tag
  317. */
  318. #ifdef USE_OPENLDAP
  319. if(ber_skip_element(ber, &tmp_bv) == LDAP_TAG_MSGID) {
  320. /*
  321. * We only allow unbind operations to be processed for unencrypted operations
  322. */
  323. if (( tag = ber_peek_tag( ber, &ber_len )) == LDAP_REQ_UNBIND ) {
  324. #else
  325. {
  326. tag = *ber->ber_ptr++;
  327. if (*ber->ber_ptr == LDAP_REQ_UNBIND){
  328. #endif
  329. slapi_log_error( SLAPI_LOG_CONNS, "sasl_io_start_packet", "conn=%" NSPRIu64 " fd=%d "
  330. "Received unencrypted UNBIND operation.\n", c->c_connid,
  331. c->c_sd);
  332. sp->encrypted_buffer_count = sp->encrypted_buffer_offset;
  333. sp->encrypted_buffer_offset = 0;
  334. ber_free(ber, 1);
  335. return SASL_IO_BUFFER_NOT_ENCRYPTED;
  336. }
  337. slapi_log_error( SLAPI_LOG_CONNS, "sasl_io_start_packet", "conn=%" NSPRIu64 " fd=%d "
  338. "Error: received an LDAP message (tag 0x%lx) that was not encrypted.\n",
  339. #ifdef USE_OPENLDAP
  340. c->c_connid, c->c_sd, (long unsigned int)tag);
  341. #else
  342. c->c_connid, c->c_sd, (long unsigned int)*ber->ber_ptr);
  343. #endif
  344. }
  345. }
  346. done:
  347. /* If we got here we have garbage, or a denied LDAP operation */
  348. slapi_log_error( SLAPI_LOG_CONNS, "sasl_io_start_packet", "conn=%" NSPRIu64 " fd=%d "
  349. "Error: received an invalid message that was not encrypted.\n",
  350. c->c_connid, c->c_sd);
  351. if (NULL != ber){
  352. ber_free(ber, 1);
  353. }
  354. PR_SetError(PR_IO_ERROR, 0);
  355. return PR_FAILURE;
  356. }
  357. /* At this point, sp->encrypted_buffer_offset == sizeof(buffer) */
  358. /* Decode the length */
  359. packet_length = ntohl(*(uint32_t *)sp->encrypted_buffer);
  360. /* add length itself (for Cyrus SASL library) */
  361. packet_length += sizeof(uint32_t);
  362. LDAPDebug2Args( LDAP_DEBUG_CONNS,
  363. "read sasl packet length %ld on connection %" NSPRIu64 "\n",
  364. packet_length, c->c_connid );
  365. /* Check if the packet length is larger than our max allowed. A
  366. * setting of -1 means that we allow any size SASL IO packet. */
  367. saslio_limit = config_get_maxsasliosize();
  368. if(((long)saslio_limit != -1) && (packet_length > saslio_limit)) {
  369. LDAPDebug2Args( LDAP_DEBUG_ANY,
  370. "SASL encrypted packet length exceeds maximum allowed limit (length=%ld, limit=%ld)."
  371. " Change the nsslapd-maxsasliosize attribute in cn=config to increase limit.\n",
  372. packet_length, config_get_maxsasliosize() );
  373. PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
  374. *err = PR_BUFFER_OVERFLOW_ERROR;
  375. return -1;
  376. }
  377. sasl_io_resize_encrypted_buffer(sp, packet_length);
  378. /* Cyrus SASL implementation expects to have the length at the first
  379. 4 bytes */
  380. sp->encrypted_buffer_count = packet_length;
  381. return 1;
  382. }
  383. static PRInt32
  384. sasl_io_read_packet(PRFileDesc *fd, PRIntn flags, PRIntervalTime timeout, PRInt32 *err)
  385. {
  386. PRInt32 ret = 0;
  387. sasl_io_private *sp = sasl_get_io_private(fd);
  388. Connection *c = sp->conn;
  389. size_t bytes_remaining_to_read = sp->encrypted_buffer_count - sp->encrypted_buffer_offset;
  390. LDAPDebug2Args( LDAP_DEBUG_CONNS,
  391. "sasl_io_read_packet: reading %d bytes for connection %" NSPRIu64 "\n",
  392. bytes_remaining_to_read,
  393. c->c_connid );
  394. ret = PR_Recv(fd->lower, sp->encrypted_buffer + sp->encrypted_buffer_offset, bytes_remaining_to_read, flags, timeout);
  395. if (ret <= 0) {
  396. *err = PR_GetError();
  397. if (ret == 0) {
  398. LDAPDebug1Arg( LDAP_DEBUG_CONNS,
  399. "sasl_io_read_packet: connection closed while reading sasl packet on connection %" NSPRIu64 "\n", c->c_connid );
  400. } else {
  401. LDAPDebug( LDAP_DEBUG_CONNS,
  402. "sasl_io_read_packet: error reading sasl packet on connection %" NSPRIu64 " %d:%s\n", c->c_connid, *err, slapd_pr_strerror(*err) );
  403. }
  404. return ret;
  405. }
  406. sp->encrypted_buffer_offset += ret;
  407. return ret;
  408. }
  409. static PRInt32 PR_CALLBACK
  410. sasl_io_recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
  411. PRIntervalTime timeout)
  412. {
  413. sasl_io_private *sp = sasl_get_io_private(fd);
  414. Connection *c = sp->conn;
  415. PRInt32 ret = 0;
  416. size_t bytes_in_buffer = 0;
  417. PRInt32 err = 0;
  418. /* Do we have decrypted data buffered from 'before' ? */
  419. bytes_in_buffer = sp->decrypted_buffer_count - sp->decrypted_buffer_offset;
  420. LDAPDebug( LDAP_DEBUG_CONNS,
  421. "sasl_io_recv for connection %" NSPRIu64 " len %d bytes_in_buffer %d\n", c->c_connid, len, bytes_in_buffer );
  422. LDAPDebug( LDAP_DEBUG_CONNS,
  423. "sasl_io_recv for connection %" NSPRIu64 " len %d encrypted buffer count %d\n", c->c_connid, len, sp->encrypted_buffer_count );
  424. if (0 == bytes_in_buffer) {
  425. /* If there wasn't buffered decrypted data, we need to get some... */
  426. if (!sasl_io_reading_packet(sp)) {
  427. /* First read the packet length and so on */
  428. ret = sasl_io_start_packet(fd, flags, timeout, &err);
  429. if (SASL_IO_BUFFER_NOT_ENCRYPTED == ret) {
  430. /*
  431. * Special case: we received unencrypted data that was actually
  432. * an unbind. Copy it to the buffer and return its length.
  433. */
  434. memcpy(buf, sp->encrypted_buffer, sp->encrypted_buffer_count);
  435. return sp->encrypted_buffer_count;
  436. }
  437. if (0 >= ret) {
  438. /* timeout, connection closed, or error */
  439. return ret;
  440. }
  441. }
  442. /* We now have the packet length
  443. * we now must read more data off the wire until we have the complete packet
  444. */
  445. ret = sasl_io_read_packet(fd, flags, timeout, &err);
  446. if (0 >= ret) {
  447. return ret; /* read packet will set pr error */
  448. }
  449. /* If we have not read the packet yet, we cannot return any decrypted data to the
  450. * caller - so just tell the caller we don't have enough data yet
  451. * this is equivalent to recv() returning EAGAIN on a non-blocking socket
  452. * the caller must handle this condition and poll() or similar to know
  453. * when more data arrives
  454. */
  455. if (!sasl_io_finished_packet(sp)) {
  456. LDAPDebug( LDAP_DEBUG_CONNS,
  457. "sasl_io_recv for connection %" NSPRIu64 " - not finished reading packet yet\n", c->c_connid, 0, 0 );
  458. #if defined(EWOULDBLOCK)
  459. errno = EWOULDBLOCK;
  460. #elif defined(EAGAIN)
  461. errno = EAGAIN;
  462. #endif
  463. PR_SetError(PR_WOULD_BLOCK_ERROR, errno);
  464. return PR_FAILURE;
  465. }
  466. /* We have the full encrypted buffer now - decrypt it */
  467. {
  468. const char *output_buffer = NULL;
  469. unsigned int output_length = 0;
  470. LDAPDebug1Arg( LDAP_DEBUG_CONNS,
  471. "sasl_io_recv finished reading packet for connection %" NSPRIu64 "\n", c->c_connid );
  472. /* Now decode it */
  473. ret = sasl_decode(c->c_sasl_conn,sp->encrypted_buffer,sp->encrypted_buffer_count,&output_buffer,&output_length);
  474. /* even if decode fails, need re-initialize the encrypted_buffer */
  475. sp->encrypted_buffer_offset = 0;
  476. sp->encrypted_buffer_count = 0;
  477. if (SASL_OK == ret) {
  478. LDAPDebug2Args( LDAP_DEBUG_CONNS,
  479. "sasl_io_recv decoded packet length %d for connection %" NSPRIu64 "\n", output_length, c->c_connid );
  480. if (output_length) {
  481. sasl_io_resize_decrypted_buffer(sp,output_length);
  482. memcpy(sp->decrypted_buffer,output_buffer,output_length);
  483. sp->decrypted_buffer_count = output_length;
  484. sp->decrypted_buffer_offset = 0;
  485. bytes_in_buffer = output_length;
  486. }
  487. } else {
  488. LDAPDebug1Arg( LDAP_DEBUG_ANY,
  489. "sasl_io_recv failed to decode packet for connection %" NSPRIu64 "\n", c->c_connid );
  490. PR_SetError(PR_IO_ERROR, 0);
  491. return PR_FAILURE;
  492. }
  493. }
  494. }
  495. /* Finally, return data from the buffer to the caller */
  496. {
  497. size_t bytes_to_return = sp->decrypted_buffer_count - sp->decrypted_buffer_offset;
  498. if (bytes_to_return > len) {
  499. bytes_to_return = len;
  500. }
  501. /* Copy data from the decrypted buffer starting at the offset */
  502. memcpy(buf, sp->decrypted_buffer + sp->decrypted_buffer_offset, bytes_to_return);
  503. if (bytes_in_buffer == bytes_to_return) {
  504. sp->decrypted_buffer_offset = 0;
  505. sp->decrypted_buffer_count = 0;
  506. LDAPDebug1Arg( LDAP_DEBUG_CONNS,
  507. "sasl_io_recv all decrypted data returned for connection %" NSPRIu64 "\n", c->c_connid );
  508. } else {
  509. sp->decrypted_buffer_offset += bytes_to_return;
  510. LDAPDebug( LDAP_DEBUG_CONNS,
  511. "sasl_io_recv returning %d bytes to caller %d bytes left to return for connection %" NSPRIu64 "\n",
  512. bytes_to_return,
  513. sp->decrypted_buffer_count - sp->decrypted_buffer_offset,
  514. c->c_connid );
  515. }
  516. ret = bytes_to_return;
  517. }
  518. if (ret > 0) {
  519. /* we actually read something - we can now send encrypted data */
  520. sp->send_encrypted = PR_TRUE;
  521. }
  522. return ret;
  523. }
  524. static void
  525. reset_send_info(sasl_io_private *sp)
  526. {
  527. sp->send_buffer = NULL;
  528. sp->send_size = 0;
  529. sp->send_offset = 0;
  530. }
  531. PRInt32
  532. sasl_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount,
  533. PRIntn flags, PRIntervalTime timeout)
  534. {
  535. PRInt32 ret = 0;
  536. sasl_io_private *sp = sasl_get_io_private(fd);
  537. Connection *c = sp->conn;
  538. LDAPDebug1Arg( LDAP_DEBUG_CONNS,
  539. "sasl_io_send writing %d bytes\n", amount );
  540. if (sp->send_encrypted) {
  541. /* Get SASL to encrypt the buffer */
  542. if (NULL == sp->send_buffer) {
  543. ret = sasl_encode(c->c_sasl_conn, buf, amount, &sp->send_buffer, &sp->send_size);
  544. if (ret != SASL_OK) {
  545. const char *saslerr = sasl_errdetail(c->c_sasl_conn);
  546. LDAPDebug2Args( LDAP_DEBUG_ANY,
  547. "sasl_io_send could not encode %d bytes - sasl error %s\n",
  548. amount, saslerr ? saslerr : "unknown" );
  549. reset_send_info(sp);
  550. PR_SetError(PR_IO_ERROR, 0);
  551. return PR_FAILURE;
  552. }
  553. LDAPDebug1Arg( LDAP_DEBUG_CONNS,
  554. "sasl_io_send encoded as %d bytes\n", sp->send_size );
  555. sp->send_offset = 0;
  556. } else if ((amount > 0) && (sp->send_offset >= sp->send_size)) {
  557. /* something went wrong - we sent too many bytes */
  558. LDAPDebug2Args( LDAP_DEBUG_ANY,
  559. "sasl_io_send - client requested to send %d bytes but we "
  560. "already sent %d bytes\n", amount, (sp->send_offset >= sp->send_size));
  561. reset_send_info(sp);
  562. PR_SetError(PR_BUFFER_OVERFLOW_ERROR, EMSGSIZE);
  563. return PR_FAILURE;
  564. }
  565. ret = PR_Send(fd->lower, sp->send_buffer + sp->send_offset,
  566. sp->send_size - sp->send_offset, flags, timeout);
  567. /* we need to return the amount of cleartext sent */
  568. if (ret == (sp->send_size - sp->send_offset)) {
  569. ret = amount; /* sent amount of data requested by caller */
  570. reset_send_info(sp); /* done with this buffer, ready for next buffer */
  571. } else if (ret > 0) { /* could not send the entire encrypted buffer - tell caller we're blocked */
  572. LDAPDebug2Args( LDAP_DEBUG_CONNS,
  573. "sasl_io_send error: only sent %d of %d encoded bytes\n", ret,
  574. (sp->send_size - sp->send_offset) );
  575. sp->send_offset += ret;
  576. ret = PR_FAILURE;
  577. #if defined(EWOULDBLOCK)
  578. errno = EWOULDBLOCK;
  579. #elif defined(EAGAIN)
  580. errno = EAGAIN;
  581. #endif
  582. PR_SetError(PR_WOULD_BLOCK_ERROR, errno);
  583. }
  584. /* else - ret is error - caller will handle */
  585. } else {
  586. ret = PR_Send(fd->lower, buf, amount, flags, timeout);
  587. }
  588. return ret;
  589. }
  590. /*
  591. * Need to handle cases where caller uses PR_Write instead of
  592. * PR_Send on the network socket
  593. */
  594. static PRInt32 PR_CALLBACK
  595. sasl_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount)
  596. {
  597. return sasl_io_send(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);
  598. }
  599. static PRStatus PR_CALLBACK
  600. sasl_pop_IO_layer(PRFileDesc* stack, int doclose)
  601. {
  602. PRFileDesc* layer = NULL;
  603. sasl_io_private *sp = NULL;
  604. PRStatus rv = 0;
  605. PRDescIdentity id = PR_TOP_IO_LAYER;
  606. /* see if stack has the sasl io layer */
  607. if (!sasl_LayerID || !stack) {
  608. LDAPDebug0Args( LDAP_DEBUG_CONNS,
  609. "sasl_pop_IO_layer: no SASL IO layer\n" );
  610. return PR_SUCCESS;
  611. }
  612. /* if we're not being called during PR_Close, then we just want to
  613. pop the sasl io layer if it is on the stack */
  614. if (!doclose) {
  615. id = sasl_LayerID;
  616. if (!PR_GetIdentitiesLayer(stack, id)) {
  617. LDAPDebug0Args( LDAP_DEBUG_CONNS,
  618. "sasl_pop_IO_layer: no SASL IO layer\n" );
  619. return PR_SUCCESS;
  620. }
  621. }
  622. /* remove the layer from the stack */
  623. layer = PR_PopIOLayer(stack, id);
  624. if (!layer) {
  625. LDAPDebug0Args( LDAP_DEBUG_CONNS,
  626. "sasl_pop_IO_layer: error - could not pop SASL IO layer\n" );
  627. return PR_FAILURE;
  628. }
  629. /* get our private data and clean it up */
  630. sp = sasl_get_io_private(layer);
  631. if (sp) {
  632. LDAPDebug0Args( LDAP_DEBUG_CONNS,
  633. "sasl_pop_IO_layer: removing SASL IO layer\n" );
  634. /* Free the buffers */
  635. slapi_ch_free_string(&sp->encrypted_buffer);
  636. slapi_ch_free_string(&sp->decrypted_buffer);
  637. slapi_ch_free((void**)&sp);
  638. }
  639. layer->secret = NULL;
  640. if (layer->dtor) {
  641. layer->dtor(layer);
  642. }
  643. if (doclose) {
  644. rv = stack->methods->close(stack);
  645. } else {
  646. rv = PR_SUCCESS;
  647. }
  648. return rv;
  649. }
  650. static PRStatus PR_CALLBACK
  651. closeLayer(PRFileDesc* stack)
  652. {
  653. PRStatus rv = 0;
  654. LDAPDebug0Args( LDAP_DEBUG_CONNS,
  655. "closeLayer: closing SASL IO layer\n" );
  656. rv = sasl_pop_IO_layer(stack, 1 /* do close */);
  657. if (PR_SUCCESS != rv) {
  658. LDAPDebug0Args( LDAP_DEBUG_CONNS,
  659. "closeLayer: error closing SASL IO layer\n" );
  660. return rv;
  661. }
  662. return rv;
  663. }
  664. static PRStatus PR_CALLBACK
  665. initialize(void)
  666. {
  667. sasl_LayerID = PR_GetUniqueIdentity(sasl_LayerName);
  668. if (PR_INVALID_IO_LAYER == sasl_LayerID) {
  669. return PR_FAILURE;
  670. } else {
  671. const PRIOMethods* defaults = PR_GetDefaultIOMethods();
  672. if (!defaults) {
  673. return PR_FAILURE;
  674. } else {
  675. memcpy(&sasl_IoMethods, defaults, sizeof(sasl_IoMethods));
  676. }
  677. }
  678. /* Customize methods: */
  679. sasl_IoMethods.recv = sasl_io_recv;
  680. sasl_IoMethods.send = sasl_io_send;
  681. sasl_IoMethods.close = closeLayer;
  682. sasl_IoMethods.write = sasl_io_write; /* some code uses PR_Write instead of PR_Send */
  683. return PR_SUCCESS;
  684. }
  685. /*
  686. * Push the SASL I/O layer on top of the current NSPR I/O layer of the prfd used
  687. * by the connection.
  688. * must be called with the connection lock (c_mutex) held or in a condition in which
  689. * no other threads are accessing conn->c_prfd
  690. */
  691. int
  692. sasl_io_enable(Connection *c, void *data /* UNUSED */)
  693. {
  694. PRStatus rv = PR_CallOnce(&sasl_callOnce, initialize);
  695. if (PR_SUCCESS == rv) {
  696. PRFileDesc* layer = NULL;
  697. sasl_io_private *sp = NULL;
  698. if ( c->c_flags & CONN_FLAG_CLOSING ) {
  699. slapi_log_error( SLAPI_LOG_FATAL, "sasl_io_enable",
  700. "Cannot enable SASL security on connection in CLOSING state\n");
  701. return PR_FAILURE;
  702. }
  703. layer = PR_CreateIOLayerStub(sasl_LayerID, &sasl_IoMethods);
  704. sp = (sasl_io_private*) slapi_ch_calloc(1, sizeof(sasl_io_private));
  705. sasl_io_init_buffers(sp);
  706. layer->secret = sp;
  707. sp->conn = c;
  708. rv = PR_PushIOLayer(c->c_prfd, PR_TOP_IO_LAYER, layer);
  709. if (rv) {
  710. LDAPDebug( LDAP_DEBUG_ANY,
  711. "sasl_io_enable: error enabling sasl io on connection %" NSPRIu64 " %d:%s\n", c->c_connid, rv, slapd_pr_strerror(rv) );
  712. } else {
  713. LDAPDebug( LDAP_DEBUG_CONNS,
  714. "sasl_io_enable: enabled sasl io on connection %" NSPRIu64 " \n", c->c_connid, 0, 0 );
  715. debug_print_layers(c->c_prfd);
  716. }
  717. }
  718. return (int)rv;
  719. }
  720. /*
  721. * Remove the SASL I/O layer from the top of the current NSPR I/O layer of the prfd used
  722. * by the connection. Must either be called within the connection lock, or be
  723. * called while the connection (c_prfd) is not being referenced by another thread.
  724. */
  725. int
  726. sasl_io_cleanup(Connection *c, void *data /* UNUSED */)
  727. {
  728. int ret = 0;
  729. LDAPDebug( LDAP_DEBUG_CONNS,
  730. "sasl_io_cleanup for connection %" NSPRIu64 "\n", c->c_connid, 0, 0 );
  731. ret = sasl_pop_IO_layer(c->c_prfd, 0 /* do not close */);
  732. c->c_sasl_ssf = 0;
  733. return ret;
  734. }