/*
- Unix SMB/CIFS mplementation.
+ Unix SMB/CIFS implementation.
LDAP protocol helper functions for SAMBA
Copyright (C) Jean François Micouleau 1998
Copyright (C) Gerald Carter 2001-2003
{ LDAP_ATTR_CN, "cn" },
{ LDAP_ATTR_DISPLAY_NAME, "displayName" },
{ LDAP_ATTR_HOME_PATH, "smbHome" },
- { LDAP_ATTR_HOME_DRIVE, "homeDrives" },
+ { LDAP_ATTR_HOME_DRIVE, "homeDrive" },
{ LDAP_ATTR_LOGON_SCRIPT, "scriptPath" },
{ LDAP_ATTR_PROFILE_PATH, "profilePath" },
{ LDAP_ATTR_DESC, "description" },
{ LDAP_ATTR_DOMAIN, "domain" },
{ LDAP_ATTR_OBJCLASS, "objectClass" },
{ LDAP_ATTR_ACB_INFO, "acctFlags" },
+ { LDAP_ATTR_MOD_TIMESTAMP, "modifyTimestamp" },
+ { LDAP_ATTR_LIST_END, NULL }
+};
+
+ATTRIB_MAP_ENTRY attrib_map_to_delete_v22[] = {
+ { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" },
+ { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" },
+ { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" },
+ { LDAP_ATTR_LOGON_TIME, "logonTime" },
+ { LDAP_ATTR_LOGOFF_TIME, "logoffTime" },
+ { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" },
+ { LDAP_ATTR_DISPLAY_NAME, "displayName" },
+ { LDAP_ATTR_HOME_PATH, "smbHome" },
+ { LDAP_ATTR_HOME_DRIVE, "homeDrives" },
+ { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" },
+ { LDAP_ATTR_PROFILE_PATH, "profilePath" },
+ { LDAP_ATTR_USER_WKS, "userWorkstations"},
+ { LDAP_ATTR_USER_RID, "rid" },
+ { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"},
+ { LDAP_ATTR_LMPW, "lmPassword" },
+ { LDAP_ATTR_NTPW, "ntPassword" },
+ { LDAP_ATTR_DOMAIN, "domain" },
+ { LDAP_ATTR_ACB_INFO, "acctFlags" },
{ LDAP_ATTR_LIST_END, NULL }
};
{ LDAP_ATTR_MUNGED_DIAL, "sambaMungedDial" },
{ LDAP_ATTR_BAD_PASSWORD_COUNT, "sambaBadPasswordCount" },
{ LDAP_ATTR_BAD_PASSWORD_TIME, "sambaBadPasswordTime" },
+ { LDAP_ATTR_PWD_HISTORY, "sambaPasswordHistory" },
+ { LDAP_ATTR_MOD_TIMESTAMP, "modifyTimestamp" },
+ { LDAP_ATTR_LOGON_HOURS, "sambaLogonHours" },
+ { LDAP_ATTR_LIST_END, NULL }
+};
+
+ATTRIB_MAP_ENTRY attrib_map_to_delete_v30[] = {
+ { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" },
+ { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" },
+ { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" },
+ { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" },
+ { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" },
+ { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" },
+ { LDAP_ATTR_HOME_DRIVE, "sambaHomeDrive" },
+ { LDAP_ATTR_HOME_PATH, "sambaHomePath" },
+ { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" },
+ { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" },
+ { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" },
+ { LDAP_ATTR_USER_SID, LDAP_ATTRIBUTE_SID },
+ { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" },
+ { LDAP_ATTR_LMPW, "sambaLMPassword" },
+ { LDAP_ATTR_NTPW, "sambaNTPassword" },
+ { LDAP_ATTR_DOMAIN, "sambaDomainName" },
+ { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" },
+ { LDAP_ATTR_MUNGED_DIAL, "sambaMungedDial" },
+ { LDAP_ATTR_BAD_PASSWORD_COUNT, "sambaBadPasswordCount" },
+ { LDAP_ATTR_BAD_PASSWORD_TIME, "sambaBadPasswordTime" },
+ { LDAP_ATTR_PWD_HISTORY, "sambaPasswordHistory" },
+ { LDAP_ATTR_LOGON_HOURS, "sambaLogonHours" },
{ LDAP_ATTR_LIST_END, NULL }
};
{ LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER},
{ LDAP_ATTR_GROUP_SID, LDAP_ATTRIBUTE_SID },
{ LDAP_ATTR_GROUP_TYPE, "sambaGroupType" },
+ { LDAP_ATTR_SID_LIST, "sambaSIDList" },
{ LDAP_ATTR_DESC, "description" },
{ LDAP_ATTR_DISPLAY_NAME, "displayName" },
{ LDAP_ATTR_CN, "cn" },
{ LDAP_ATTR_GROUP_TYPE, "sambaGroupType" },
{ LDAP_ATTR_DESC, "description" },
{ LDAP_ATTR_DISPLAY_NAME, "displayName" },
+ { LDAP_ATTR_SID_LIST, "sambaSIDList" },
{ LDAP_ATTR_LIST_END, NULL }
};
Return the list of attribute names from a mapping table
**********************************************************************/
- char** get_attr_list( ATTRIB_MAP_ENTRY table[] )
+ const char** get_attr_list( ATTRIB_MAP_ENTRY table[] )
{
- char **names;
+ const char **names;
int i = 0;
while ( table[i].attrib != LDAP_ATTR_LIST_END )
i++;
i++;
- names = (char**)malloc( sizeof(char*)*i );
+ names = SMB_MALLOC_ARRAY( const char*, i );
if ( !names ) {
DEBUG(0,("get_attr_list: out of memory\n"));
return NULL;
i = 0;
while ( table[i].attrib != LDAP_ATTR_LIST_END ) {
- names[i] = strdup( table[i].name );
+ names[i] = SMB_STRDUP( table[i].name );
i++;
}
names[i] = NULL;
Cleanup
********************************************************************/
- void free_attr_list( char **list )
+ void free_attr_list( const char **list )
{
int i = 0;
if (!size) {
/* Upgrade 2.2 style entry */
char *p;
- char* old_style_key = strdup(*dn);
+ char* old_style_key = SMB_STRDUP(*dn);
char *data;
fstring old_style_pw;
return False;
}
- if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len) == (size_t)-1) {
+ if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, False) == (size_t)-1) {
DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n",
attribute, values[0]));
ldap_value_free(values);
/* sanity checks on the mod values */
- if (attribute == NULL || *attribute == '\0')
+ if (attribute == NULL || *attribute == '\0') {
return;
+ }
+
#if 0 /* commented out after discussion with abartlet. Do not reenable.
left here so other so re-add similar code --jerry */
if (value == NULL || *value == '\0')
return;
#endif
- if (mods == NULL)
- {
- mods = (LDAPMod **) malloc(sizeof(LDAPMod *));
- if (mods == NULL)
- {
+ if (mods == NULL) {
+ mods = SMB_MALLOC_P(LDAPMod *);
+ if (mods == NULL) {
DEBUG(0, ("make_a_mod: out of memory!\n"));
return;
}
break;
}
- if (mods[i] == NULL)
- {
- mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *));
- if (mods == NULL)
- {
+ if (mods[i] == NULL) {
+ mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2);
+ if (mods == NULL) {
DEBUG(0, ("make_a_mod: out of memory!\n"));
return;
}
- mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod));
- if (mods[i] == NULL)
- {
+ mods[i] = SMB_MALLOC_P(LDAPMod);
+ if (mods[i] == NULL) {
DEBUG(0, ("make_a_mod: out of memory!\n"));
return;
}
mods[i]->mod_op = modop;
mods[i]->mod_values = NULL;
- mods[i]->mod_type = strdup(attribute);
+ mods[i]->mod_type = SMB_STRDUP(attribute);
mods[i + 1] = NULL;
}
- if (value != NULL)
- {
+ if (value != NULL) {
char *utf8_value = NULL;
j = 0;
if (mods[i]->mod_values != NULL) {
for (; mods[i]->mod_values[j] != NULL; j++);
}
- mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values,
- (j + 2) * sizeof (char *));
+ mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2);
if (mods[i]->mod_values == NULL) {
DEBUG (0, ("make_a_mod: Memory allocation failure!\n"));
char oldval[2048]; /* current largest allowed value is mungeddial */
BOOL existed;
+ if (attribute == NULL) {
+ /* This can actually happen for ldapsam_compat where we for
+ * example don't have a password history */
+ return;
+ }
+
if (existing != NULL) {
existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
} else {
return;
}
- t = smb_xmalloc(sizeof(*t));
+ t = SMB_XMALLOC_P(struct smbldap_state_lookup);
ZERO_STRUCTP(t);
DLIST_ADD_END(smbldap_state_lookup_list, t, tmp);
DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n",
ldap_state->bind_dn));
- *whop = strdup(ldap_state->bind_dn);
+ *whop = SMB_STRDUP(ldap_state->bind_dn);
if (!*whop) {
return LDAP_NO_MEMORY;
}
- *credp = strdup(ldap_state->bind_secret);
+ *credp = SMB_STRDUP(ldap_state->bind_secret);
if (!*credp) {
SAFE_FREE(*whop);
return LDAP_NO_MEMORY;
*methodp = LDAP_AUTH_SIMPLE;
}
- gettimeofday(&(ldap_state->last_rebind),NULL);
+ GetTimeOfDay(&ldap_state->last_rebind);
return 0;
}
rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret);
- gettimeofday(&(ldap_state->last_rebind),NULL);
+ GetTimeOfDay(&ldap_state->last_rebind);
return rc;
}
int rc;
char *ldap_dn;
char *ldap_secret;
+ int version;
/* get the password */
- if (!fetch_ldap_pw(&ldap_dn, &ldap_secret))
- {
+ if (!fetch_ldap_pw(&ldap_dn, &ldap_secret)) {
DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n"));
return LDAP_INVALID_CREDENTIALS;
}
ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
&ld_error);
DEBUG(ldap_state->num_failures ? 2 : 0,
- ("failed to bind to server with dn= %s Error: %s\n\t%s\n",
+ ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n",
+ ldap_state->uri,
ldap_dn ? ldap_dn : "(unknown)", ldap_err2string(rc),
ld_error ? ld_error : "(unknown)"));
SAFE_FREE(ld_error);
ldap_state->num_failures = 0;
+ ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
+
+ if (smbldap_has_control(ldap_state, ADS_PAGE_CTL_OID) && version == 3) {
+ ldap_state->paged_results = True;
+ }
+
DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n"));
+ DEBUGADD(3, ("ldap_connect_system: LDAP server %s support paged results\n", ldap_state->paged_results?"does":"does not"));
return rc;
}
/**********************************************************************
-Connect to LDAP server (called before every ldap operation)
+ Connect to LDAP server (called before every ldap operation)
*********************************************************************/
static int smbldap_open(struct smbldap_state *ldap_state)
{
- int rc;
- SMB_ASSERT(ldap_state);
+ int rc, opt_rc;
+ BOOL reopen = False;
+ SMB_ASSERT(ldap_state);
#ifndef NO_LDAP_SECURITY
if (geteuid() != 0) {
DEBUG(0, ("smbldap_open: cannot access LDAP when not root..\n"));
}
#endif
- 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(NULL))) {
+
struct sockaddr_un addr;
socklen_t len = sizeof(addr);
int sd;
- if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
- getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
+
+ opt_rc = ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd);
+ if (opt_rc == 0 && (getpeername(sd, (struct sockaddr *) &addr, &len)) < 0 )
+ reopen = True;
+
+#ifdef HAVE_UNIXSOCKET
+ if (opt_rc == 0 && addr.sun_family == AF_UNIX)
+ reopen = True;
+#endif
+ if (reopen) {
/* the other end has died. reopen. */
ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
ldap_state->ldap_struct = NULL;
ldap_state->last_ping = time(NULL);
- DEBUG(4,("The LDAP server is succesful connected\n"));
+ ldap_state->pid = sys_getpid();
+ DEBUG(4,("The LDAP server is succesfully connected\n"));
return LDAP_SUCCESS;
}
return NT_STATUS_OK;
}
-int smbldap_retry_open(struct smbldap_state *ldap_state, int *attempts)
+static BOOL got_alarm;
+
+static void (*old_handler)(int);
+
+static void gotalarm_sig(int dummy)
{
- int rc;
+ got_alarm = True;
+}
- SMB_ASSERT(ldap_state && attempts);
-
- if (*attempts != 0) {
- unsigned int sleep_time;
- uint8 rand_byte;
+static int another_ldap_try(struct smbldap_state *ldap_state, int *rc,
+ int *attempts, time_t endtime)
+{
+ time_t now = time(NULL);
+ int open_rc = LDAP_SERVER_DOWN;
- /* Sleep for a random timeout */
- rand_byte = (char)(sys_random());
+ if (*rc != LDAP_SERVER_DOWN)
+ goto no_next;
- sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2;
- /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds
- on average.
- */
- DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n",
- sleep_time));
- smb_msleep(sleep_time);
+ if (now >= endtime) {
+ smbldap_close(ldap_state);
+ *rc = LDAP_TIMEOUT;
+ goto no_next;
}
- (*attempts)++;
- if ((rc = smbldap_open(ldap_state))) {
- DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts));
- return rc;
- }
-
- return LDAP_SUCCESS;
-}
+ if (*attempts == 0) {
+ got_alarm = False;
+ old_handler = CatchSignal(SIGALRM, gotalarm_sig);
+ alarm(endtime - now);
+
+ if (ldap_state->pid != sys_getpid())
+ smbldap_close(ldap_state);
+ }
+ while (1) {
+
+ if (*attempts != 0)
+ smb_msleep(1000);
+
+ *attempts += 1;
+
+ open_rc = smbldap_open(ldap_state);
+
+ if (open_rc == LDAP_SUCCESS) {
+ ldap_state->last_use = now;
+ return True;
+ }
+
+ if (got_alarm) {
+ *rc = LDAP_TIMEOUT;
+ break;
+ }
+
+ if (open_rc != LDAP_SUCCESS) {
+ DEBUG(1, ("Connection to LDAP server failed for the "
+ "%d try!\n", *attempts));
+ }
+ }
+
+ no_next:
+ CatchSignal(SIGALRM, old_handler);
+ alarm(0);
+ ldap_state->last_use = now;
+ return False;
+}
/*********************************************************************
********************************************************************/
int smbldap_search(struct smbldap_state *ldap_state,
const char *base, int scope, const char *filter,
- char *attrs[], int attrsonly,
+ const char *attrs[], int attrsonly,
LDAPMessage **res)
{
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
char *utf8_filter;
+ time_t endtime = time(NULL)+lp_ldap_timeout();
SMB_ASSERT(ldap_state);
if (ldap_state->last_rebind.tv_sec > 0) {
struct timeval tval;
- int tdiff = 0;
+ SMB_BIG_INT tdiff = 0;
int sleep_time = 0;
ZERO_STRUCT(tval);
+ GetTimeOfDay(&tval);
- gettimeofday(&tval,NULL);
-
- tdiff = 1000000 *(tval.tv_sec - ldap_state->last_rebind.tv_sec) +
- (tval.tv_usec - ldap_state->last_rebind.tv_usec);
+ tdiff = usec_time_diff(&tval, &ldap_state->last_rebind);
+ tdiff /= 1000; /* Convert to milliseconds. */
- sleep_time = ((1000*lp_ldap_replication_sleep())-tdiff)/1000;
+ sleep_time = lp_ldap_replication_sleep()-(int)tdiff;
+ sleep_time = MIN(sleep_time, MAX_LDAP_REPLICATION_SLEEP_TIME);
if (sleep_time > 0) {
/* we wait for the LDAP replication */
DEBUG(5,("smbldap_search: waiting %d milliseconds for LDAP replication.\n",sleep_time));
smb_msleep(sleep_time);
DEBUG(5,("smbldap_search: go on!\n"));
- ZERO_STRUCT(ldap_state->last_rebind);
}
+ ZERO_STRUCT(ldap_state->last_rebind);
}
if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) {
return LDAP_NO_MEMORY;
}
- while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
-
- if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
- continue;
-
+ while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
rc = ldap_search_s(ldap_state->ldap_struct, base, scope,
- utf8_filter, attrs, attrsonly, res);
- }
+ utf8_filter,
+ CONST_DISCARD(char **, attrs),
+ attrsonly, res);
- if (rc == LDAP_SERVER_DOWN) {
- DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
- smbldap_close(ldap_state);
- }
-
- ldap_state->last_use = time(NULL);
-
SAFE_FREE(utf8_filter);
return rc;
}
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
char *utf8_dn;
+ time_t endtime = time(NULL)+lp_ldap_timeout();
SMB_ASSERT(ldap_state);
return LDAP_NO_MEMORY;
}
- while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
-
- if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
- continue;
-
+ while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
- }
-
- if (rc == LDAP_SERVER_DOWN) {
- DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
- smbldap_close(ldap_state);
- }
-
- ldap_state->last_use = time(NULL);
-
+
SAFE_FREE(utf8_dn);
return rc;
}
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
char *utf8_dn;
+ time_t endtime = time(NULL)+lp_ldap_timeout();
SMB_ASSERT(ldap_state);
return LDAP_NO_MEMORY;
}
- while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
-
- if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
- continue;
-
+ while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
- }
- if (rc == LDAP_SERVER_DOWN) {
- DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
- smbldap_close(ldap_state);
- }
-
- ldap_state->last_use = time(NULL);
-
SAFE_FREE(utf8_dn);
return rc;
}
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
char *utf8_dn;
+ time_t endtime = time(NULL)+lp_ldap_timeout();
SMB_ASSERT(ldap_state);
return LDAP_NO_MEMORY;
}
- while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
-
- if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
- continue;
-
+ while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
- }
- if (rc == LDAP_SERVER_DOWN) {
- DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
- smbldap_close(ldap_state);
- }
-
- ldap_state->last_use = time(NULL);
-
SAFE_FREE(utf8_dn);
return rc;
}
{
int rc = LDAP_SERVER_DOWN;
int attempts = 0;
+ time_t endtime = time(NULL)+lp_ldap_timeout();
if (!ldap_state)
return (-1);
- while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) {
-
- if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS)
- continue;
-
- rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata,
- serverctrls, clientctrls, retoidp, retdatap);
- }
-
- if (rc == LDAP_SERVER_DOWN) {
- DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO));
- smbldap_close(ldap_state);
- }
-
- ldap_state->last_use = time(NULL);
-
+ while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+ rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid,
+ reqdata, serverctrls,
+ clientctrls, retoidp, retdatap);
return rc;
}
run the search by name.
******************************************************************/
int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter,
- char **search_attr, LDAPMessage ** result)
+ const char **search_attr, LDAPMessage ** result)
{
int scope = LDAP_SCOPE_SUBTREE;
int rc;
NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char *location, struct smbldap_state **smbldap_state)
{
- *smbldap_state = talloc_zero(mem_ctx, sizeof(**smbldap_state));
+ *smbldap_state = TALLOC_ZERO_P(mem_ctx, struct smbldap_state);
if (!*smbldap_state) {
DEBUG(0, ("talloc() failed for ldapsam private_data!\n"));
return NT_STATUS_NO_MEMORY;
return NT_STATUS_OK;
}
+/**********************************************************************
+ Add the sambaDomain to LDAP, so we don't have to search for this stuff
+ again. This is a once-add operation for now.
+
+ TODO: Add other attributes, and allow modification.
+*********************************************************************/
+static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
+ const char *domain_name)
+{
+ fstring sid_string;
+ fstring algorithmic_rid_base_string;
+ pstring filter, dn;
+ LDAPMod **mods = NULL;
+ int rc;
+ int ldap_op;
+ LDAPMessage *result = NULL;
+ int num_result;
+ const char **attr_list;
+ uid_t u_low, u_high;
+ gid_t g_low, g_high;
+ uint32 rid_low, rid_high;
+
+ slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))",
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+ domain_name, LDAP_OBJ_DOMINFO);
+
+ attr_list = get_attr_list( dominfo_attr_list );
+ rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
+ free_attr_list( attr_list );
+
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ num_result = ldap_count_entries(ldap_state->ldap_struct, result);
+
+ if (num_result > 1) {
+ DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* Check if we need to add an entry */
+ DEBUG(3,("Adding new domain\n"));
+ ldap_op = LDAP_MOD_ADD;
+
+ pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+ domain_name, lp_ldap_suffix());
+
+ /* Free original search */
+ ldap_msgfree(result);
+
+ /* make the changes - the entry *must* not already have samba attributes */
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+ domain_name);
+
+ /* If we don't have an entry, then ask secrets.tdb for what it thinks.
+ It may choose to make it up */
+
+ sid_to_string(sid_string, get_global_sam_sid());
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string);
+
+ slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base());
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
+ algorithmic_rid_base_string);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
+
+ /* add the sambaNext[User|Group]Rid attributes if the idmap ranges are set.
+ TODO: fix all the places where the line between idmap and normal operations
+ needed by smbd gets fuzzy --jerry 2003-08-11 */
+
+ if ( lp_idmap_uid(&u_low, &u_high) && lp_idmap_gid(&g_low, &g_high)
+ && get_free_rid_range(&rid_low, &rid_high) )
+ {
+ fstring rid_str;
+
+ fstr_sprintf( rid_str, "%i", rid_high|USER_RID_TYPE );
+ DEBUG(10,("setting next available user rid [%s]\n", rid_str));
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
+ rid_str);
+
+ fstr_sprintf( rid_str, "%i", rid_high|GROUP_RID_TYPE );
+ DEBUG(10,("setting next available group rid [%s]\n", rid_str));
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
+ rid_str);
+
+ }
+
+
+ switch(ldap_op)
+ {
+ case LDAP_MOD_ADD:
+ rc = smbldap_add(ldap_state, dn, mods);
+ break;
+ case LDAP_MOD_REPLACE:
+ rc = smbldap_modify(ldap_state, dn, mods);
+ break;
+ default:
+ DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (rc!=LDAP_SUCCESS) {
+ char *ld_error = NULL;
+ ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
+ DEBUG(1,("failed to %s domain dn= %s with: %s\n\t%s\n",
+ ldap_op == LDAP_MOD_ADD ? "add" : "modify",
+ dn, ldap_err2string(rc),
+ ld_error?ld_error:"unknown"));
+ SAFE_FREE(ld_error);
+
+ ldap_mods_free(mods, True);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ DEBUG(2,("added: domain = %s in the LDAP database\n", domain_name));
+ ldap_mods_free(mods, True);
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+Search for the domain info entry
+*********************************************************************/
+NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
+ LDAPMessage ** result, const char *domain_name,
+ BOOL try_add)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ pstring filter;
+ int rc;
+ const char **attr_list;
+ int count;
+
+ pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
+ LDAP_OBJ_DOMINFO,
+ get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+ domain_name);
+
+ DEBUG(2, ("Searching for:[%s]\n", filter));
+
+
+ attr_list = get_attr_list( dominfo_attr_list );
+ rc = smbldap_search_suffix(ldap_state, filter, attr_list , result);
+ free_attr_list( attr_list );
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
+ DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter));
+ } else if (ldap_count_entries(ldap_state->ldap_struct, *result) < 1) {
+ DEBUG(3, ("Got no domain info entries for domain\n"));
+ ldap_msgfree(*result);
+ *result = NULL;
+ if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state, domain_name))) {
+ return smbldap_search_domain_info(ldap_state, result, domain_name, False);
+ }
+ else {
+ DEBUG(0, ("Adding domain info for %s failed with %s\n",
+ domain_name, nt_errstr(ret)));
+ return ret;
+ }
+ } else if ((count = ldap_count_entries(ldap_state->ldap_struct, *result)) > 1) {
+ DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n",
+ count, domain_name));
+ ldap_msgfree(*result);
+ *result = NULL;
+ return ret;
+ } else {
+ return NT_STATUS_OK;
+ }
+
+ return ret;
+}
+
/*******************************************************************
Return a copy of the DN for a LDAPMessage. Convert from utf8 to CH_UNIX.
********************************************************************/
ldap_memfree(utf8_dn);
return unix_dn;
}
+
+/*******************************************************************
+ Check if root-dse has a certain Control or Extension
+********************************************************************/
+
+static BOOL smbldap_check_root_dse(struct smbldap_state *ldap_state, const char **attrs, const char *value)
+{
+ LDAPMessage *msg = NULL;
+ LDAPMessage *entry = NULL;
+ char **values = NULL;
+ int rc, num_result, num_values, i;
+ BOOL result = False;
+
+ if (!attrs[0]) {
+ DEBUG(3,("smbldap_check_root_dse: nothing to look for\n"));
+ return False;
+ }
+
+ if (!strequal(attrs[0], "supportedExtension") &&
+ !strequal(attrs[0], "supportedControl")) {
+ DEBUG(3,("smbldap_check_root_dse: no idea what to query root-dse for: %s ?\n", attrs[0]));
+ return False;
+ }
+
+ rc = ldap_search_s(ldap_state->ldap_struct, "", LDAP_SCOPE_BASE,
+ "(objectclass=*)", CONST_DISCARD(char **, attrs),
+ 0 , &msg);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n"));
+ return False;
+ }
+
+ num_result = ldap_count_entries(ldap_state->ldap_struct, msg);
+
+ if (num_result != 1) {
+ DEBUG(3,("smbldap_check_root_dse: Expected one rootDSE, got %d\n", num_result));
+ goto done;
+ }
+
+ entry = ldap_first_entry(ldap_state->ldap_struct, msg);
+
+ if (entry == NULL) {
+ DEBUG(3,("smbldap_check_root_dse: Could not retrieve rootDSE\n"));
+ goto done;
+ }
+
+ values = ldap_get_values(ldap_state->ldap_struct, entry, attrs[0]);
+
+ if (values == NULL) {
+ DEBUG(5,("smbldap_check_root_dse: LDAP Server does not support any %s\n", attrs[0]));
+ goto done;
+ }
+
+ num_values = ldap_count_values(values);
+
+ if (num_values == 0) {
+ DEBUG(5,("smbldap_check_root_dse: LDAP Server does not have any %s\n", attrs[0]));
+ goto done;
+ }
+
+ for (i=0; i<num_values; i++) {
+ if (strcmp(values[i], value) == 0)
+ result = True;
+ }
+
+
+ done:
+ if (values != NULL)
+ ldap_value_free(values);
+ if (msg != NULL)
+ ldap_msgfree(msg);
+
+ return result;
+}
+
+/*******************************************************************
+ Check if LDAP-Server supports a certain Control (OID in string format)
+********************************************************************/
+
+BOOL smbldap_has_control(struct smbldap_state *ldap_state, const char *control)
+{
+ const char *attrs[] = { "supportedControl", NULL };
+ return smbldap_check_root_dse(ldap_state, attrs, control);
+}
+
+/*******************************************************************
+ Check if LDAP-Server supports a certain Extension (OID in string format)
+********************************************************************/
+
+BOOL smbldap_has_extension(struct smbldap_state *ldap_state, const char *extension)
+{
+ const char *attrs[] = { "supportedExtension", NULL };
+ return smbldap_check_root_dse(ldap_state, attrs, extension);
+}