In order to support other bind methods, introduce a generic bind callback.
When smbldap_state.bind_callback is set, it means there is an alternative
way to perform LDAP bind to ldap_simple_bind_s() so call it instead.
The call is wrapped in become_root()/unbecome_root() to allow proper permissions
in smbd to access needed resources in the callback, for example, credential caches.
When run outside smbd, become_root()/unbecome_root() are no-op.
The API expectation is similar to ldap_simple_bind_s().
A caller of smbldap API can pass additional information to the callback by setting
smbldap_state.bind_callback_data pointer.
Both callback and the data pointer elements of smbldap_state structure get
cleaned up if someone sets proper credentials on smbldap_state with
smbldap_set_creds() so if you are interested in using smbldap_state.bind_dn
with the callback, make sure to set callback after credentials are set.
bool anonymous;
char *bind_dn;
char *bind_secret;
bool anonymous;
char *bind_dn;
char *bind_secret;
+ int (*bind_callback)(LDAP *ldap_struct, struct smbldap_state *ldap_state, void *data);
+ void *bind_callback_data;
#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
#endif
#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
#endif
- rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
+ /* When there is an alternative bind callback is set,
+ attempt to use it to perform the bind */
+ if (ldap_state->bind_callback != NULL) {
+ /* We have to allow bind callback to be run under become_root/unbecome_root
+ to make sure within smbd the callback has proper write access to its resources,
+ like credential cache. This is similar to passdb case where this callback is supposed
+ to be used. When used outside smbd, become_root()/unbecome_root() are no-op.
+ */
+ become_root();
+ rc = ldap_state->bind_callback(ldap_struct, ldap_state, ldap_state->bind_callback_data);
+ unbecome_root();
+ } else {
+ rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
+ }
if (rc != LDAP_SUCCESS) {
char *ld_error = NULL;
if (rc != LDAP_SUCCESS) {
char *ld_error = NULL;
SAFE_FREE((*ldap_state)->bind_dn);
SAFE_FREE((*ldap_state)->bind_secret);
SAFE_FREE((*ldap_state)->bind_dn);
SAFE_FREE((*ldap_state)->bind_secret);
+ (*ldap_state)->bind_callback = NULL;
+ (*ldap_state)->bind_callback_data = NULL;
TALLOC_FREE(*ldap_state);
TALLOC_FREE(*ldap_state);
/* free any previously set credential */
SAFE_FREE(ldap_state->bind_dn);
/* free any previously set credential */
SAFE_FREE(ldap_state->bind_dn);
+ ldap_state->bind_callback = NULL;
+ ldap_state->bind_callback_data = NULL;
+
if (ldap_state->bind_secret) {
/* make sure secrets are zeroed out of memory */
memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));
if (ldap_state->bind_secret) {
/* make sure secrets are zeroed out of memory */
memset(ldap_state->bind_secret, '\0', strlen(ldap_state->bind_secret));