ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads) { const char *attrs[] = {"supportedSASLMechanisms", NULL}; char **values; ADS_STATUS status; int i, j; LDAPMessage *res; /* get a list of supported SASL mechanisms */ status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); if (!ADS_ERR_OK(status)) return status; values = ldap_get_values(ads->ld, res, "supportedSASLMechanisms"); /* try our supported mechanisms in order */ for (i=0;sasl_mechanisms[i].name;i++) { /* see if the server supports it */ for (j=0;values && values[j];j++) { if (strcmp(values[j], sasl_mechanisms[i].name) == 0) { DEBUG(4,("Found SASL mechanism %s\n", values[j])); status = sasl_mechanisms[i].fn(ads); ldap_value_free(values); ldap_msgfree(res); return status; } } } ldap_value_free(values); ldap_msgfree(res); return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED); }
ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads) { const char *attrs[] = {"supportedSASLMechanisms", NULL}; char **values; ADS_STATUS status; int i, j; LDAPMessage *res; struct ads_saslwrap *wrap = &ads->ldap_wrap_data; /* get a list of supported SASL mechanisms */ status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); if (!ADS_ERR_OK(status)) return status; values = ldap_get_values(ads->ldap.ld, res, "supportedSASLMechanisms"); if (ads->auth.flags & ADS_AUTH_SASL_SEAL) { wrap->wrap_type = ADS_SASLWRAP_TYPE_SEAL; } else if (ads->auth.flags & ADS_AUTH_SASL_SIGN) { wrap->wrap_type = ADS_SASLWRAP_TYPE_SIGN; } else { wrap->wrap_type = ADS_SASLWRAP_TYPE_PLAIN; } /* try our supported mechanisms in order */ for (i=0;sasl_mechanisms[i].name;i++) { /* see if the server supports it */ for (j=0;values && values[j];j++) { if (strcmp(values[j], sasl_mechanisms[i].name) == 0) { DEBUG(4,("Found SASL mechanism %s\n", values[j])); retry: status = sasl_mechanisms[i].fn(ads); if (status.error_type == ENUM_ADS_ERROR_LDAP && status.err.rc == LDAP_STRONG_AUTH_REQUIRED && wrap->wrap_type == ADS_SASLWRAP_TYPE_PLAIN) { DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED " "retrying with signing enabled\n")); wrap->wrap_type = ADS_SASLWRAP_TYPE_SIGN; goto retry; } ldap_value_free(values); ldap_msgfree(res); return status; } } } ldap_value_free(values); ldap_msgfree(res); return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED); }
ADS_STATUS cell_do_search(struct likewise_cell *c, const char *search_base, int scope, const char *expr, const char **attrs, LDAPMessage ** msg) { int search_count = 0; ADS_STATUS status; NTSTATUS nt_status; /* check for a NULL connection */ if (!c->conn) { nt_status = cell_connect(c); if (!NT_STATUS_IS_OK(nt_status)) { status = ADS_ERROR_NT(nt_status); return status; } } DEBUG(10, ("cell_do_search: Base = %s, Filter = %s, Scope = %d, GC = %s\n", search_base, expr, scope, c->conn->server.gc ? "yes" : "no")); /* we try multiple times in case the ADS_STRUCT is bad and we need to reconnect */ while (search_count < MAX_SEARCH_COUNT) { *msg = NULL; status = ads_do_search(c->conn, search_base, scope, expr, attrs, msg); if (ADS_ERR_OK(status)) { if (DEBUGLEVEL >= 10) { LDAPMessage *e = NULL; int n = ads_count_replies(c->conn, *msg); DEBUG(10,("cell_do_search: Located %d entries\n", n)); for (e=ads_first_entry(c->conn, *msg); e!=NULL; e = ads_next_entry(c->conn, e)) { char *dn = ads_get_dn(c->conn, talloc_tos(), e); DEBUGADD(10,(" dn: %s\n", dn ? dn : "<NULL>")); TALLOC_FREE(dn); } } return status; } DEBUG(5, ("cell_do_search: search[%d] failed (%s)\n", search_count, ads_errstr(status))); search_count++; /* Houston, we have a problem */ if (status.error_type == ENUM_ADS_ERROR_LDAP) { switch (status.err.rc) { case LDAP_TIMELIMIT_EXCEEDED: case LDAP_TIMEOUT: case -1: /* we get this error if we cannot contact the LDAP server */ nt_status = cell_connect(c); if (!NT_STATUS_IS_OK(nt_status)) { status = ADS_ERROR_NT(nt_status); return status; } break; default: /* we're all done here */ return status; } } } DEBUG(5, ("cell_do_search: exceeded maximum search count!\n")); return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); }
/* a wrapper around ldap_search_s that retries depending on the error code this is supposed to catch dropped connections and auto-reconnect */ static ADS_STATUS ads_do_search_retry_internal(ADS_STRUCT *ads, const char *bind_path, int scope, const char *expr, const char **attrs, void *args, LDAPMessage **res) { ADS_STATUS status = ADS_SUCCESS; int count = 3; char *bp; *res = NULL; if (!ads->ldap.ld && time_mono(NULL) - ads->ldap.last_attempt < ADS_RECONNECT_TIME) { return ADS_ERROR(LDAP_SERVER_DOWN); } bp = SMB_STRDUP(bind_path); if (!bp) { return ADS_ERROR(LDAP_NO_MEMORY); } *res = NULL; /* when binding anonymously, we cannot use the paged search LDAP * control - Guenther */ if (ads->auth.flags & ADS_AUTH_ANON_BIND) { status = ads_do_search(ads, bp, scope, expr, attrs, res); } else { status = ads_do_search_all_args(ads, bp, scope, expr, attrs, args, res); } if (ADS_ERR_OK(status)) { DEBUG(5,("Search for %s in <%s> gave %d replies\n", expr, bp, ads_count_replies(ads, *res))); SAFE_FREE(bp); return status; } while (--count) { if (NT_STATUS_EQUAL(ads_ntstatus(status), NT_STATUS_IO_TIMEOUT) && ads->config.ldap_page_size >= 250) { int new_page_size = (ads->config.ldap_page_size / 2); DEBUG(1, ("Reducing LDAP page size from %d to %d due to IO_TIMEOUT\n", ads->config.ldap_page_size, new_page_size)); ads->config.ldap_page_size = new_page_size; } if (*res) ads_msgfree(ads, *res); *res = NULL; DEBUG(3,("Reopening ads connection to realm '%s' after error %s\n", ads->config.realm, ads_errstr(status))); ads_disconnect(ads); status = ads_connect(ads); if (!ADS_ERR_OK(status)) { DEBUG(1,("ads_search_retry: failed to reconnect (%s)\n", ads_errstr(status))); ads_destroy(&ads); SAFE_FREE(bp); return status; } *res = NULL; /* when binding anonymously, we cannot use the paged search LDAP * control - Guenther */ if (ads->auth.flags & ADS_AUTH_ANON_BIND) { status = ads_do_search(ads, bp, scope, expr, attrs, res); } else { status = ads_do_search_all_args(ads, bp, scope, expr, attrs, args, res); } if (ADS_ERR_OK(status)) { DEBUG(5,("Search for filter: %s, base: %s gave %d replies\n", expr, bp, ads_count_replies(ads, *res))); SAFE_FREE(bp); return status; } } SAFE_FREE(bp); if (!ADS_ERR_OK(status)) { DEBUG(1,("ads reopen failed after error %s\n", ads_errstr(status))); } return status; }