ptbind.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. /*
  13. * ptbind.c - LDAP bind-related code for Pass Through Authentication
  14. *
  15. */
  16. #include "passthru.h"
  17. static int
  18. passthru_simple_bind_once_s( PassThruServer *srvr, const char *dn,
  19. struct berval *creds, LDAPControl **reqctrls, int *lderrnop,
  20. char **matcheddnp, char **errmsgp, struct berval ***refurlsp,
  21. LDAPControl ***resctrlsp );
  22. /*
  23. * Attempt to chain a bind request off to "srvr." We return an LDAP error
  24. * code that indicates whether we successfully got a response from the
  25. * other server or not. If we succeed, we return LDAP_SUCCESS and *lderrnop
  26. * is set to the result code from the remote server.
  27. *
  28. * Note that in the face of "ldap server down" or "ldap connect failed" errors
  29. * we make up to "tries" attempts to bind to the remote server. Since we
  30. * are only interested in recovering silently when the remote server is up
  31. * but decided to close our connection, we retry without pausing between
  32. * attempts.
  33. */
  34. int
  35. passthru_simple_bind_s( Slapi_PBlock *pb, PassThruServer *srvr, int tries,
  36. const char *dn, struct berval *creds, LDAPControl **reqctrls, int *lderrnop,
  37. char **matcheddnp, char **errmsgp, struct berval ***refurlsp,
  38. LDAPControl ***resctrlsp )
  39. {
  40. int rc;
  41. PASSTHRU_ASSERT( srvr != NULL );
  42. PASSTHRU_ASSERT( tries > 0 );
  43. PASSTHRU_ASSERT( creds != NULL );
  44. PASSTHRU_ASSERT( lderrnop != NULL );
  45. PASSTHRU_ASSERT( refurlsp != NULL );
  46. do {
  47. /*
  48. * check to see if operation has been abandoned...
  49. */
  50. if ( slapi_op_abandoned( pb )) {
  51. slapi_log_error(SLAPI_LOG_PLUGIN, PASSTHRU_PLUGIN_SUBSYSTEM,
  52. "operation abandoned\n" );
  53. rc = LDAP_USER_CANCELLED;
  54. } else {
  55. rc = passthru_simple_bind_once_s( srvr, dn, creds, reqctrls,
  56. lderrnop, matcheddnp, errmsgp, refurlsp, resctrlsp );
  57. }
  58. } while ( PASSTHRU_LDAP_CONN_ERROR( rc ) && --tries > 0 );
  59. return( rc );
  60. }
  61. /*
  62. * like passthru_simple_bind_s() but only makes one attempt.
  63. */
  64. static int
  65. passthru_simple_bind_once_s( PassThruServer *srvr, const char *dn,
  66. struct berval *creds, LDAPControl **reqctrls, int *lderrnop,
  67. char **matcheddnp, char **errmsgp, struct berval ***refurlsp,
  68. LDAPControl ***resctrlsp )
  69. {
  70. int rc, msgid;
  71. char **referrals;
  72. struct timeval tv, *timeout;
  73. LDAPMessage *result;
  74. LDAP *ld;
  75. /*
  76. * Grab an LDAP connection to use for this bind.
  77. */
  78. ld = NULL;
  79. if (( rc = passthru_get_connection( srvr, &ld )) != LDAP_SUCCESS ) {
  80. goto release_and_return;
  81. }
  82. /*
  83. * Send the bind operation (need to retry on LDAP_SERVER_DOWN)
  84. */
  85. if (( rc = ldap_sasl_bind( ld, dn, LDAP_SASL_SIMPLE, creds, reqctrls,
  86. NULL, &msgid )) != LDAP_SUCCESS ) {
  87. goto release_and_return;
  88. }
  89. /*
  90. * determine timeout value (how long we will wait for a response)
  91. * if timeout is NULL or zero'd, we wait indefinitely.
  92. */
  93. if ( srvr->ptsrvr_timeout == NULL || ( srvr->ptsrvr_timeout->tv_sec == 0
  94. && srvr->ptsrvr_timeout->tv_usec == 0 )) {
  95. timeout = NULL;
  96. } else {
  97. tv = *srvr->ptsrvr_timeout; /* struct copy */
  98. timeout = &tv;
  99. }
  100. /*
  101. * Wait for a result.
  102. */
  103. rc = ldap_result( ld, msgid, 1, timeout, &result );
  104. /*
  105. * Interpret the result.
  106. */
  107. if ( rc == 0 ) { /* timeout */
  108. /*
  109. * Timed out waiting for a reply from the server.
  110. */
  111. rc = LDAP_TIMEOUT;
  112. } else if ( rc < 0 ) {
  113. /*
  114. * Some other error occurred (no result received).
  115. */
  116. rc = slapi_ldap_get_lderrno( ld, matcheddnp, errmsgp );
  117. } else {
  118. /*
  119. * Got a result from remote server -- parse it.
  120. */
  121. rc = ldap_parse_result( ld, result, lderrnop, matcheddnp, errmsgp,
  122. &referrals, resctrlsp, 1 );
  123. if ( referrals != NULL ) {
  124. *refurlsp = passthru_strs2bervals( referrals );
  125. slapi_ldap_value_free( referrals );
  126. }
  127. }
  128. release_and_return:
  129. if ( ld != NULL ) {
  130. passthru_release_connection( srvr, ld, PASSTHRU_LDAP_CONN_ERROR( rc ));
  131. }
  132. return( rc );
  133. }