#include "includes.h"
#include "smbldap.h"
-
-#ifndef LDAP_OPT_SUCCESS
-#define LDAP_OPT_SUCCESS 0
-#endif
+#include "secrets.h"
+#include "../libcli/security/security.h"
/* Try not to hit the up or down server forever */
int max_len)
{
char **values;
+ size_t size = 0;
if ( !attribute )
return False;
return False;
}
- if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, False) == (size_t)-1) {
+ if (!convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, &size)) {
DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
attribute, values[0]));
ldap_value_free(values);
return result;
}
+ char * smbldap_talloc_first_attribute(LDAP *ldap_struct, LDAPMessage *entry,
+ const char *attribute,
+ TALLOC_CTX *mem_ctx)
+{
+ char **values;
+ char *result;
+ size_t converted_size;
+
+ if (attribute == NULL) {
+ return NULL;
+ }
+
+ values = ldap_get_values(ldap_struct, entry, attribute);
+
+ if (values == NULL) {
+ DEBUG(10, ("attribute %s does not exist\n", attribute));
+ return NULL;
+ }
+
+ if (!pull_utf8_talloc(mem_ctx, &result, values[0], &converted_size)) {
+ DEBUG(10, ("pull_utf8_talloc failed\n"));
+ ldap_value_free(values);
+ return NULL;
+ }
+
+ ldap_value_free(values);
+
+#ifdef DEBUG_PASSWORDS
+ DEBUG (100, ("smbldap_get_first_attribute: [%s] = [%s]\n",
+ attribute, result));
+#endif
+ return result;
+}
+
char * smbldap_talloc_smallest_attribute(LDAP *ldap_struct, LDAPMessage *entry,
const char *attribute,
TALLOC_CTX *mem_ctx)
manage memory used by the array, by each struct, and values
***********************************************************************/
- void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
+static void smbldap_set_mod_internal(LDAPMod *** modlist, int modop, const char *attribute, const char *value, const DATA_BLOB *blob)
{
LDAPMod **mods;
int i;
mods[i + 1] = NULL;
}
- if (value != NULL) {
+ if (blob && (modop & LDAP_MOD_BVALUES)) {
+ j = 0;
+ if (mods[i]->mod_bvalues != NULL) {
+ for (; mods[i]->mod_bvalues[j] != NULL; j++);
+ }
+ mods[i]->mod_bvalues = SMB_REALLOC_ARRAY(mods[i]->mod_bvalues, struct berval *, j + 2);
+
+ if (mods[i]->mod_bvalues == NULL) {
+ smb_panic("smbldap_set_mod: out of memory!");
+ /* notreached. */
+ }
+
+ mods[i]->mod_bvalues[j] = SMB_MALLOC_P(struct berval);
+ SMB_ASSERT(mods[i]->mod_bvalues[j] != NULL);
+
+ mods[i]->mod_bvalues[j]->bv_val = (char *)memdup(blob->data, blob->length);
+ SMB_ASSERT(mods[i]->mod_bvalues[j]->bv_val != NULL);
+ mods[i]->mod_bvalues[j]->bv_len = blob->length;
+
+ mods[i]->mod_bvalues[j + 1] = NULL;
+ } else if (value != NULL) {
char *utf8_value = NULL;
size_t converted_size;
*modlist = mods;
}
+ void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value)
+{
+ smbldap_set_mod_internal(modlist, modop, attribute, value, NULL);
+}
+
+ void smbldap_set_mod_blob(LDAPMod *** modlist, int modop, const char *attribute, const DATA_BLOB *value)
+{
+ smbldap_set_mod_internal(modlist, modop | LDAP_MOD_BVALUES, attribute, NULL, value);
+}
+
/**********************************************************************
Set attribute to newval in LDAP, regardless of what value the
attribute had in LDAP before.
*********************************************************************/
- void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
- LDAPMod ***mods,
- const char *attribute, const char *newval)
+static void smbldap_make_mod_internal(LDAP *ldap_struct, LDAPMessage *existing,
+ LDAPMod ***mods,
+ const char *attribute, int op,
+ const char *newval,
+ const DATA_BLOB *newblob)
{
char oldval[2048]; /* current largest allowed value is mungeddial */
bool existed;
+ DATA_BLOB oldblob = data_blob_null;
if (attribute == NULL) {
/* This can actually happen for ldapsam_compat where we for
}
if (existing != NULL) {
- existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
+ if (op & LDAP_MOD_BVALUES) {
+ existed = smbldap_talloc_single_blob(talloc_tos(), ldap_struct, existing, attribute, &oldblob);
+ } else {
+ existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
+ }
} else {
existed = False;
*oldval = '\0';
}
- /* all of our string attributes are case insensitive */
-
- if (existed && newval && (StrCaseCmp(oldval, newval) == 0)) {
+ if (existed) {
+ bool equal = false;
+ if (op & LDAP_MOD_BVALUES) {
+ equal = (newblob && (data_blob_cmp(&oldblob, newblob) == 0));
+ } else {
+ /* all of our string attributes are case insensitive */
+ equal = (newval && (StrCaseCmp(oldval, newval) == 0));
+ }
- /* Believe it or not, but LDAP will deny a delete and
- an add at the same time if the values are the
- same... */
- DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute));
- return;
- }
+ if (equal) {
+ /* Believe it or not, but LDAP will deny a delete and
+ an add at the same time if the values are the
+ same... */
+ DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute));
+ return;
+ }
- if (existed) {
/* There has been no value before, so don't delete it.
* Here's a possible race: We might end up with
* duplicate attributes */
* in Novell NDS. In NDS you have to first remove attribute and then
* you could add new value */
- DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
- smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
+ if (op & LDAP_MOD_BVALUES) {
+ DEBUG(10,("smbldap_make_mod: deleting attribute |%s| blob\n", attribute));
+ smbldap_set_mod_blob(mods, LDAP_MOD_DELETE, attribute, &oldblob);
+ } else {
+ DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval));
+ smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval);
+ }
}
/* Regardless of the real operation (add or modify)
we add the new value here. We rely on deleting
the old value, should it exist. */
- if ((newval != NULL) && (strlen(newval) > 0)) {
- DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval));
- smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
+ if (op & LDAP_MOD_BVALUES) {
+ if (newblob && newblob->length) {
+ DEBUG(10,("smbldap_make_mod: adding attribute |%s| blob\n", attribute));
+ smbldap_set_mod_blob(mods, LDAP_MOD_ADD, attribute, newblob);
+ }
+ } else {
+ if ((newval != NULL) && (strlen(newval) > 0)) {
+ DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval));
+ smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval);
+ }
}
}
+ void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
+ LDAPMod ***mods,
+ const char *attribute, const char *newval)
+{
+ smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
+ 0, newval, NULL);
+}
+
+ void smbldap_make_mod_blob(LDAP *ldap_struct, LDAPMessage *existing,
+ LDAPMod ***mods,
+ const char *attribute, const DATA_BLOB *newblob)
+{
+ smbldap_make_mod_internal(ldap_struct, existing, mods, attribute,
+ LDAP_MOD_BVALUES, NULL, newblob);
+}
+
/**********************************************************************
Some varients of the LDAP rebind code do not pass in the third 'arg'
pointer to a void*, so we try and work around it by assuming that the
setup a connection to the LDAP server based on a uri
*******************************************************************/
-int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
+static int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
{
int rc;
return rc;
}
- if (lp_ldap_ref_follow() != Auto) {
+ if (lp_ldap_follow_referral() != Auto) {
rc = ldap_set_option(*ldap_struct, LDAP_OPT_REFERRALS,
- lp_ldap_ref_follow() ? LDAP_OPT_ON : LDAP_OPT_OFF);
+ lp_ldap_follow_referral() ? LDAP_OPT_ON : LDAP_OPT_OFF);
if (rc != LDAP_SUCCESS)
DEBUG(0, ("Failed to set LDAP_OPT_REFERRALS: %s\n",
ldap_err2string(rc)));
version
*******************************************************************/
-int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
+static int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
{
int version;
int rc;
{
int rc = LDAP_SUCCESS;
int version;
+ int deref;
LDAP **ldap_struct = &ldap_state->ldap_struct;
rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
return rc;
}
+ /* Set alias dereferencing method */
+ deref = lp_ldap_deref();
+ if (deref != -1) {
+ if (ldap_set_option (*ldap_struct, LDAP_OPT_DEREF, &deref) != LDAP_OPT_SUCCESS) {
+ DEBUG(1,("smbldap_open_connection: Failed to set dereferencing method: %d\n", deref));
+ } else {
+ DEBUG(5,("Set dereferencing method: %d\n", deref));
+ }
+ }
+
DEBUG(2, ("smbldap_open_connection: connection opened\n"));
return rc;
}
int *methodp, int freeit, void *arg)
{
struct smbldap_state *ldap_state = arg;
+ struct timespec ts;
/** @TODO Should we be doing something to check what servers we rebind to?
Could we get a referral to a machine that we don't want to give our
*methodp = LDAP_AUTH_SIMPLE;
}
- GetTimeOfDay(&ldap_state->last_rebind);
+ clock_gettime_mono(&ts);
+ ldap_state->last_rebind = convert_timespec_to_timeval(ts);
return 0;
}
struct smbldap_state *ldap_state =
(struct smbldap_state *)arg;
int rc;
+ struct timespec ts;
int version;
DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
DEBUG(10,("rebindproc_connect_with_state: "
"setting last_rebind timestamp "
"(req: 0x%02x)\n", (unsigned int)request));
- GetTimeOfDay(&ldap_state->last_rebind);
+ clock_gettime_mono(&ts);
+ ldap_state->last_rebind = convert_timespec_to_timeval(ts);
break;
default:
ZERO_STRUCT(ldap_state->last_rebind);
static void smbldap_idle_fn(struct event_context *event_ctx,
struct timed_event *te,
- struct timeval now,
+ struct timeval now_abs,
void *private_data);
/**********************************************************************
bool reopen = False;
SMB_ASSERT(ldap_state);
- if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time(NULL))) {
+ if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time_mono(NULL))) {
#ifdef HAVE_UNIXSOCKET
struct sockaddr_un addr;
ldap_state->ldap_struct = NULL;
ldap_state->last_ping = (time_t)0;
} else {
- ldap_state->last_ping = time(NULL);
+ ldap_state->last_ping = time_mono(NULL);
}
}
}
- ldap_state->last_ping = time(NULL);
+ ldap_state->last_ping = time_mono(NULL);
ldap_state->pid = sys_getpid();
TALLOC_FREE(ldap_state->idle_event);
static int another_ldap_try(struct smbldap_state *ldap_state, int *rc,
int *attempts, time_t endtime)
{
- time_t now = time(NULL);
+ time_t now = time_mono(NULL);
int open_rc = LDAP_SERVER_DOWN;
if (*rc != LDAP_SERVER_DOWN)
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
char *utf8_filter;
- time_t endtime = time(NULL)+lp_ldap_timeout();
+ time_t endtime = time_mono(NULL)+lp_ldap_timeout();
struct timeval timeout;
size_t converted_size;
if (ldap_state->last_rebind.tv_sec > 0) {
struct timeval tval;
+ struct timespec ts;
int64_t tdiff = 0;
int sleep_time = 0;
- ZERO_STRUCT(tval);
- GetTimeOfDay(&tval);
+ clock_gettime_mono(&ts);
+ tval = convert_timespec_to_timeval(ts);
tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
tdiff /= 1000; /* Convert to milliseconds. */
* just a bit more kind to the server. VL. */
got_alarm = 0;
- CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
+ CatchSignal(SIGALRM, gotalarm_sig);
alarm(lp_ldap_timeout());
/* End setup timeout. */
TALLOC_FREE(utf8_filter);
/* Teardown timeout. */
- CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
+ CatchSignal(SIGALRM, SIG_IGN);
alarm(0);
if (got_alarm != 0)
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
char *utf8_dn;
- time_t endtime = time(NULL)+lp_ldap_timeout();
+ time_t endtime = time_mono(NULL)+lp_ldap_timeout();
size_t converted_size;
SMB_ASSERT(ldap_state);
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
char *utf8_dn;
- time_t endtime = time(NULL)+lp_ldap_timeout();
+ time_t endtime = time_mono(NULL)+lp_ldap_timeout();
size_t converted_size;
SMB_ASSERT(ldap_state);
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
char *utf8_dn;
- time_t endtime = time(NULL)+lp_ldap_timeout();
+ time_t endtime = time_mono(NULL)+lp_ldap_timeout();
size_t converted_size;
SMB_ASSERT(ldap_state);
{
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
- time_t endtime = time(NULL)+lp_ldap_timeout();
+ time_t endtime = time_mono(NULL)+lp_ldap_timeout();
if (!ldap_state)
return (-1);
static void smbldap_idle_fn(struct event_context *event_ctx,
struct timed_event *te,
- struct timeval now,
+ struct timeval now_abs,
void *private_data)
{
struct smbldap_state *state = (struct smbldap_state *)private_data;
return;
}
- if ((state->last_use+SMBLDAP_IDLE_TIME) > now.tv_sec) {
+ if ((state->last_use+SMBLDAP_IDLE_TIME) > time_mono(NULL)) {
DEBUG(10,("ldap connection not idle...\n"));
+ /* this needs to be made monotonic clock aware inside tevent: */
state->idle_event = event_add_timed(
event_ctx, NULL,
- timeval_add(&now, SMBLDAP_IDLE_TIME, 0),
+ timeval_add(&now_abs, SMBLDAP_IDLE_TIME, 0),
smbldap_idle_fn,
private_data);
return;