Copyright (C) Shahms King 2001
Copyright (C) Andrew Bartlett 2002-2003
Copyright (C) Stefan (metze) Metzmacher 2002-2003
+ Copyright (C) Simo Sorce 2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
* Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK
*
* Other LDAP based login attributes: accountExpires, etc.
-* (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT
+* (should be the domain of Samba proper, but the sam_password/struct samu
* structures don't have fields for some of these attributes)
*
* SSL is done, but can't get the certificate based authentication to work
#endif
-#ifndef SAM_ACCOUNT
-#define SAM_ACCOUNT struct sam_passwd
-#endif
-
#include "smbldap.h"
/**********************************************************************
- Free a LDAPMessage (one is stored on the SAM_ACCOUNT).
+ Simple helper function to make stuff better readable
**********************************************************************/
-
-void private_data_free_fn(void **result)
+
+static LDAP *priv2ld(struct ldapsam_privates *priv)
{
- ldap_msgfree(*result);
- *result = NULL;
+ return priv->smbldap_state->ldap_struct;
}
/**********************************************************************
Return the list of attribute names given a user schema version.
**********************************************************************/
-const char** get_userattr_list( int schema_ver )
+const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
- return get_attr_list( attrib_map_v22 );
+ return get_attr_list( mem_ctx, attrib_map_v22 );
case SCHEMAVER_SAMBASAMACCOUNT:
- return get_attr_list( attrib_map_v30 );
+ return get_attr_list( mem_ctx, attrib_map_v30 );
default:
DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
break;
Return the list of attribute names to delete given a user schema version.
**************************************************************************/
-static const char** get_userattr_delete_list( int schema_ver )
+static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx,
+ int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
- return get_attr_list( attrib_map_to_delete_v22 );
+ return get_attr_list( mem_ctx,
+ attrib_map_to_delete_v22 );
case SCHEMAVER_SAMBASAMACCOUNT:
- return get_attr_list( attrib_map_to_delete_v30 );
+ return get_attr_list( mem_ctx,
+ attrib_map_to_delete_v30 );
default:
DEBUG(0,("get_userattr_delete_list: unknown schema version specified!\n"));
break;
return objclass_filter;
}
+/*****************************************************************
+ Scan a sequence number off OpenLDAP's syncrepl contextCSN
+******************************************************************/
+
+static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_num)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+ LDAPMessage *msg = NULL;
+ LDAPMessage *entry = NULL;
+ TALLOC_CTX *mem_ctx;
+ char **values = NULL;
+ int rc, num_result, num_values, rid;
+ pstring suffix;
+ fstring tok;
+ const char *p;
+ const char **attrs;
+
+ /* Unfortunatly there is no proper way to detect syncrepl-support in
+ * smbldap_connect_system(). The syncrepl OIDs are submitted for publication
+ * but do not show up in the root-DSE yet. Neither we can query the
+ * subschema-context for the syncProviderSubentry or syncConsumerSubentry
+ * objectclass. Currently we require lp_ldap_suffix() to show up as
+ * namingContext. - Guenther
+ */
+
+ if (!lp_parm_bool(-1, "ldapsam", "syncrepl_seqnum", False)) {
+ return ntstatus;
+ }
+
+ if (!seq_num) {
+ DEBUG(3,("ldapsam_get_seq_num: no sequence_number\n"));
+ return ntstatus;
+ }
+
+ if (!smbldap_has_naming_context(ldap_state->smbldap_state->ldap_struct, lp_ldap_suffix())) {
+ DEBUG(3,("ldapsam_get_seq_num: DIT not configured to hold %s "
+ "as top-level namingContext\n", lp_ldap_suffix()));
+ return ntstatus;
+ }
+
+ mem_ctx = talloc_init("ldapsam_get_seq_num");
+
+ if (mem_ctx == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ if ((attrs = TALLOC_ARRAY(mem_ctx, const char *, 2)) == NULL) {
+ ntstatus = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ /* if we got a syncrepl-rid (up to three digits long) we speak with a consumer */
+ rid = lp_parm_int(-1, "ldapsam", "syncrepl_rid", -1);
+ if (rid > 0) {
+
+ /* consumer syncreplCookie: */
+ /* csn=20050126161620Z#0000001#00#00000 */
+ attrs[0] = talloc_strdup(mem_ctx, "syncreplCookie");
+ attrs[1] = NULL;
+ pstr_sprintf( suffix, "cn=syncrepl%d,%s", rid, lp_ldap_suffix());
+
+ } else {
+
+ /* provider contextCSN */
+ /* 20050126161620Z#000009#00#000000 */
+ attrs[0] = talloc_strdup(mem_ctx, "contextCSN");
+ attrs[1] = NULL;
+ pstr_sprintf( suffix, "cn=ldapsync,%s", lp_ldap_suffix());
+
+ }
+
+ rc = smbldap_search(ldap_state->smbldap_state, suffix,
+ LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &msg);
+
+ if (rc != LDAP_SUCCESS) {
+ goto done;
+ }
+
+ num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg);
+ if (num_result != 1) {
+ DEBUG(3,("ldapsam_get_seq_num: Expected one entry, got %d\n", num_result));
+ goto done;
+ }
+
+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg);
+ if (entry == NULL) {
+ DEBUG(3,("ldapsam_get_seq_num: Could not retrieve entry\n"));
+ goto done;
+ }
+
+ values = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, attrs[0]);
+ if (values == NULL) {
+ DEBUG(3,("ldapsam_get_seq_num: no values\n"));
+ goto done;
+ }
+
+ num_values = ldap_count_values(values);
+ if (num_values == 0) {
+ DEBUG(3,("ldapsam_get_seq_num: not a single value\n"));
+ goto done;
+ }
+
+ p = values[0];
+ if (!next_token(&p, tok, "#", sizeof(tok))) {
+ DEBUG(0,("ldapsam_get_seq_num: failed to parse sequence number\n"));
+ goto done;
+ }
+
+ p = tok;
+ if (!strncmp(p, "csn=", strlen("csn=")))
+ p += strlen("csn=");
+
+ DEBUG(10,("ldapsam_get_seq_num: got %s: %s\n", attrs[0], p));
+
+ *seq_num = generalized_to_unix_time(p);
+
+ /* very basic sanity check */
+ if (*seq_num <= 0) {
+ DEBUG(3,("ldapsam_get_seq_num: invalid sequence number: %d\n",
+ (int)*seq_num));
+ goto done;
+ }
+
+ ntstatus = NT_STATUS_OK;
+
+ done:
+ if (values != NULL)
+ ldap_value_free(values);
+ if (msg != NULL)
+ ldap_msgfree(msg);
+ if (mem_ctx)
+ talloc_destroy(mem_ctx);
+
+ return ntstatus;
+}
+
/*******************************************************************
Run the search by name.
******************************************************************/
object found in search_result depending on lp_ldap_delete_dn
******************************************************************/
-static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
- LDAPMessage *result,
- const char *objectclass,
- const char **attrs)
+static int ldapsam_delete_entry(struct ldapsam_privates *priv,
+ TALLOC_CTX *mem_ctx,
+ LDAPMessage *entry,
+ const char *objectclass,
+ const char **attrs)
{
- int rc;
- LDAPMessage *entry = NULL;
LDAPMod **mods = NULL;
- char *name, *dn;
+ char *name;
+ const char *dn;
BerElement *ptr = NULL;
- rc = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
-
- if (rc != 1) {
- DEBUG(0, ("ldapsam_delete_entry: Entry must exist exactly once!\n"));
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!dn) {
- return NT_STATUS_UNSUCCESSFUL;
+ dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry);
+ if (dn == NULL) {
+ return LDAP_NO_MEMORY;
}
if (lp_ldap_delete_dn()) {
- NTSTATUS ret = NT_STATUS_OK;
- rc = smbldap_delete(ldap_state->smbldap_state, dn);
-
- if (rc != LDAP_SUCCESS) {
- DEBUG(0, ("ldapsam_delete_entry: Could not delete object %s\n", dn));
- ret = NT_STATUS_UNSUCCESSFUL;
- }
- SAFE_FREE(dn);
- return ret;
+ return smbldap_delete(priv->smbldap_state, dn);
}
/* Ok, delete only the SAM attributes */
- for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr);
+ for (name = ldap_first_attribute(priv2ld(priv), entry, &ptr);
name != NULL;
- name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) {
+ name = ldap_next_attribute(priv2ld(priv), entry, ptr)) {
const char **attrib;
/* We are only allowed to delete the attributes that
really exist. */
for (attrib = attrs; *attrib != NULL; attrib++) {
- /* Don't delete LDAP_ATTR_MOD_TIMESTAMP attribute. */
- if (strequal(*attrib, get_userattr_key2string(ldap_state->schema_ver,
- LDAP_ATTR_MOD_TIMESTAMP))) {
- continue;
- }
if (strequal(*attrib, name)) {
DEBUG(10, ("ldapsam_delete_entry: deleting "
"attribute %s\n", name));
NULL);
}
}
-
ldap_memfree(name);
}
-
+
if (ptr != NULL) {
ber_free(ptr, 0);
}
smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
-
- rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
- ldap_mods_free(mods, True);
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
-
- DEBUG(0, ("ldapsam_delete_entry: Could not delete attributes for %s, error: %s (%s)\n",
- dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
- SAFE_FREE(dn);
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- SAFE_FREE(dn);
- return NT_STATUS_OK;
-}
-
-/* New Interface is being implemented here */
-
-#if 0 /* JERRY - not uesed anymore */
-
-/**********************************************************************
-Initialize SAM_ACCOUNT from an LDAP query (unix attributes only)
-*********************************************************************/
-static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
- SAM_ACCOUNT * sampass,
- LDAPMessage * entry,
- gid_t *gid)
-{
- pstring homedir;
- pstring temp;
- char **ldap_values;
- char **values;
-
- if ((ldap_values = ldap_get_values (ldap_state->smbldap_state->ldap_struct, entry, "objectClass")) == NULL) {
- DEBUG (1, ("get_unix_attributes: no objectClass! \n"));
- return False;
- }
-
- for (values=ldap_values;*values;values++) {
- if (strequal(*values, LDAP_OBJ_POSIXACCOUNT )) {
- break;
- }
- }
-
- if (!*values) { /*end of array, no posixAccount */
- DEBUG(10, ("user does not have %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
- ldap_value_free(ldap_values);
- return False;
- }
- ldap_value_free(ldap_values);
-
- if ( !smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) )
- {
- return False;
- }
-
- if ( !smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) )
- {
- return False;
- }
-
- *gid = (gid_t)atol(temp);
-
- pdb_set_unix_homedir(sampass, homedir, PDB_SET);
-
- DEBUG(10, ("user has %s attributes\n", LDAP_OBJ_POSIXACCOUNT));
+ talloc_autofree_ldapmod(mem_ctx, mods);
- return True;
+ return smbldap_modify(priv->smbldap_state, dn, mods);
}
-
-#endif
-
-static time_t ldapsam_get_entry_timestamp(
- struct ldapsam_privates *ldap_state,
- LDAPMessage * entry)
+
+static time_t ldapsam_get_entry_timestamp( struct ldapsam_privates *ldap_state, LDAPMessage * entry)
{
pstring temp;
struct tm tm;
temp))
return (time_t) 0;
- strptime(temp, "%Y%m%d%H%M%SZ", &tm);
+ if ( !strptime(temp, "%Y%m%d%H%M%SZ", &tm)) {
+ DEBUG(2,("ldapsam_get_entry_timestamp: strptime failed on: %s\n",
+ (char*)temp));
+ return (time_t) 0;
+ }
tzset();
return timegm(&tm);
}
/**********************************************************************
- Initialize SAM_ACCOUNT from an LDAP query.
+ Initialize struct samu from an LDAP query.
(Based on init_sam_from_buffer in pdb_tdb.c)
*********************************************************************/
static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
- SAM_ACCOUNT * sampass,
+ struct samu * sampass,
LDAPMessage * entry)
{
time_t logon_time,
uint8 smblmpwd[LM_HASH_LEN],
smbntpwd[NT_HASH_LEN];
BOOL use_samba_attrs = True;
- uint16 acct_ctrl = 0,
- logon_divs;
+ uint32 acct_ctrl = 0;
+ uint16 logon_divs;
uint16 bad_password_count = 0,
logon_count = 0;
uint32 hours_len;
LOGIN_CACHE *cache_entry = NULL;
uint32 pwHistLen;
pstring tmpstring;
+ BOOL expand_explicit = lp_passdb_expand_explicit();
/*
* do a little initialization
return False;
}
- if (ldap_state->smbldap_state->ldap_struct == NULL) {
- DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->ldap_struct is NULL!\n"));
+ if (priv2ld(ldap_state) == NULL) {
+ DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->"
+ "ldap_struct is NULL!\n"));
return False;
}
- if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) {
- DEBUG(1, ("init_sam_from_ldap: No uid attribute found for this user!\n"));
+ if (!smbldap_get_single_pstring(priv2ld(ldap_state), entry, "uid",
+ username)) {
+ DEBUG(1, ("init_sam_from_ldap: No uid attribute found for "
+ "this user!\n"));
return False;
}
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) {
pdb_set_user_sid_from_string(sampass, temp, PDB_SET);
}
-
- if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) {
- pdb_set_group_sid_from_string(sampass, temp, PDB_SET);
- } else {
- pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
- }
} else {
if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) {
user_rid = (uint32)atol(temp);
pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
}
-
- if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) {
- pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
- } else {
- uint32 group_rid;
-
- group_rid = (uint32)atol(temp);
-
- /* for some reason, we often have 0 as a primary group RID.
- Make sure that we treat this just as a 'default' value */
-
- if ( group_rid > 0 )
- pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
- else
- pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
- }
}
if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) {
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir))
{
pdb_set_homedir( sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_home()),
PDB_DEFAULT );
} else {
pstrcpy( tmpstring, homedir );
- standard_sub_basic( username, tmpstring, sizeof(tmpstring) );
+ if (expand_explicit) {
+ standard_sub_basic( username, domain, tmpstring,
+ sizeof(tmpstring) );
+ }
pdb_set_homedir(sampass, tmpstring, PDB_SET);
}
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script))
{
pdb_set_logon_script( sampass,
- talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()),
+ talloc_sub_basic(sampass, username, domain,
+ lp_logon_script()),
PDB_DEFAULT );
} else {
pstrcpy( tmpstring, logon_script );
- standard_sub_basic( username, tmpstring, sizeof(tmpstring) );
+ if (expand_explicit) {
+ standard_sub_basic( username, domain, tmpstring,
+ sizeof(tmpstring) );
+ }
pdb_set_logon_script(sampass, tmpstring, PDB_SET);
}
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path))
{
pdb_set_profile_path( sampass,
- talloc_sub_basic( sampass->mem_ctx, username, lp_logon_path()),
+ talloc_sub_basic( sampass, username, domain,
+ lp_logon_path()),
PDB_DEFAULT );
} else {
pstrcpy( tmpstring, profile_path );
- standard_sub_basic( username, tmpstring, sizeof(tmpstring) );
+ if (expand_explicit) {
+ standard_sub_basic( username, domain, tmpstring,
+ sizeof(tmpstring) );
+ }
pdb_set_profile_path(sampass, tmpstring, PDB_SET);
}
if (ldap_state->is_nds_ldap) {
char *user_dn;
- int pwd_len;
+ size_t pwd_len;
char clear_text_pw[512];
-
+
/* Make call to Novell eDirectory ldap extension to get clear text password.
NOTE: This will only work if we have an SSL connection to eDirectory. */
user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
pwd_len = sizeof(clear_text_pw);
if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd);
- if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
+ if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET)) {
+ SAFE_FREE(user_dn);
return False;
+ }
ZERO_STRUCT(smblmpwd);
- if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
+ if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET)) {
+ SAFE_FREE(user_dn);
return False;
+ }
ZERO_STRUCT(smbntpwd);
use_samba_attrs = False;
}
+
+ SAFE_FREE(user_dn);
+
} else {
DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username));
}
- }
+ }
if (use_samba_attrs) {
if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
return False;
ZERO_STRUCT(smbntpwd);
}
- }
+ }
- account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+ pwHistLen = 0;
+
+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
if (pwHistLen > 0){
uint8 *pwhist = NULL;
int i;
+ char history_string[MAX_PW_HISTORY_LEN*64];
- /* We can only store (sizeof(pstring)-1)/64 password history entries. */
- pwHistLen = MIN(pwHistLen, ((sizeof(temp)-1)/64));
+ pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN);
- if ((pwhist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
+ if ((pwhist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN)) == NULL){
DEBUG(0, ("init_sam_from_ldap: malloc failed!\n"));
return False;
}
memset(pwhist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
- if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), temp)) {
+ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY),
+ history_string, sizeof(history_string))) {
/* leave as default - zeros */
} else {
BOOL hex_failed = False;
for (i = 0; i < pwHistLen; i++){
/* Get the 16 byte salt. */
- if (!pdb_gethexpwd(&temp[i*64], &pwhist[i*PW_HISTORY_ENTRY_LEN])) {
+ if (!pdb_gethexpwd(&history_string[i*64], &pwhist[i*PW_HISTORY_ENTRY_LEN])) {
hex_failed = True;
break;
}
/* Get the 16 byte MD5 hash of salt+passwd. */
- if (!pdb_gethexpwd(&temp[(i*64)+32],
+ if (!pdb_gethexpwd(&history_string[(i*64)+32],
&pwhist[(i*PW_HISTORY_ENTRY_LEN)+PW_HISTORY_SALT_LEN])) {
hex_failed = True;
break;
ZERO_STRUCT(hours);
}
+ if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+ if (smbldap_get_single_pstring(priv2ld(ldap_state), entry,
+ "uidNumber", temp)) {
+ /* We've got a uid, feed the cache */
+ uid_t uid = strtoul(temp, NULL, 10);
+ store_uid_sid_cache(pdb_get_user_sid(sampass), uid);
+ }
+ }
+
/* check the timestamp of the cache vs ldap entry */
if (!(ldap_entry_time = ldapsam_get_entry_timestamp(ldap_state,
entry)))
}
/**********************************************************************
- Initialize the ldap db from a SAM_ACCOUNT. Called on update.
+ Initialize the ldap db from a struct samu. Called on update.
(Based on init_buffer_from_sam in pdb_tdb.c)
*********************************************************************/
static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
LDAPMessage *existing,
- LDAPMod *** mods, SAM_ACCOUNT * sampass,
- BOOL (*need_update)(const SAM_ACCOUNT *,
+ LDAPMod *** mods, struct samu * sampass,
+ BOOL (*need_update)(const struct samu *,
enum pdb_elements))
{
pstring temp;
* took out adding "objectclass: sambaAccount"
* do this on a per-mod basis
*/
- if (need_update(sampass, PDB_USERNAME))
+ if (need_update(sampass, PDB_USERNAME)) {
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
"uid", pdb_get_username(sampass));
+ if (ldap_state->is_nds_ldap) {
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
+ "cn", pdb_get_username(sampass));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
+ "sn", pdb_get_username(sampass));
+ }
+ }
DEBUG(2, ("init_ldap_from_sam: Setting entry for user: %s\n", pdb_get_username(sampass)));
/* only update the RID if we actually need to */
if (need_update(sampass, PDB_USERSID)) {
fstring sid_string;
- fstring dom_sid_string;
const DOM_SID *user_sid = pdb_get_user_sid(sampass);
switch ( ldap_state->schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) {
DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
- sid_to_string(sid_string, user_sid),
- sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
+ sid_string_static(user_sid),
+ sid_string_static(&ldap_state->domain_sid)));
return False;
}
slprintf(temp, sizeof(temp) - 1, "%i", rid);
if (need_update(sampass, PDB_GROUPSID)) {
fstring sid_string;
- fstring dom_sid_string;
const DOM_SID *group_sid = pdb_get_group_sid(sampass);
switch ( ldap_state->schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) {
DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n",
- sid_to_string(sid_string, group_sid),
- sid_to_string(dom_sid_string, &ldap_state->domain_sid)));
+ sid_string_static(group_sid),
+ sid_string_static(&ldap_state->domain_sid)));
return False;
}
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp);
- slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
+ slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time_noncalc(sampass));
if (need_update(sampass, PDB_CANCHANGETIME))
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp);
if (need_update(sampass, PDB_PWHISTORY)) {
uint32 pwHistLen = 0;
- account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
if (pwHistLen == 0) {
/* Remove any password history from the LDAP store. */
memset(temp, '0', 64); /* NOTE !!!! '0' *NOT '\0' */
uint16 badcount = pdb_get_bad_password_count(sampass);
time_t badtime = pdb_get_bad_password_time(sampass);
uint32 pol;
- account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &pol);
+ pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &pol);
DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n",
(unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime));
Connect to LDAP server for password enumeration.
*********************************************************************/
-static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint16 acb_mask)
+static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update, uint32 acb_mask)
{
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
int rc;
DEBUG(10,("ldapsam_setsampwent: LDAP Query for acb_mask 0x%x will use suffix %s\n",
acb_mask, suffix));
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
rc = smbldap_search(ldap_state->smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter,
attr_list, 0, &ldap_state->result);
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (rc != LDAP_SUCCESS) {
DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc)));
Get the next entry in the LDAP password database.
*********************************************************************/
-static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
+static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods,
+ struct samu *user)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)my_methods->private_data;
BOOL bret = False;
while (!bret) {
ldap_state->index++;
bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
- ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
- ldap_state->entry);
+ ldap_state->entry = ldap_next_entry(priv2ld(ldap_state),
+ ldap_state->entry);
}
return NT_STATUS_OK;
}
-static void append_attr(const char ***attr_list, const char *new_attr)
+static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
+ const char *new_attr)
{
int i;
;
}
- (*attr_list) = SMB_REALLOC_ARRAY((*attr_list), const char *, i+2);
+ (*attr_list) = TALLOC_REALLOC_ARRAY(mem_ctx, (*attr_list),
+ const char *, i+2);
SMB_ASSERT((*attr_list) != NULL);
- (*attr_list)[i] = SMB_STRDUP(new_attr);
+ (*attr_list)[i] = talloc_strdup((*attr_list), new_attr);
(*attr_list)[i+1] = NULL;
}
/**********************************************************************
-Get SAM_ACCOUNT entry from LDAP by username.
+Get struct samu entry from LDAP by username.
*********************************************************************/
-static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
+static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, struct samu *user, const char *sname)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
const char ** attr_list;
int rc;
- attr_list = get_userattr_list( ldap_state->schema_ver );
- append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP));
- rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
- free_attr_list( attr_list );
+ attr_list = get_userattr_list( user, ldap_state->schema_ver );
+ append_attr(user, &attr_list,
+ get_userattr_key2string(ldap_state->schema_ver,
+ LDAP_ATTR_MOD_TIMESTAMP));
+ append_attr(user, &attr_list, "uidNumber");
+ rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result,
+ attr_list);
+ TALLOC_FREE( attr_list );
if ( rc != LDAP_SUCCESS )
return NT_STATUS_NO_SUCH_USER;
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_USER;
}
- pdb_set_backend_private_data(user, result,
- private_data_free_fn,
+ pdb_set_backend_private_data(user, result, NULL,
my_methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(user, result);
ret = NT_STATUS_OK;
} else {
ldap_msgfree(result);
uint32 rid;
switch ( ldap_state->schema_ver ) {
- case SCHEMAVER_SAMBASAMACCOUNT:
- attr_list = get_userattr_list(ldap_state->schema_ver);
- append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP));
- rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list);
- free_attr_list( attr_list );
+ case SCHEMAVER_SAMBASAMACCOUNT: {
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return LDAP_NO_MEMORY;
+ }
+
+ attr_list = get_userattr_list(tmp_ctx,
+ ldap_state->schema_ver);
+ append_attr(tmp_ctx, &attr_list,
+ get_userattr_key2string(
+ ldap_state->schema_ver,
+ LDAP_ATTR_MOD_TIMESTAMP));
+ append_attr(tmp_ctx, &attr_list, "uidNumber");
+ rc = ldapsam_search_suffix_by_sid(ldap_state, sid,
+ result, attr_list);
+ TALLOC_FREE(tmp_ctx);
if ( rc != LDAP_SUCCESS )
return rc;
break;
+ }
case SCHEMAVER_SAMBAACCOUNT:
if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
return rc;
}
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL,
+ ldap_state->schema_ver);
rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if ( rc != LDAP_SUCCESS )
return rc;
}
/**********************************************************************
- Get SAM_ACCOUNT entry from LDAP by SID.
+ Get struct samu entry from LDAP by SID.
*********************************************************************/
-static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid)
+static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, struct samu * user, const DOM_SID *sid)
{
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
LDAPMessage *result = NULL;
return NT_STATUS_NO_SUCH_USER;
}
- pdb_set_backend_private_data(user, result,
- private_data_free_fn,
+ pdb_set_backend_private_data(user, result, NULL,
my_methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(user, result);
return NT_STATUS_OK;
}
-static BOOL ldapsam_can_pwchange_exop(struct smbldap_state *ldap_state)
-{
- return smbldap_has_extension(ldap_state, LDAP_EXOP_MODIFY_PASSWD);
-}
-
/********************************************************************
Do the actual modification - also change a plaintext passord if
it it set.
**********************************************************************/
static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
- SAM_ACCOUNT *newpwd, char *dn,
+ struct samu *newpwd, char *dn,
LDAPMod **mods, int ldap_op,
- BOOL (*need_update)(const SAM_ACCOUNT *, enum pdb_elements))
+ BOOL (*need_update)(const struct samu *, enum pdb_elements))
{
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
int rc;
- if (!my_methods || !newpwd || !dn) {
+ if (!newpwd || !dn) {
return NT_STATUS_INVALID_PARAMETER;
}
/* may be password change below however */
} else {
switch(ldap_op) {
- case LDAP_MOD_ADD:
- smbldap_set_mod(&mods, LDAP_MOD_ADD,
- "objectclass",
- LDAP_OBJ_ACCOUNT);
+ case LDAP_MOD_ADD:
+ if (ldap_state->is_nds_ldap) {
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ "objectclass",
+ "inetOrgPerson");
+ } else {
+ smbldap_set_mod(&mods, LDAP_MOD_ADD,
+ "objectclass",
+ LDAP_OBJ_ACCOUNT);
+ }
rc = smbldap_add(ldap_state->smbldap_state,
dn, mods);
break;
}
if (rc!=LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(1, ("ldapsam_modify_entry: Failed to %s user 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);
return NT_STATUS_UNSUCCESSFUL;
}
}
char *utf8_dn;
if (!ldap_state->is_nds_ldap) {
- if (!ldapsam_can_pwchange_exop(ldap_state->smbldap_state)) {
+
+ if (!smbldap_has_extension(ldap_state->smbldap_state->ldap_struct,
+ LDAP_EXOP_MODIFY_PASSWD)) {
DEBUG(2, ("ldap password change requested, but LDAP "
"server does not support it -- ignoring\n"));
return NT_STATUS_OK;
}
if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) {
+ SAFE_FREE(utf8_password);
return NT_STATUS_NO_MEMORY;
}
if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
DEBUG(0,("ber_alloc_t returns NULL\n"));
SAFE_FREE(utf8_password);
+ SAFE_FREE(utf8_dn);
return NT_STATUS_UNSUCCESSFUL;
}
ber_printf (ber, "{");
ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn);
ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password);
- ber_printf (ber, "N}");
+ ber_printf (ber, "n}");
if ((rc = ber_flatten (ber, &bv))<0) {
DEBUG(0,("ldapsam_modify_entry: ber_flatten returns a value <0\n"));
if (retdata)
ber_bvfree(retdata);
if (retoid)
- ber_memfree(retoid);
+ ldap_memfree(retoid);
}
ber_bvfree(bv);
}
Delete entry from LDAP for username.
*********************************************************************/
-static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
+static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods,
+ struct samu * sam_acct)
{
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *priv =
+ (struct ldapsam_privates *)my_methods->private_data;
const char *sname;
int rc;
- LDAPMessage *result = NULL;
- NTSTATUS ret;
+ LDAPMessage *msg, *entry;
+ NTSTATUS result = NT_STATUS_NO_MEMORY;
const char **attr_list;
- fstring objclass;
+ TALLOC_CTX *mem_ctx;
if (!sam_acct) {
DEBUG(0, ("ldapsam_delete_sam_account: sam_acct was NULL!\n"));
sname = pdb_get_username(sam_acct);
- DEBUG (3, ("ldapsam_delete_sam_account: Deleting user %s from LDAP.\n", sname));
+ DEBUG(3, ("ldapsam_delete_sam_account: Deleting user %s from "
+ "LDAP.\n", sname));
- attr_list= get_userattr_delete_list( ldap_state->schema_ver );
- rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ goto done;
+ }
- if (rc != LDAP_SUCCESS) {
- free_attr_list( attr_list );
- return NT_STATUS_NO_SUCH_USER;
+ attr_list = get_userattr_delete_list(mem_ctx, priv->schema_ver );
+ if (attr_list == NULL) {
+ goto done;
}
-
- switch ( ldap_state->schema_ver ) {
- case SCHEMAVER_SAMBASAMACCOUNT:
- fstrcpy( objclass, LDAP_OBJ_SAMBASAMACCOUNT );
- break;
-
- case SCHEMAVER_SAMBAACCOUNT:
- fstrcpy( objclass, LDAP_OBJ_SAMBAACCOUNT );
- break;
- default:
- fstrcpy( objclass, "UNKNOWN" );
- DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
- break;
+
+ rc = ldapsam_search_suffix_by_name(priv, sname, &msg, attr_list);
+
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(priv2ld(priv), msg) != 1) ||
+ ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
+ DEBUG(5, ("Could not find user %s\n", sname));
+ result = NT_STATUS_NO_SUCH_USER;
+ goto done;
}
+
+ rc = ldapsam_delete_entry(
+ priv, mem_ctx, entry,
+ priv->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ?
+ LDAP_OBJ_SAMBASAMACCOUNT : LDAP_OBJ_SAMBAACCOUNT,
+ attr_list);
- ret = ldapsam_delete_entry(ldap_state, result, objclass, attr_list );
- ldap_msgfree(result);
- free_attr_list( attr_list );
+ result = (rc == LDAP_SUCCESS) ?
+ NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
- return ret;
+ done:
+ TALLOC_FREE(mem_ctx);
+ return result;
}
/**********************************************************************
we need LDAP modification.
*********************************************************************/
-static BOOL element_is_changed(const SAM_ACCOUNT *sampass,
+static BOOL element_is_changed(const struct samu *sampass,
enum pdb_elements element)
{
return IS_SAM_CHANGED(sampass, element);
}
/**********************************************************************
- Update SAM_ACCOUNT.
+ Update struct samu.
*********************************************************************/
-static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
+static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, struct samu * newpwd)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
LDAPMod **mods = NULL;
const char **attr_list;
- result = pdb_get_backend_private_data(newpwd, my_methods);
+ result = (LDAPMessage *)pdb_get_backend_private_data(newpwd, my_methods);
if (!result) {
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
+ if (pdb_get_username(newpwd) == NULL) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (rc != LDAP_SUCCESS) {
return NT_STATUS_UNSUCCESSFUL;
}
- pdb_set_backend_private_data(newpwd, result, private_data_free_fn, my_methods, PDB_CHANGED);
+ pdb_set_backend_private_data(newpwd, result, NULL,
+ my_methods, PDB_CHANGED);
+ talloc_autofree_ldapmsg(newpwd, result);
}
if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
ldap_mods_free(mods,True);
SAFE_FREE(dn);
+ /*
+ * We need to set the backend private data to NULL here. For example
+ * setuserinfo level 25 does a pdb_update_sam_account twice on the
+ * same one, and with the explicit delete / add logic for attribute
+ * values the second time we would use the wrong "old" value which
+ * does not exist in LDAP anymore. Thus the LDAP server would refuse
+ * the update.
+ * The existing LDAPMessage is still being auto-freed by the
+ * destructor.
+ */
+ pdb_set_backend_private_data(newpwd, NULL, NULL, my_methods,
+ PDB_CHANGED);
+
if (!NT_STATUS_IS_OK(ret)) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0,("ldapsam_update_sam_account: failed to modify user with uid = %s, error: %s (%s)\n",
- pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
- SAFE_FREE(ld_error);
return ret;
}
return NT_STATUS_OK;
}
+/***************************************************************************
+ Renames a struct samu
+ - The "rename user script" has full responsibility for changing everything
+***************************************************************************/
+
+static NTSTATUS ldapsam_rename_sam_account(struct pdb_methods *my_methods,
+ struct samu *old_acct,
+ const char *newname)
+{
+ const char *oldname;
+ int rc;
+ pstring rename_script;
+ fstring oldname_lower, newname_lower;
+
+ if (!old_acct) {
+ DEBUG(0, ("ldapsam_rename_sam_account: old_acct was NULL!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ if (!newname) {
+ DEBUG(0, ("ldapsam_rename_sam_account: newname was NULL!\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ oldname = pdb_get_username(old_acct);
+
+ /* rename the posix user */
+ pstrcpy(rename_script, lp_renameuser_script());
+
+ if (!(*rename_script))
+ return NT_STATUS_ACCESS_DENIED;
+
+ DEBUG (3, ("ldapsam_rename_sam_account: Renaming user %s to %s.\n",
+ oldname, newname));
+
+ /* We have to allow the account name to end with a '$'.
+ Also, follow the semantics in _samr_create_user() and lower case the
+ posix name but preserve the case in passdb */
+
+ fstrcpy( oldname_lower, oldname );
+ strlower_m( oldname_lower );
+ fstrcpy( newname_lower, newname );
+ strlower_m( newname_lower );
+ string_sub2(rename_script, "%unew", newname_lower, sizeof(pstring),
+ True, False, True);
+ string_sub2(rename_script, "%uold", oldname_lower, sizeof(pstring),
+ True, False, True);
+ rc = smbrun(rename_script, NULL);
+
+ DEBUG(rc ? 0 : 3,("Running the command `%s' gave %d\n",
+ rename_script, rc));
+
+ if (rc == 0) {
+ smb_nscd_flush_user_cache();
+ }
+
+ if (rc)
+ return NT_STATUS_UNSUCCESSFUL;
+
+ return NT_STATUS_OK;
+}
+
/**********************************************************************
Helper function to determine for update_sam_account whether
we need LDAP modification.
*********************************************************************/
-static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass,
+static BOOL element_is_set_or_changed(const struct samu *sampass,
enum pdb_elements element)
{
return (IS_SAM_SET(sampass, element) ||
}
/**********************************************************************
- Add SAM_ACCOUNT to LDAP.
+ Add struct samu to LDAP.
*********************************************************************/
-static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd)
+static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct samu * newpwd)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
}
/* free this list after the second search or in case we exit on failure */
- attr_list = get_userattr_list(ldap_state->schema_ver);
+ attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
if (rc != LDAP_SUCCESS) {
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
DEBUG(0,("ldapsam_add_sam_account: User '%s' already in the base, with samba attributes\n",
username));
ldap_msgfree(result);
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
ldap_msgfree(result);
if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
DEBUG(0,("ldapsam_add_sam_account: SID '%s' already in the base, with samba attributes\n",
sid_to_string(sid_string, sid)));
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
rc = smbldap_search_suffix(ldap_state->smbldap_state,
filter, attr_list, &result);
if ( rc != LDAP_SUCCESS ) {
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
if (num_result > 1) {
DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
if (!tmp) {
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
filter, attr_list, &result);
if ( rc != LDAP_SUCCESS ) {
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
return NT_STATUS_UNSUCCESSFUL;
}
num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
if (num_result > 1) {
- DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
- free_attr_list( attr_list );
+ DEBUG (0, ("ldapsam_add_sam_account: More than one user with specified Sid exists: bailing out!\n"));
+ TALLOC_FREE( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
if (!tmp) {
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;
}
}
}
- free_attr_list( attr_list );
+ TALLOC_FREE( attr_list );
if (num_result == 0) {
+ char *escape_username;
/* Check if we need to add an entry */
DEBUG(3,("ldapsam_add_sam_account: Adding new user\n"));
ldap_op = LDAP_MOD_ADD;
+
+ escape_username = escape_rdn_val_string_alloc(username);
+ if (!escape_username) {
+ DEBUG(0, ("Out of memory!\n"));
+ ldap_msgfree(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+
if (username[strlen(username)-1] == '$') {
- slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
+ slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", escape_username, lp_ldap_machine_suffix ());
} else {
- slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
+ slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", escape_username, lp_ldap_user_suffix ());
}
+
+ SAFE_FREE(escape_username);
}
if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
int rc;
const char **attr_list;
- attr_list = get_attr_list(groupmap_attr_list);
+ attr_list = get_attr_list(NULL, groupmap_attr_list);
rc = smbldap_search(ldap_state->smbldap_state,
lp_ldap_group_suffix (), scope,
filter, attr_list, 0, result);
- free_attr_list( attr_list );
-
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0, ("ldapsam_search_one_group: "
- "Problem during the LDAP search: LDAP error: %s (%s)\n",
- ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
- DEBUGADD(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
- lp_ldap_group_suffix(), filter));
- SAFE_FREE(ld_error);
- }
+ TALLOC_FREE(attr_list);
return rc;
}
get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE)));
return False;
}
- map->sid_name_use = (enum SID_NAME_USE)atol(temp);
+ map->sid_name_use = (enum lsa_SidType)atol(temp);
if ((map->sid_name_use < SID_NAME_USER) ||
(map->sid_name_use > SID_NAME_UNKNOWN)) {
}
fstrcpy(map->comment, temp);
+ if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+ store_gid_sid_cache(&map->sid, map->gid);
+ }
+
return True;
}
/**********************************************************************
*********************************************************************/
-static BOOL init_ldap_from_group(LDAP *ldap_struct,
- LDAPMessage *existing,
- LDAPMod ***mods,
- const GROUP_MAP *map)
-{
- pstring tmp;
-
- if (mods == NULL || map == NULL) {
- DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
- return False;
- }
-
- *mods = NULL;
-
- sid_to_string(tmp, &map->sid);
-
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
- pstr_sprintf(tmp, "%i", map->sid_name_use);
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
-
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
- smbldap_make_mod(ldap_struct, existing, mods,
- get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
-
- return True;
-}
-
-/**********************************************************************
- *********************************************************************/
-
-static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
- const char *filter,
- GROUP_MAP *map)
+static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
+ const char *filter,
+ GROUP_MAP *map)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
return NT_STATUS_NO_SUCH_GROUP;
}
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+ count = ldap_count_entries(priv2ld(ldap_state), result);
if (count < 1) {
DEBUG(4, ("ldapsam_getgroup: Did not find group\n"));
}
if (count > 1) {
- DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: count=%d\n",
- filter, count));
+ DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
+ "count=%d\n", filter, count));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_GROUP;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
if (!entry) {
ldap_msgfree(result);
}
if (!init_group_from_ldap(ldap_state, map, entry)) {
- DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for group filter %s\n",
- filter));
+ DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for "
+ "group filter %s\n", filter));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_GROUP;
}
{
pstring filter;
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))",
+ pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
LDAP_OBJ_GROUPMAP,
get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
- gid);
+ (unsigned long)gid);
return ldapsam_getgroup(methods, filter, map);
}
return ldapsam_getgroup(methods, filter, map);
}
-static void add_rid_to_array_unique(TALLOC_CTX *mem_ctx,
- uint32 rid, uint32 **rids, int *num)
-{
- int i;
-
- for (i=0; i<*num; i++) {
- if ((*rids)[i] == rid)
- return;
- }
-
- *rids = TALLOC_REALLOC_ARRAY(mem_ctx, *rids, uint32, *num+1);
-
- if (*rids == NULL)
- return;
-
- (*rids)[*num] = rid;
- *num += 1;
-}
-
static BOOL ldapsam_extract_rid_from_entry(LDAP *ldap_struct,
LDAPMessage *entry,
const DOM_SID *domain_sid,
static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
TALLOC_CTX *mem_ctx,
const DOM_SID *group,
- uint32 **member_rids,
- int *num_members)
+ uint32 **pp_member_rids,
+ size_t *p_num_members)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
struct smbldap_state *conn = ldap_state->smbldap_state;
- pstring filter;
- int rc, count;
- LDAPMessage *msg = NULL;
+ const char *id_attrs[] = { "memberUid", "gidNumber", NULL };
+ const char *sid_attrs[] = { "sambaSID", NULL };
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ LDAPMessage *result = NULL;
LDAPMessage *entry;
+ char *filter;
char **values = NULL;
char **memberuid;
- char *sid_filter = NULL;
- char *tmp;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
- if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
- return pdb_default_enum_group_members(methods, mem_ctx, group,
- member_rids,
- num_members);
-
- *member_rids = NULL;
- *num_members = 0;
-
- pstr_sprintf(filter,
- "(&(objectClass=sambaSamAccount)"
- "(sambaPrimaryGroupSid=%s))",
- sid_string_static(group));
+ char *gidstr;
+ int rc, count;
- {
- const char *attrs[] = { "sambaSID", NULL };
- rc = smbldap_search(conn, lp_ldap_user_suffix(),
- LDAP_SCOPE_SUBTREE, filter, attrs, 0,
- &msg);
- }
+ *pp_member_rids = NULL;
+ *p_num_members = 0;
- if (rc != LDAP_SUCCESS)
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=%s)"
+ "(objectClass=%s)"
+ "(sambaSID=%s))",
+ LDAP_OBJ_POSIXGROUP,
+ LDAP_OBJ_GROUPMAP,
+ sid_string_static(group));
+ if (filter == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
goto done;
-
- for (entry = ldap_first_entry(conn->ldap_struct, msg);
- entry != NULL;
- entry = ldap_next_entry(conn->ldap_struct, entry))
- {
- uint32 rid;
-
- if (!ldapsam_extract_rid_from_entry(conn->ldap_struct,
- entry,
- get_global_sam_sid(),
- &rid)) {
- DEBUG(2, ("Could not find sid from ldap entry\n"));
- continue;
- }
-
- add_rid_to_array_unique(mem_ctx, rid, member_rids,
- num_members);
}
- if (msg != NULL)
- ldap_msgfree(msg);
-
- pstr_sprintf(filter,
- "(&(objectClass=sambaGroupMapping)"
- "(objectClass=posixGroup)"
- "(sambaSID=%s))",
- sid_string_static(group));
-
- {
- const char *attrs[] = { "memberUid", NULL };
- rc = smbldap_search(conn, lp_ldap_group_suffix(),
- LDAP_SCOPE_SUBTREE, filter, attrs, 0,
- &msg);
- }
+ rc = smbldap_search(conn, lp_ldap_group_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, id_attrs, 0,
+ &result);
if (rc != LDAP_SUCCESS)
goto done;
- count = ldap_count_entries(conn->ldap_struct, msg);
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ count = ldap_count_entries(conn->ldap_struct, result);
if (count > 1) {
DEBUG(1, ("Found more than one groupmap entry for %s\n",
sid_string_static(group)));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
goto done;
}
if (count == 0) {
- result = NT_STATUS_OK;
+ ret = NT_STATUS_NO_SUCH_GROUP;
goto done;
}
- entry = ldap_first_entry(conn->ldap_struct, msg);
+ entry = ldap_first_entry(conn->ldap_struct, result);
if (entry == NULL)
goto done;
- values = ldap_get_values(conn->ldap_struct, msg, "memberUid");
- if (values == NULL) {
- result = NT_STATUS_OK;
+ gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
+ if (!gidstr) {
+ DEBUG (0, ("ldapsam_enum_group_members: Unable to find the group's gid!\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
goto done;
}
- sid_filter = SMB_STRDUP("(&(objectClass=sambaSamAccount)(|");
- if (sid_filter == NULL) {
- result = NT_STATUS_NO_MEMORY;
- goto done;
- }
+ values = ldap_get_values(conn->ldap_struct, entry, "memberUid");
- for (memberuid = values; *memberuid != NULL; memberuid += 1) {
- tmp = sid_filter;
- asprintf(&sid_filter, "%s(uid=%s)", tmp, *memberuid);
- free(tmp);
- if (sid_filter == NULL) {
- result = NT_STATUS_NO_MEMORY;
+ if (values) {
+
+ filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(|", LDAP_OBJ_SAMBASAMACCOUNT);
+ if (filter == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
goto done;
}
- }
- tmp = sid_filter;
- asprintf(&sid_filter, "%s))", sid_filter);
- free(tmp);
- if (sid_filter == NULL) {
- result = NT_STATUS_NO_MEMORY;
- goto done;
- }
+ for (memberuid = values; *memberuid != NULL; memberuid += 1) {
+ char *escape_memberuid;
+
+ escape_memberuid = escape_ldap_string_alloc(*memberuid);
+ if (escape_memberuid == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ filter = talloc_asprintf_append_buffer(filter, "(uid=%s)", escape_memberuid);
+ if (filter == NULL) {
+ SAFE_FREE(escape_memberuid);
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ SAFE_FREE(escape_memberuid);
+ }
+
+ filter = talloc_asprintf_append_buffer(filter, "))");
+ if (filter == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
- {
- const char *attrs[] = { "sambaSID", NULL };
rc = smbldap_search(conn, lp_ldap_user_suffix(),
- LDAP_SCOPE_SUBTREE, sid_filter, attrs, 0,
- &msg);
+ LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
+ &result);
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ count = ldap_count_entries(conn->ldap_struct, result);
+ DEBUG(10,("ldapsam_enum_group_members: found %d accounts\n", count));
+
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ for (entry = ldap_first_entry(conn->ldap_struct, result);
+ entry != NULL;
+ entry = ldap_next_entry(conn->ldap_struct, entry))
+ {
+ char *sidstr;
+ DOM_SID sid;
+ uint32 rid;
+
+ sidstr = smbldap_talloc_single_attribute(conn->ldap_struct,
+ entry, "sambaSID",
+ mem_ctx);
+ if (!sidstr) {
+ DEBUG(0, ("Severe DB error, sambaSamAccount can't miss "
+ "the sambaSID attribute\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ if (!string_to_sid(&sid, sidstr))
+ goto done;
+
+ if (!sid_check_is_in_our_domain(&sid)) {
+ DEBUG(0, ("Inconsistent SAM -- group member uid not "
+ "in our domain\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ sid_peek_rid(&sid, &rid);
+
+ if (!add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
+ p_num_members)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
}
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=%s)"
+ "(gidNumber=%s))",
+ LDAP_OBJ_SAMBASAMACCOUNT,
+ gidstr);
+
+ rc = smbldap_search(conn, lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, sid_attrs, 0,
+ &result);
+
if (rc != LDAP_SUCCESS)
goto done;
- for (entry = ldap_first_entry(conn->ldap_struct, msg);
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ for (entry = ldap_first_entry(conn->ldap_struct, result);
entry != NULL;
entry = ldap_next_entry(conn->ldap_struct, entry))
{
- fstring str;
- DOM_SID sid;
uint32 rid;
- if (!smbldap_get_single_attribute(conn->ldap_struct,
- entry, "sambaSID",
- str, sizeof(str)-1))
- continue;
-
- if (!string_to_sid(&sid, str))
+ if (!ldapsam_extract_rid_from_entry(conn->ldap_struct,
+ entry,
+ get_global_sam_sid(),
+ &rid)) {
+ DEBUG(0, ("Severe DB error, sambaSamAccount can't miss "
+ "the sambaSID attribute\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
goto done;
-
- if (!sid_check_is_in_our_domain(&sid)) {
- DEBUG(1, ("Inconsistent SAM -- group member uid not "
- "in our domain\n"));
- continue;
}
- sid_peek_rid(&sid, &rid);
-
- add_rid_to_array_unique(mem_ctx, rid, member_rids,
- num_members);
+ if (!add_rid_to_array_unique(mem_ctx, rid, pp_member_rids,
+ p_num_members)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
- result = NT_STATUS_OK;
+ ret = NT_STATUS_OK;
done:
- SAFE_FREE(sid_filter);
- if (values != NULL)
+ if (values)
ldap_value_free(values);
- if (msg != NULL)
- ldap_msgfree(msg);
-
- return result;
+ return ret;
}
static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
- const char *username,
- gid_t primary_gid,
- DOM_SID **sids, gid_t **gids,
- int *num_groups)
+ TALLOC_CTX *mem_ctx,
+ struct samu *user,
+ DOM_SID **pp_sids,
+ gid_t **pp_gids,
+ size_t *p_num_groups)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
struct smbldap_state *conn = ldap_state->smbldap_state;
- pstring filter;
+ char *filter;
const char *attrs[] = { "gidNumber", "sambaSID", NULL };
char *escape_name;
- int rc;
- LDAPMessage *msg = NULL;
+ int rc, count;
+ LDAPMessage *result = NULL;
LDAPMessage *entry;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
- int num_sids, num_gids;
-
- if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
- return pdb_default_enum_group_memberships(methods, username,
- primary_gid, sids,
- gids, num_groups);
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+ size_t num_sids, num_gids;
+ char *gidstr;
+ gid_t primary_gid = -1;
- *sids = NULL;
+ *pp_sids = NULL;
num_sids = 0;
- escape_name = escape_ldap_string_alloc(username);
+ if (pdb_get_username(user) == NULL) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ escape_name = escape_ldap_string_alloc(pdb_get_username(user));
if (escape_name == NULL)
return NT_STATUS_NO_MEMORY;
- pstr_sprintf(filter, "(&(objectClass=posixGroup)"
- "(|(memberUid=%s)(gidNumber=%d)))",
- username, primary_gid);
+ /* retrieve the users primary gid */
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=%s)(uid=%s))",
+ LDAP_OBJ_SAMBASAMACCOUNT,
+ escape_name);
+ if (filter == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ rc = smbldap_search(conn, lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ count = ldap_count_entries(priv2ld(ldap_state), result);
+
+ switch (count) {
+ case 0:
+ DEBUG(1, ("User account [%s] not found!\n", pdb_get_username(user)));
+ ret = NT_STATUS_NO_SUCH_USER;
+ goto done;
+ case 1:
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+
+ gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", mem_ctx);
+ if (!gidstr) {
+ DEBUG (1, ("Unable to find the member's gid!\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+ primary_gid = strtoul(gidstr, NULL, 10);
+ break;
+ default:
+ DEBUG(1, ("found more than one account with the same user name ?!\n"));
+ ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
+
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=%s)(|(memberUid=%s)(gidNumber=%d)))",
+ LDAP_OBJ_POSIXGROUP, escape_name, primary_gid);
+ if (filter == NULL) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
rc = smbldap_search(conn, lp_ldap_group_suffix(),
- LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg);
+ LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
if (rc != LDAP_SUCCESS)
goto done;
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
num_gids = 0;
- *gids = NULL;
+ *pp_gids = NULL;
num_sids = 0;
- *sids = NULL;
+ *pp_sids = NULL;
/* We need to add the primary group as the first gid/sid */
- add_gid_to_array_unique(NULL, primary_gid, gids, &num_gids);
+ if (!add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
/* This sid will be replaced later */
- add_sid_to_array_unique(NULL, &global_sid_NULL, sids, &num_sids);
+ if (!add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
- for (entry = ldap_first_entry(conn->ldap_struct, msg);
+ for (entry = ldap_first_entry(conn->ldap_struct, result);
entry != NULL;
entry = ldap_next_entry(conn->ldap_struct, entry))
{
goto done;
if (gid == primary_gid) {
- sid_copy(&(*sids)[0], &sid);
+ sid_copy(&(*pp_sids)[0], &sid);
} else {
- add_gid_to_array_unique(NULL, gid, gids, &num_gids);
- add_sid_to_array_unique(NULL, &sid, sids, &num_sids);
+ if (!add_gid_to_array_unique(mem_ctx, gid, pp_gids,
+ &num_gids)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ if (!add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
+ &num_sids)) {
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
}
}
- if (sid_compare(&global_sid_NULL, &(*sids)[0]) == 0) {
- DEBUG(3, ("primary group of [%s] not found\n", username));
+ if (sid_compare(&global_sid_NULL, &(*pp_sids)[0]) == 0) {
+ DEBUG(3, ("primary group of [%s] not found\n",
+ pdb_get_username(user)));
goto done;
}
- *num_groups = num_sids;
+ *p_num_groups = num_sids;
- result = NT_STATUS_OK;
+ ret = NT_STATUS_OK;
done:
SAFE_FREE(escape_name);
- if (msg != NULL)
- ldap_msgfree(msg);
-
- return result;
+ return ret;
}
/**********************************************************************
+ * Augment a posixGroup object with a sambaGroupMapping domgroup
*********************************************************************/
-static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
- gid_t gid,
- LDAPMessage **result)
+static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
+ struct ldapsam_privates *ldap_state,
+ GROUP_MAP *map)
{
- pstring filter;
+ const char *filter, *dn;
+ LDAPMessage *msg, *entry;
+ LDAPMod **mods;
+ int rc;
- pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%d))",
- LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY,
- get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
- gid);
+ filter = talloc_asprintf(mem_ctx,
+ "(&(objectClass=posixGroup)(gidNumber=%u))",
+ map->gid);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- return ldapsam_search_one_group(ldap_state, filter, result);
-}
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
+ get_attr_list(mem_ctx, groupmap_attr_list),
+ &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
-/**********************************************************************
- *********************************************************************/
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
+ ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+
+ dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
+ if (dn == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ mods = NULL;
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass",
+ "sambaGroupMapping");
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaSid",
+ sid_string_static(&map->sid));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaGroupType",
+ talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
+ map->nt_name);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
+ map->comment);
+ talloc_autofree_ldapmod(mem_ctx, mods);
+
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ return NT_STATUS_OK;
+}
static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
GROUP_MAP *map)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
- LDAPMessage *result = NULL;
+ LDAPMessage *msg = NULL;
LDAPMod **mods = NULL;
- int count;
+ const char *attrs[] = { NULL };
+ char *filter;
- char *tmp;
- pstring dn;
- LDAPMessage *entry;
+ char *dn;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS result;
- GROUP_MAP dummy;
+ DOM_SID sid;
int rc;
- if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
- map->gid))) {
- DEBUG(0, ("ldapsam_add_group_mapping_entry: Group %ld already exists in LDAP\n", (unsigned long)map->gid));
- return NT_STATUS_UNSUCCESSFUL;
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
- if (rc != LDAP_SUCCESS) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ filter = talloc_asprintf(mem_ctx, "(sambaSid=%s)",
+ sid_string_static(&map->sid));
+ if (filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
-
- if ( count == 0 ) {
- /* There's no posixGroup account, let's try to find an
- * appropriate idmap entry for aliases */
+ rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, attrs, True, &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
- pstring suffix;
- pstring filter;
- const char **attr_list;
+ if ((rc == LDAP_SUCCESS) &&
+ (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) > 0)) {
- ldap_msgfree(result);
+ DEBUG(3, ("SID %s already present in LDAP, refusing to add "
+ "group mapping entry\n",
+ sid_string_static(&map->sid)));
+ result = NT_STATUS_GROUP_EXISTS;
+ goto done;
+ }
- pstrcpy( suffix, lp_ldap_idmap_suffix() );
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))",
- LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER,
- map->gid);
-
- attr_list = get_attr_list( sidmap_attr_list );
- rc = smbldap_search(ldap_state->smbldap_state, suffix,
- LDAP_SCOPE_SUBTREE, filter, attr_list,
- 0, &result);
+ switch (map->sid_name_use) {
- free_attr_list(attr_list);
+ case SID_NAME_DOM_GRP:
+ /* To map a domain group we need to have a posix group
+ to attach to. */
+ result = ldapsam_map_posixgroup(mem_ctx, ldap_state, map);
+ goto done;
+ break;
- if (rc != LDAP_SUCCESS) {
- DEBUG(3,("Failure looking up entry (%s)\n",
- ldap_err2string(rc) ));
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ case SID_NAME_ALIAS:
+ if (!sid_check_is_in_our_domain(&map->sid)
+ && !sid_check_is_in_builtin(&map->sid) )
+ {
+ DEBUG(3, ("Refusing to map sid %s as an alias, not in our domain\n",
+ sid_string_static(&map->sid)));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
}
- }
-
- count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
- if ( count == 0 ) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
- }
+ break;
- if (count > 1) {
- DEBUG(2, ("ldapsam_add_group_mapping_entry: Group %lu must exist exactly once in LDAP\n",
- (unsigned long)map->gid));
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ default:
+ DEBUG(3, ("Got invalid use '%s' for mapping\n",
+ sid_type_lookup(map->sid_name_use)));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
- tmp = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!tmp) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ /* Domain groups have been mapped in a separate routine, we have to
+ * create an alias now */
+
+ if (map->gid == -1) {
+ DEBUG(10, ("Refusing to map gid==-1\n"));
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
}
- pstrcpy(dn, tmp);
- SAFE_FREE(tmp);
- if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
- result, &mods, map)) {
- DEBUG(0, ("ldapsam_add_group_mapping_entry: init_ldap_from_group failed!\n"));
- ldap_mods_free(mods, True);
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ if (pdb_gid_to_sid(map->gid, &sid)) {
+ DEBUG(3, ("Gid %d is already mapped to SID %s, refusing to "
+ "add\n", map->gid, sid_string_static(&sid)));
+ result = NT_STATUS_GROUP_EXISTS;
+ goto done;
}
- ldap_msgfree(result);
+ /* Ok, enough checks done. It's still racy to go ahead now, but that's
+ * the best we can get out of LDAP. */
- if (mods == NULL) {
- DEBUG(0, ("ldapsam_add_group_mapping_entry: mods is empty\n"));
- return NT_STATUS_UNSUCCESSFUL;
+ dn = talloc_asprintf(mem_ctx, "sambaSid=%s,%s",
+ sid_string_static(&map->sid),
+ lp_ldap_group_suffix());
+ if (dn == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
- smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP );
+ mods = NULL;
- rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
- ldap_mods_free(mods, True);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
+ "sambaSidEntry");
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
+ "sambaGroupMapping");
- if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0, ("ldapsam_add_group_mapping_entry: failed to add group %lu error: %s (%s)\n", (unsigned long)map->gid,
- ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
- SAFE_FREE(ld_error);
- return NT_STATUS_UNSUCCESSFUL;
- }
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaSid",
+ sid_string_static(&map->sid));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaGroupType",
+ talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "displayName",
+ map->nt_name);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "description",
+ map->comment);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "gidNumber",
+ talloc_asprintf(mem_ctx, "%u", map->gid));
+ talloc_autofree_ldapmod(mem_ctx, mods);
- DEBUG(2, ("ldapsam_add_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
- return NT_STATUS_OK;
+ rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
+
+ result = (rc == LDAP_SUCCESS) ?
+ NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+
+ done:
+ TALLOC_FREE(mem_ctx);
+ return result;
}
/**********************************************************************
+ * Update a group mapping entry. We're quite strict about what can be changed:
+ * Only the description and displayname may be changed. It simply does not
+ * make any sense to change the SID, gid or the type in a mapping.
*********************************************************************/
static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
int rc;
- char *dn = NULL;
- LDAPMessage *result = NULL;
+ const char *filter, *dn;
+ LDAPMessage *msg = NULL;
LDAPMessage *entry = NULL;
LDAPMod **mods = NULL;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS result;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
- rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
+ /* Make 100% sure that sid, gid and type are not changed by looking up
+ * exactly the values we're given in LDAP. */
- if (rc != LDAP_SUCCESS) {
- return NT_STATUS_UNSUCCESSFUL;
+ filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)"
+ "(sambaSid=%s)(gidNumber=%u)"
+ "(sambaGroupType=%d))",
+ LDAP_OBJ_GROUPMAP,
+ sid_string_static(&map->sid), map->gid,
+ map->sid_name_use);
+ if (filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
- if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
- DEBUG(0, ("ldapsam_update_group_mapping_entry: No group to modify!\n"));
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
+ get_attr_list(mem_ctx, groupmap_attr_list),
+ &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
+
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
+ ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
+ result = NT_STATUS_NO_SUCH_GROUP;
+ goto done;
}
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+ dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
- if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
- result, &mods, map)) {
- DEBUG(0, ("ldapsam_update_group_mapping_entry: init_ldap_from_group failed\n"));
- ldap_msgfree(result);
- if (mods != NULL)
- ldap_mods_free(mods,True);
- return NT_STATUS_UNSUCCESSFUL;
+ if (dn == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
}
+ mods = NULL;
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
+ map->nt_name);
+ smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
+ map->comment);
+ talloc_autofree_ldapmod(mem_ctx, mods);
+
if (mods == NULL) {
- DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: nothing to do\n"));
- ldap_msgfree(result);
- return NT_STATUS_OK;
+ DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: "
+ "nothing to do\n"));
+ result = NT_STATUS_OK;
+ goto done;
}
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!dn) {
- ldap_msgfree(result);
- return NT_STATUS_UNSUCCESSFUL;
- }
rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
- SAFE_FREE(dn);
-
- ldap_mods_free(mods, True);
- ldap_msgfree(result);
if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
- &ld_error);
- DEBUG(0, ("ldapsam_update_group_mapping_entry: failed to modify group %lu error: %s (%s)\n", (unsigned long)map->gid,
- ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
- SAFE_FREE(ld_error);
- return NT_STATUS_UNSUCCESSFUL;
+ result = NT_STATUS_ACCESS_DENIED;
+ goto done;
}
- DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
- return NT_STATUS_OK;
+ DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified "
+ "group %lu in LDAP\n", (unsigned long)map->gid));
+
+ result = NT_STATUS_OK;
+
+ done:
+ TALLOC_FREE(mem_ctx);
+ return result;
}
/**********************************************************************
static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
DOM_SID sid)
{
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
- pstring sidstring, filter;
- LDAPMessage *result = NULL;
+ struct ldapsam_privates *priv =
+ (struct ldapsam_privates *)methods->private_data;
+ LDAPMessage *msg, *entry;
int rc;
- NTSTATUS ret;
- const char **attr_list;
+ NTSTATUS result;
+ TALLOC_CTX *mem_ctx;
+ char *filter;
- sid_to_string(sidstring, &sid);
-
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
- LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
- rc = ldapsam_search_one_group(ldap_state, filter, &result);
+ filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))",
+ LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID,
+ sid_string_static(&sid));
+ if (filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ rc = smbldap_search_suffix(priv->smbldap_state, filter,
+ get_attr_list(mem_ctx, groupmap_attr_list),
+ &msg);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
- if (rc != LDAP_SUCCESS) {
- return NT_STATUS_NO_SUCH_GROUP;
+ if ((rc != LDAP_SUCCESS) ||
+ (ldap_count_entries(priv2ld(priv), msg) != 1) ||
+ ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
+ result = NT_STATUS_NO_SUCH_GROUP;
+ goto done;
+ }
+
+ rc = ldapsam_delete_entry(priv, mem_ctx, entry, LDAP_OBJ_GROUPMAP,
+ get_attr_list(mem_ctx,
+ groupmap_attr_list_to_delete));
+
+ if ((rc == LDAP_NAMING_VIOLATION) ||
+ (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
+ const char *attrs[] = { "sambaGroupType", "description",
+ "displayName", "sambaSIDList",
+ NULL };
+
+ /* Second try. Don't delete the sambaSID attribute, this is
+ for "old" entries that are tacked on a winbind
+ sambaIdmapEntry. */
+
+ rc = ldapsam_delete_entry(priv, mem_ctx, entry,
+ LDAP_OBJ_GROUPMAP, attrs);
}
- attr_list = get_attr_list( groupmap_attr_list_to_delete );
- ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
- free_attr_list ( attr_list );
+ if ((rc == LDAP_NAMING_VIOLATION) ||
+ (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
+ const char *attrs[] = { "sambaGroupType", "description",
+ "displayName", "sambaSIDList",
+ "gidNumber", NULL };
- ldap_msgfree(result);
+ /* Third try. This is a post-3.0.21 alias (containing only
+ * sambaSidEntry and sambaGroupMapping classes), we also have
+ * to delete the gidNumber attribute, only the sambaSidEntry
+ * remains */
- return ret;
-}
+ rc = ldapsam_delete_entry(priv, mem_ctx, entry,
+ LDAP_OBJ_GROUPMAP, attrs);
+ }
+
+ result = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+
+ done:
+ TALLOC_FREE(mem_ctx);
+ return result;
+ }
/**********************************************************************
*********************************************************************/
-static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
+static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
+ BOOL update)
{
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)my_methods->private_data;
fstring filter;
int rc;
const char **attr_list;
pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
- attr_list = get_attr_list( groupmap_attr_list );
+ attr_list = get_attr_list( NULL, groupmap_attr_list );
rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
LDAP_SCOPE_SUBTREE, filter,
attr_list, 0, &ldap_state->result);
- free_attr_list( attr_list );
+ TALLOC_FREE(attr_list);
if (rc != LDAP_SUCCESS) {
- DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n", ldap_err2string(rc)));
- DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n", lp_ldap_group_suffix(), filter));
+ DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n",
+ ldap_err2string(rc)));
+ DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n",
+ lp_ldap_group_suffix(), filter));
ldap_msgfree(ldap_state->result);
ldap_state->result = NULL;
return NT_STATUS_UNSUCCESSFUL;
ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
ldap_state->result)));
- ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result);
+ ldap_state->entry =
+ ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+ ldap_state->result);
ldap_state->index = 0;
return NT_STATUS_OK;
GROUP_MAP *map)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)my_methods->private_data;
BOOL bret = False;
while (!bret) {
return ret;
ldap_state->index++;
- bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
+ bret = init_group_from_ldap(ldap_state, map,
+ ldap_state->entry);
- ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
- ldap_state->entry);
+ ldap_state->entry =
+ ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
+ ldap_state->entry);
}
return NT_STATUS_OK;
*********************************************************************/
static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
- enum SID_NAME_USE sid_name_use,
- GROUP_MAP **rmap, int *num_entries,
+ const DOM_SID *domsid, enum lsa_SidType sid_name_use,
+ GROUP_MAP **pp_rmap,
+ size_t *p_num_entries,
BOOL unix_only)
{
GROUP_MAP map;
- GROUP_MAP *mapt;
- int entries = 0;
+ size_t entries = 0;
- *num_entries = 0;
- *rmap = NULL;
+ *p_num_entries = 0;
+ *pp_rmap = NULL;
if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
- DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open passdb\n"));
+ DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open "
+ "passdb\n"));
return NT_STATUS_ACCESS_DENIED;
}
while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) {
if (sid_name_use != SID_NAME_UNKNOWN &&
sid_name_use != map.sid_name_use) {
- DEBUG(11,("ldapsam_enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
+ DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
+ "not of the requested type\n", map.nt_name));
continue;
}
if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
- DEBUG(11,("ldapsam_enum_group_mapping: group %s is non mapped\n", map.nt_name));
+ DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
+ "non mapped\n", map.nt_name));
continue;
}
- mapt=SMB_REALLOC_ARRAY((*rmap), GROUP_MAP, entries+1);
- if (!mapt) {
- DEBUG(0,("ldapsam_enum_group_mapping: Unable to enlarge group map!\n"));
- SAFE_FREE(*rmap);
+ (*pp_rmap)=SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
+ if (!(*pp_rmap)) {
+ DEBUG(0,("ldapsam_enum_group_mapping: Unable to "
+ "enlarge group map!\n"));
return NT_STATUS_UNSUCCESSFUL;
}
- else
- (*rmap) = mapt;
- mapt[entries] = map;
+ (*pp_rmap)[entries] = map;
entries += 1;
}
ldapsam_endsamgrent(methods);
- *num_entries = entries;
+ *p_num_entries = entries;
return NT_STATUS_OK;
}
int count;
LDAPMod **mods = NULL;
int rc;
+ enum lsa_SidType type = SID_NAME_USE_NONE;
pstring filter;
- pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
- LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
- get_attr_key2string(groupmap_attr_list,
- LDAP_ATTR_GROUP_SID),
- sid_string_static(alias));
+ if (sid_check_is_in_builtin(alias)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (sid_check_is_in_our_domain(alias)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (type == SID_NAME_USE_NONE) {
+ DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
+ sid_string_static(alias)));
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+
+ pstr_sprintf(filter,
+ "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
+ LDAP_OBJ_GROUPMAP, sid_string_static(alias),
+ type);
if (ldapsam_search_one_group(ldap_state, filter,
&result) != LDAP_SUCCESS)
}
if (count > 1) {
- DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for filter %s: "
- "count=%d\n", filter, count));
+ DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for "
+ "filter %s: count=%d\n", filter, count));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_ALIAS;
}
ldap_mods_free(mods, True);
ldap_msgfree(result);
+ SAFE_FREE(dn);
+
+ if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
+ return NT_STATUS_MEMBER_IN_ALIAS;
+ }
+
+ if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
+ return NT_STATUS_MEMBER_NOT_IN_ALIAS;
+ }
if (rc != LDAP_SUCCESS) {
- char *ld_error = NULL;
- ldap_get_option(ldap_state->smbldap_state->ldap_struct,
- LDAP_OPT_ERROR_STRING,&ld_error);
-
- DEBUG(0, ("ldapsam_modify_aliasmem: Could not modify alias "
- "for %s, error: %s (%s)\n", dn, ldap_err2string(rc),
- ld_error?ld_error:"unknown"));
- SAFE_FREE(ld_error);
- SAFE_FREE(dn);
return NT_STATUS_UNSUCCESSFUL;
}
- SAFE_FREE(dn);
-
return NT_STATUS_OK;
}
}
static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
- const DOM_SID *alias, DOM_SID **members,
- int *num_members)
+ const DOM_SID *alias,
+ DOM_SID **pp_members,
+ size_t *p_num_members)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
char **values;
int i;
pstring filter;
+ size_t num_members = 0;
+ enum lsa_SidType type = SID_NAME_USE_NONE;
+
+ *pp_members = NULL;
+ *p_num_members = 0;
+
+ if (sid_check_is_in_builtin(alias)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (sid_check_is_in_our_domain(alias)) {
+ type = SID_NAME_ALIAS;
+ }
- *members = NULL;
- *num_members = 0;
+ if (type == SID_NAME_USE_NONE) {
+ DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
+ sid_string_static(alias)));
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
- pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
- LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
- get_attr_key2string(groupmap_attr_list,
- LDAP_ATTR_GROUP_SID),
- sid_string_static(alias));
+ pstr_sprintf(filter,
+ "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
+ LDAP_OBJ_GROUPMAP, sid_string_static(alias),
+ type);
if (ldapsam_search_one_group(ldap_state, filter,
&result) != LDAP_SUCCESS)
}
if (count > 1) {
- DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for filter %s: "
- "count=%d\n", filter, count));
+ DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for "
+ "filter %s: count=%d\n", filter, count));
ldap_msgfree(result);
return NT_STATUS_NO_SUCH_ALIAS;
}
if (!string_to_sid(&member, values[i]))
continue;
- add_sid_to_array(NULL, &member, members, num_members);
+ if (!add_sid_to_array(NULL, &member, pp_members, &num_members)) {
+ ldap_value_free(values);
+ ldap_msgfree(result);
+ return NT_STATUS_NO_MEMORY;
+ }
}
+ *p_num_members = num_members;
ldap_value_free(values);
ldap_msgfree(result);
TALLOC_CTX *mem_ctx,
const DOM_SID *domain_sid,
const DOM_SID *members,
- int num_members,
- uint32 **alias_rids,
- int *num_alias_rids)
+ size_t num_members,
+ uint32 **pp_alias_rids,
+ size_t *p_num_alias_rids)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
int i;
int rc;
char *filter;
+ enum lsa_SidType type = SID_NAME_USE_NONE;
+
+ if (sid_check_is_builtin(domain_sid)) {
+ type = SID_NAME_ALIAS;
+ }
+
+ if (sid_check_is_domain(domain_sid)) {
+ type = SID_NAME_ALIAS;
+ }
- /* This query could be further optimized by adding a
- (&(sambaSID=<domain-sid>*)) so that only those aliases that are
- asked for in the getuseraliases are returned. */
+ if (type == SID_NAME_USE_NONE) {
+ DEBUG(5, ("SID %s is neither builtin nor domain!\n",
+ sid_string_static(domain_sid)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
filter = talloc_asprintf(mem_ctx,
- "(&(|(objectclass=%s)(objectclass=%s))(|",
- LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY);
+ "(&(|(objectclass=%s)(sambaGroupType=%d))(|",
+ LDAP_OBJ_GROUPMAP, type);
for (i=0; i<num_members; i++)
filter = talloc_asprintf(mem_ctx, "%s(sambaSIDList=%s)",
filter = talloc_asprintf(mem_ctx, "%s))", filter);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
if (!sid_peek_check_rid(domain_sid, &sid, &rid))
continue;
- add_rid_to_array_unique(mem_ctx, rid, alias_rids,
- num_alias_rids);
+ if (!add_rid_to_array_unique(mem_ctx, rid, pp_alias_rids,
+ p_num_alias_rids)) {
+ ldap_msgfree(result);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ ldap_msgfree(result);
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
+ int policy_index,
+ uint32 value)
+{
+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+ int rc;
+ LDAPMod **mods = NULL;
+ fstring value_string;
+ const char *policy_attr = NULL;
+
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+
+ DEBUG(10,("ldapsam_set_account_policy_in_ldap\n"));
+
+ if (!ldap_state->domain_dn) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ policy_attr = get_account_policy_attr(policy_index);
+ if (policy_attr == NULL) {
+ DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid "
+ "policy\n"));
+ return ntstatus;
+ }
+
+ slprintf(value_string, sizeof(value_string) - 1, "%i", value);
+
+ smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
+
+ rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn,
+ mods);
+
+ ldap_mods_free(mods, True);
+
+ if (rc != LDAP_SUCCESS) {
+ return ntstatus;
+ }
+
+ if (!cache_account_policy_set(policy_index, value)) {
+ DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to "
+ "update local tdb cache\n"));
+ return ntstatus;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods,
+ int policy_index, uint32 value)
+{
+ return ldapsam_set_account_policy_in_ldap(methods, policy_index,
+ value);
+}
+
+static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods,
+ int policy_index,
+ uint32 *value)
+{
+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ int count;
+ int rc;
+ char **vals = NULL;
+ const char *policy_attr = NULL;
+
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+
+ const char *attrs[2];
+
+ DEBUG(10,("ldapsam_get_account_policy_from_ldap\n"));
+
+ if (!ldap_state->domain_dn) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ policy_attr = get_account_policy_attr(policy_index);
+ if (!policy_attr) {
+ DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid "
+ "policy index: %d\n", policy_index));
+ return ntstatus;
+ }
+
+ attrs[0] = policy_attr;
+ attrs[1] = NULL;
+
+ rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
+ LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0,
+ &result);
+
+ if (rc != LDAP_SUCCESS) {
+ return ntstatus;
+ }
+
+ count = ldap_count_entries(priv2ld(ldap_state), result);
+ if (count < 1) {
+ goto out;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (entry == NULL) {
+ goto out;
+ }
+
+ vals = ldap_get_values(priv2ld(ldap_state), entry, policy_attr);
+ if (vals == NULL) {
+ goto out;
}
+ *value = (uint32)atol(vals[0]);
+
+ ntstatus = NT_STATUS_OK;
+
+out:
+ if (vals)
+ ldap_value_free(vals);
ldap_msgfree(result);
+
+ return ntstatus;
+}
+
+/* wrapper around ldapsam_get_account_policy_from_ldap(), handles tdb as cache
+
+ - if user hasn't decided to use account policies inside LDAP just reuse the
+ old tdb values
+
+ - if there is a valid cache entry, return that
+ - if there is an LDAP entry, update cache and return
+ - otherwise set to default, update cache and return
+
+ Guenther
+*/
+static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
+ int policy_index, uint32 *value)
+{
+ NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+
+ if (cache_account_policy_get(policy_index, value)) {
+ DEBUG(11,("ldapsam_get_account_policy: got valid value from "
+ "cache\n"));
+ return NT_STATUS_OK;
+ }
+
+ ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index,
+ value);
+ if (NT_STATUS_IS_OK(ntstatus)) {
+ goto update_cache;
+ }
+
+ DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from "
+ "ldap\n"));
+
+#if 0
+ /* should we automagically migrate old tdb value here ? */
+ if (account_policy_get(policy_index, value))
+ goto update_ldap;
+
+ DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying "
+ "default\n", policy_index));
+#endif
+
+ if (!account_policy_get_default(policy_index, value)) {
+ return ntstatus;
+ }
+
+/* update_ldap: */
+
+ ntstatus = ldapsam_set_account_policy(methods, policy_index, *value);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ return ntstatus;
+ }
+
+ update_cache:
+
+ if (!cache_account_policy_set(policy_index, *value)) {
+ DEBUG(0,("ldapsam_get_account_policy: failed to update local "
+ "tdb as a cache\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
return NT_STATUS_OK;
}
static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
- TALLOC_CTX *mem_ctx,
const DOM_SID *domain_sid,
int num_rids,
uint32 *rids,
- const char ***names,
- uint32 **attrs)
+ const char **names,
+ enum lsa_SidType *attrs)
{
struct ldapsam_privates *ldap_state =
(struct ldapsam_privates *)methods->private_data;
- LDAP *ldap_struct = ldap_state->smbldap_state->ldap_struct;
LDAPMessage *msg = NULL;
LDAPMessage *entry;
char *allsids = NULL;
- char *tmp;
int i, rc, num_mapped;
- NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
- if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
- return pdb_default_lookup_rids(methods, mem_ctx, domain_sid,
- num_rids, rids, names, attrs);
+ NTSTATUS result = NT_STATUS_NO_MEMORY;
+ TALLOC_CTX *mem_ctx;
+ LDAP *ld;
+ BOOL is_builtin;
- if (!sid_equal(domain_sid, get_global_sam_sid())) {
- /* TODO: Sooner or later we need to look up BUILTIN rids as
- * well. -- vl */
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
goto done;
}
- (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids);
- (*attrs) = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
-
- if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL)))
- return NT_STATUS_NO_MEMORY;
+ if (!sid_check_is_builtin(domain_sid) &&
+ !sid_check_is_domain(domain_sid)) {
+ result = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
for (i=0; i<num_rids; i++)
- (*attrs)[i] = SID_NAME_UNKNOWN;
+ attrs[i] = SID_NAME_UNKNOWN;
- allsids = SMB_STRDUP("");
- if (allsids == NULL) return NT_STATUS_NO_MEMORY;
+ allsids = talloc_strdup(mem_ctx, "");
+ if (allsids == NULL) {
+ goto done;
+ }
for (i=0; i<num_rids; i++) {
DOM_SID sid;
- sid_copy(&sid, domain_sid);
- sid_append_rid(&sid, rids[i]);
- tmp = allsids;
- asprintf(&allsids, "%s(sambaSid=%s)", allsids,
- sid_string_static(&sid));
- if (allsids == NULL) return NT_STATUS_NO_MEMORY;
- free(tmp);
+ sid_compose(&sid, domain_sid, rids[i]);
+ allsids = talloc_asprintf_append_buffer(allsids, "(sambaSid=%s)",
+ sid_string_static(&sid));
+ if (allsids == NULL) {
+ goto done;
+ }
}
/* First look for users */
char *filter;
const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
- asprintf(&filter, ("(&(objectClass=sambaSamAccount)(|%s))"),
- allsids);
- if (filter == NULL) return NT_STATUS_NO_MEMORY;
+ filter = talloc_asprintf(
+ mem_ctx, ("(&(objectClass=%s)(|%s))"),
+ LDAP_OBJ_SAMBASAMACCOUNT, allsids);
+
+ if (filter == NULL) {
+ goto done;
+ }
rc = smbldap_search(ldap_state->smbldap_state,
lp_ldap_user_suffix(),
LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
&msg);
-
- SAFE_FREE(filter);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
}
if (rc != LDAP_SUCCESS)
goto done;
+ ld = ldap_state->smbldap_state->ldap_struct;
num_mapped = 0;
- for (entry = ldap_first_entry(ldap_struct, msg);
+ for (entry = ldap_first_entry(ld, msg);
entry != NULL;
- entry = ldap_next_entry(ldap_struct, entry))
- {
+ entry = ldap_next_entry(ld, entry)) {
uint32 rid;
int rid_index;
- fstring str;
+ const char *name;
- if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
- get_global_sam_sid(),
+ if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
&rid)) {
DEBUG(2, ("Could not find sid from ldap entry\n"));
continue;
}
- if (!smbldap_get_single_attribute(ldap_struct, entry,
- "uid", str, sizeof(str)-1)) {
+ name = smbldap_talloc_single_attribute(ld, entry, "uid",
+ names);
+ if (name == NULL) {
DEBUG(2, ("Could not retrieve uid attribute\n"));
continue;
}
continue;
}
- (*attrs)[rid_index] = SID_NAME_USER;
- (*names)[rid_index] = talloc_strdup(mem_ctx, str);
- if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
-
+ attrs[rid_index] = SID_NAME_USER;
+ names[rid_index] = name;
num_mapped += 1;
}
{
char *filter;
- const char *ldap_attrs[] = { "cn", "sambaSid", NULL };
+ const char *ldap_attrs[] = { "cn", "displayName", "sambaSid",
+ "sambaGroupType", NULL };
- asprintf(&filter, ("(&(objectClass=sambaGroupMapping)(|%s))"),
- allsids);
- if (filter == NULL) return NT_STATUS_NO_MEMORY;
+ filter = talloc_asprintf(
+ mem_ctx, "(&(objectClass=%s)(|%s))",
+ LDAP_OBJ_GROUPMAP, allsids);
+ if (filter == NULL) {
+ goto done;
+ }
rc = smbldap_search(ldap_state->smbldap_state,
lp_ldap_group_suffix(),
LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
&msg);
-
- SAFE_FREE(filter);
+ talloc_autofree_ldapmsg(mem_ctx, msg);
}
if (rc != LDAP_SUCCESS)
goto done;
- for (entry = ldap_first_entry(ldap_struct, msg);
+ /* ldap_struct might have changed due to a reconnect */
+
+ ld = ldap_state->smbldap_state->ldap_struct;
+
+ /* For consistency checks, we already checked we're only domain or builtin */
+
+ is_builtin = sid_check_is_builtin(domain_sid);
+
+ for (entry = ldap_first_entry(ld, msg);
entry != NULL;
- entry = ldap_next_entry(ldap_struct, entry))
+ entry = ldap_next_entry(ld, entry))
{
uint32 rid;
int rid_index;
- fstring str;
+ const char *attr;
+ enum lsa_SidType type;
+ const char *dn = smbldap_talloc_dn(mem_ctx, ld, entry);
+
+ attr = smbldap_talloc_single_attribute(ld, entry, "sambaGroupType",
+ mem_ctx);
+ if (attr == NULL) {
+ DEBUG(2, ("Could not extract type from ldap entry %s\n",
+ dn));
+ continue;
+ }
- if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
- get_global_sam_sid(),
+ type = (enum lsa_SidType)atol(attr);
+
+ /* Consistency checks */
+ if ((is_builtin && (type != SID_NAME_ALIAS)) ||
+ (!is_builtin && ((type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_DOM_GRP)))) {
+ DEBUG(2, ("Rejecting invalid group mapping entry %s\n", dn));
+ }
+
+ if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
&rid)) {
- DEBUG(2, ("Could not find sid from ldap entry\n"));
+ DEBUG(2, ("Could not find sid from ldap entry %s\n", dn));
continue;
}
- if (!smbldap_get_single_attribute(ldap_struct, entry,
- "cn", str, sizeof(str)-1)) {
- DEBUG(2, ("Could not retrieve cn attribute\n"));
+ attr = smbldap_talloc_single_attribute(ld, entry, "displayName", names);
+
+ if (attr == NULL) {
+ DEBUG(10, ("Could not retrieve 'displayName' attribute from %s\n",
+ dn));
+ attr = smbldap_talloc_single_attribute(ld, entry, "cn", names);
+ }
+
+ if (attr == NULL) {
+ DEBUG(2, ("Could not retrieve naming attribute from %s\n",
+ dn));
continue;
}
continue;
}
- (*attrs)[rid_index] = SID_NAME_DOM_GRP;
- (*names)[rid_index] = talloc_strdup(mem_ctx, str);
- if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
+ attrs[rid_index] = type;
+ names[rid_index] = attr;
num_mapped += 1;
}
result = (num_mapped == num_rids) ?
NT_STATUS_OK : STATUS_SOME_UNMAPPED;
done:
- SAFE_FREE(allsids);
+ TALLOC_FREE(mem_ctx);
+ return result;
+}
- if (msg != NULL)
- ldap_msgfree(msg);
-
- return result;
-}
-
-char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
+static char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username)
{
char *filter = NULL;
char *escaped = NULL;
escaped = escape_ldap_string_alloc(username);
if (escaped == NULL) goto done;
- filter = realloc_string_sub(filter, "%u", username);
- result = talloc_strdup(mem_ctx, filter);
+ result = talloc_string_sub(mem_ctx, filter, "%u", username);
done:
SAFE_FREE(filter);
num += 1;
va_end(ap);
- result = TALLOC_ARRAY(mem_ctx, const char *, num+1);
+ if ((result = TALLOC_ARRAY(mem_ctx, const char *, num+1)) == NULL) {
+ return NULL;
+ }
va_start(ap, mem_ctx);
- for (i=0; i<num; i++)
- result[i] = talloc_strdup(mem_ctx, va_arg(ap, const char*));
+ for (i=0; i<num; i++) {
+ result[i] = talloc_strdup(result, va_arg(ap, const char*));
+ if (result[i] == NULL) {
+ talloc_free(result);
+ return NULL;
+ }
+ }
va_end(ap);
result[num] = NULL;
struct ldap_search_state {
struct smbldap_state *connection;
- uint16 acct_flags;
+ uint32 acct_flags;
uint16 group_type;
const char *base;
static BOOL ldapsam_search_firstpage(struct pdb_search *search)
{
- struct ldap_search_state *state = search->private_data;
+ struct ldap_search_state *state =
+ (struct ldap_search_state *)search->private_data;
LDAP *ld;
int rc = LDAP_OPERATIONS_ERROR;
static BOOL ldapsam_search_nextpage(struct pdb_search *search)
{
- struct ldap_search_state *state = search->private_data;
- LDAP *ld = state->connection->ldap_struct;
+ struct ldap_search_state *state =
+ (struct ldap_search_state *)search->private_data;
int rc;
if (!state->connection->paged_results) {
if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
return False;
- state->current_entry = ldap_first_entry(ld, state->entries);
+ state->current_entry = ldap_first_entry(state->connection->ldap_struct, state->entries);
if (state->current_entry == NULL) {
ldap_msgfree(state->entries);
static BOOL ldapsam_search_next_entry(struct pdb_search *search,
struct samr_displayentry *entry)
{
- struct ldap_search_state *state = search->private_data;
- LDAP *ld = state->connection->ldap_struct;
+ struct ldap_search_state *state =
+ (struct ldap_search_state *)search->private_data;
BOOL result;
retry:
!ldapsam_search_nextpage(search))
return False;
- result = state->ldap2displayentry(state, search->mem_ctx, ld,
+ result = state->ldap2displayentry(state, search->mem_ctx, state->connection->ldap_struct,
state->current_entry, entry);
if (!result) {
char *dn;
- dn = ldap_get_dn(ld, state->current_entry);
+ dn = ldap_get_dn(state->connection->ldap_struct, state->current_entry);
DEBUG(5, ("Skipping entry %s\n", dn != NULL ? dn : "<NULL>"));
if (dn != NULL) ldap_memfree(dn);
}
- state->current_entry = ldap_next_entry(ld, state->current_entry);
+ state->current_entry = ldap_next_entry(state->connection->ldap_struct, state->current_entry);
if (state->current_entry == NULL) {
ldap_msgfree(state->entries);
static void ldapsam_search_end(struct pdb_search *search)
{
- struct ldap_search_state *state = search->private_data;
+ struct ldap_search_state *state =
+ (struct ldap_search_state *)search->private_data;
int rc;
if (state->pagedresults_cookie == NULL)
{
char **vals;
DOM_SID sid;
- uint16 acct_flags;
+ uint32 acct_flags;
vals = ldap_get_values(ld, entry, "sambaAcctFlags");
if ((vals == NULL) || (vals[0] == NULL)) {
ldap_value_free(vals);
if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
- DEBUG(0, ("sid %s does not belong to our domain\n", sid_string_static(&sid)));
+ DEBUG(0, ("sid %s does not belong to our domain\n",
+ sid_string_static(&sid)));
return False;
}
static BOOL ldapsam_search_users(struct pdb_methods *methods,
struct pdb_search *search,
- uint16 acct_flags)
+ uint32 acct_flags)
{
- struct ldapsam_privates *ldap_state = methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
struct ldap_search_state *state;
state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
vals = ldap_get_values(ld, entry, "sambaGroupType");
if ((vals == NULL) || (vals[0] == NULL)) {
DEBUG(5, ("\"sambaGroupType\" not found\n"));
+ if (vals != NULL) {
+ ldap_value_free(vals);
+ }
return False;
}
if ((state->group_type != 0) &&
((state->group_type != group_type))) {
+ ldap_value_free(vals);
return False;
}
- vals = ldap_get_values(ld, entry, "cn");
- if ((vals == NULL) || (vals[0] == NULL)) {
- DEBUG(5, ("\"cn\" not found\n"));
- return False;
- }
- pull_utf8_talloc(mem_ctx,
- CONST_DISCARD(char **, &result->account_name),
- vals[0]);
ldap_value_free(vals);
+ /* display name is the NT group name */
+
vals = ldap_get_values(ld, entry, "displayName");
- if ((vals == NULL) || (vals[0] == NULL))
+ if ((vals == NULL) || (vals[0] == NULL)) {
DEBUG(8, ("\"displayName\" not found\n"));
- else
+
+ /* fallback to the 'cn' attribute */
+ vals = ldap_get_values(ld, entry, "cn");
+ if ((vals == NULL) || (vals[0] == NULL)) {
+ DEBUG(5, ("\"cn\" not found\n"));
+ return False;
+ }
pull_utf8_talloc(mem_ctx,
- CONST_DISCARD(char **, &result->fullname),
+ CONST_DISCARD(char **, &result->account_name),
+ vals[0]);
+ }
+ else {
+ pull_utf8_talloc(mem_ctx,
+ CONST_DISCARD(char **, &result->account_name),
vals[0]);
+ }
+
ldap_value_free(vals);
vals = ldap_get_values(ld, entry, "description");
vals = ldap_get_values(ld, entry, "sambaSid");
if ((vals == NULL) || (vals[0] == NULL)) {
DEBUG(0, ("\"objectSid\" not found\n"));
+ if (vals != NULL) {
+ ldap_value_free(vals);
+ }
return False;
}
case SID_NAME_DOM_GRP:
case SID_NAME_ALIAS:
- if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
- DEBUG(0, ("%s is not in our domain\n", sid_string_static(&sid)));
+ if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)
+ && !sid_peek_check_rid(&global_sid_Builtin, &sid, &result->rid))
+ {
+ DEBUG(0, ("%s is not in our domain\n",
+ sid_string_static(&sid)));
return False;
}
break;
- case SID_NAME_WKN_GRP:
-
- if (!sid_check_is_in_builtin(&sid)) {
- DEBUG(0, ("%s is not in builtin sid\n", sid_string_static(&sid)));
- return False;
- }
- break;
-
default:
DEBUG(0,("unkown group type: %d\n", group_type));
return False;
static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
struct pdb_search *search,
- enum SID_NAME_USE type)
+ const DOM_SID *sid,
+ enum lsa_SidType type)
{
- struct ldapsam_privates *ldap_state = methods->private_data;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
struct ldap_search_state *state;
state = TALLOC_P(search->mem_ctx, struct ldap_search_state);
state->scope = LDAP_SCOPE_SUBTREE;
state->filter = talloc_asprintf(search->mem_ctx,
"(&(objectclass=sambaGroupMapping)"
- "(sambaGroupType=%d))", type);
+ "(sambaGroupType=%d)(sambaSID=%s*))",
+ type, sid_string_static(sid));
state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid",
- "displayName", "description", "sambaGroupType", NULL);
+ "displayName", "description",
+ "sambaGroupType", NULL);
state->attrsonly = 0;
state->pagedresults_cookie = NULL;
state->entries = NULL;
static BOOL ldapsam_search_groups(struct pdb_methods *methods,
struct pdb_search *search)
{
- return ldapsam_search_grouptype(methods, search, SID_NAME_DOM_GRP);
+ return ldapsam_search_grouptype(methods, search, get_global_sam_sid(), SID_NAME_DOM_GRP);
}
static BOOL ldapsam_search_aliases(struct pdb_methods *methods,
struct pdb_search *search,
const DOM_SID *sid)
{
- if (sid_check_is_domain(sid))
- return ldapsam_search_grouptype(methods, search,
- SID_NAME_ALIAS);
-
- if (sid_check_is_builtin(sid))
- return ldapsam_search_grouptype(methods, search,
- SID_NAME_WKN_GRP);
+ return ldapsam_search_grouptype(methods, search, sid, SID_NAME_ALIAS);
+}
- DEBUG(5, ("Don't know SID %s\n", sid_string_static(sid)));
+static BOOL ldapsam_rid_algorithm(struct pdb_methods *methods)
+{
return False;
}
-/**********************************************************************
- Housekeeping
- *********************************************************************/
-
-static void free_private_data(void **vp)
+static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
+ uint32 *rid)
{
- struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
+ struct smbldap_state *smbldap_state = priv->smbldap_state;
- smbldap_free_struct(&(*ldap_state)->smbldap_state);
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ LDAPMod **mods = NULL;
+ NTSTATUS status;
+ char *value;
+ int rc;
+ uint32 nextRid = 0;
+ const char *dn;
- if ((*ldap_state)->result != NULL) {
- ldap_msgfree((*ldap_state)->result);
- (*ldap_state)->result = NULL;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- if ((*ldap_state)->domain_dn != NULL) {
- SAFE_FREE((*ldap_state)->domain_dn);
+
+ status = smbldap_search_domain_info(smbldap_state, &result,
+ get_global_sam_name(), False);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3, ("Could not get domain info: %s\n",
+ nt_errstr(status)));
+ goto done;
}
- *ldap_state = NULL;
+ talloc_autofree_ldapmsg(mem_ctx, result);
- /* No need to free any further, as it is talloc()ed */
-}
+ entry = ldap_first_entry(priv2ld(priv), result);
+ if (entry == NULL) {
+ DEBUG(0, ("Could not get domain info entry\n"));
+ status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ goto done;
+ }
-/**********************************************************************
- Intitalise the parts of the pdb_context that are common to all pdb_ldap modes
- *********************************************************************/
+ /* Find the largest of the three attributes "sambaNextRid",
+ "sambaNextGroupRid" and "sambaNextUserRid". I gave up on the
+ concept of differentiating between user and group rids, and will
+ use only "sambaNextRid" in the future. But for compatibility
+ reasons I look if others have chosen different strategies -- VL */
-static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method,
- const char *location)
-{
- NTSTATUS nt_status;
- struct ldapsam_privates *ldap_state;
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaNextRid", mem_ctx);
+ if (value != NULL) {
+ uint32 tmp = (uint32)strtoul(value, NULL, 10);
+ nextRid = MAX(nextRid, tmp);
+ }
- if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
- return nt_status;
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaNextUserRid", mem_ctx);
+ if (value != NULL) {
+ uint32 tmp = (uint32)strtoul(value, NULL, 10);
+ nextRid = MAX(nextRid, tmp);
}
- (*pdb_method)->name = "ldapsam";
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaNextGroupRid", mem_ctx);
+ if (value != NULL) {
+ uint32 tmp = (uint32)strtoul(value, NULL, 10);
+ nextRid = MAX(nextRid, tmp);
+ }
- (*pdb_method)->setsampwent = ldapsam_setsampwent;
- (*pdb_method)->endsampwent = ldapsam_endsampwent;
- (*pdb_method)->getsampwent = ldapsam_getsampwent;
- (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
- (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
- (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
- (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
- (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
+ if (nextRid == 0) {
+ nextRid = BASE_RID-1;
+ }
- (*pdb_method)->getgrsid = ldapsam_getgrsid;
- (*pdb_method)->getgrgid = ldapsam_getgrgid;
- (*pdb_method)->getgrnam = ldapsam_getgrnam;
- (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
- (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
- (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
- (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
- (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
- (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships;
- (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
+ nextRid += 1;
- /* TODO: Setup private data and free */
+ smbldap_make_mod(priv2ld(priv), entry, &mods, "sambaNextRid",
+ talloc_asprintf(mem_ctx, "%d", nextRid));
+ talloc_autofree_ldapmod(mem_ctx, mods);
- ldap_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct ldapsam_privates);
- if (!ldap_state) {
- DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
- return NT_STATUS_NO_MEMORY;
+ if ((dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)) == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
}
- if (!NT_STATUS_IS_OK(nt_status =
- smbldap_init(pdb_context->mem_ctx, location,
- &ldap_state->smbldap_state)));
+ rc = smbldap_modify(smbldap_state, dn, mods);
- ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name());
- if (!ldap_state->domain_name) {
- return NT_STATUS_NO_MEMORY;
- }
+ /* ACCESS_DENIED is used as a placeholder for "the modify failed,
+ * please retry" */
- (*pdb_method)->private_data = ldap_state;
+ status = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
- (*pdb_method)->free_private_data = free_private_data;
+ done:
+ if (NT_STATUS_IS_OK(status)) {
+ *rid = nextRid;
+ }
- return NT_STATUS_OK;
+ TALLOC_FREE(mem_ctx);
+ return status;
}
-/**********************************************************************
- Initialise the 'compat' mode for pdb_ldap
- *********************************************************************/
-
-NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS ldapsam_new_rid_internal(struct pdb_methods *methods, uint32 *rid)
{
- NTSTATUS nt_status;
- struct ldapsam_privates *ldap_state;
+ int i;
-#ifdef WITH_LDAP_SAMCONFIG
- if (!location) {
- int ldap_port = lp_ldap_port();
-
- /* remap default port if not using SSL (ie clear or TLS) */
- if ( (lp_ldap_ssl() != LDAP_SSL_ON) && (ldap_port == 636) ) {
- ldap_port = 389;
+ for (i=0; i<10; i++) {
+ NTSTATUS result = ldapsam_get_new_rid(
+ (struct ldapsam_privates *)methods->private_data, rid);
+ if (NT_STATUS_IS_OK(result)) {
+ return result;
}
- location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port);
- if (!location) {
- return NT_STATUS_NO_MEMORY;
+ if (!NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
+ return result;
}
+
+ /* The ldap update failed (maybe a race condition), retry */
}
-#endif
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
- return nt_status;
+ /* Tried 10 times, fail. */
+ return NT_STATUS_ACCESS_DENIED;
+}
+
+static BOOL ldapsam_new_rid(struct pdb_methods *methods, uint32 *rid)
+{
+ NTSTATUS result = ldapsam_new_rid_internal(methods, rid);
+ return NT_STATUS_IS_OK(result) ? True : False;
+}
+
+static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
+ const DOM_SID *sid,
+ union unid_t *id, enum lsa_SidType *type)
+{
+ struct ldapsam_privates *priv =
+ (struct ldapsam_privates *)methods->private_data;
+ char *filter;
+ const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
+ NULL };
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ BOOL ret = False;
+ char *value;
+ int rc;
+
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ DEBUG(0, ("talloc_new failed\n"));
+ return False;
}
- (*pdb_method)->name = "ldapsam_compat";
+ filter = talloc_asprintf(mem_ctx,
+ "(&(sambaSid=%s)"
+ "(|(objectClass=%s)(objectClass=%s)))",
+ sid_string_static(sid),
+ LDAP_OBJ_GROUPMAP, LDAP_OBJ_SAMBASAMACCOUNT);
+ if (filter == NULL) {
+ DEBUG(5, ("talloc_asprintf failed\n"));
+ goto done;
+ }
- ldap_state = (*pdb_method)->private_data;
- ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
+ rc = smbldap_search_suffix(priv->smbldap_state, filter,
+ attrs, &result);
+ if (rc != LDAP_SUCCESS) {
+ goto done;
+ }
+ talloc_autofree_ldapmsg(mem_ctx, result);
- sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
+ if (ldap_count_entries(priv2ld(priv), result) != 1) {
+ DEBUG(10, ("Got %d entries, expected one\n",
+ ldap_count_entries(priv2ld(priv), result)));
+ goto done;
+ }
- return NT_STATUS_OK;
+ entry = ldap_first_entry(priv2ld(priv), result);
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "sambaGroupType", mem_ctx);
+
+ if (value != NULL) {
+ const char *gid_str;
+ /* It's a group */
+
+ gid_str = smbldap_talloc_single_attribute(
+ priv2ld(priv), entry, "gidNumber", mem_ctx);
+ if (gid_str == NULL) {
+ DEBUG(1, ("%s has sambaGroupType but no gidNumber\n",
+ smbldap_talloc_dn(mem_ctx, priv2ld(priv),
+ entry)));
+ goto done;
+ }
+
+ id->gid = strtoul(gid_str, NULL, 10);
+ *type = (enum lsa_SidType)strtoul(value, NULL, 10);
+ ret = True;
+ goto done;
+ }
+
+ /* It must be a user */
+
+ value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+ "uidNumber", mem_ctx);
+ if (value == NULL) {
+ DEBUG(1, ("Could not find uidNumber in %s\n",
+ smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)));
+ goto done;
+ }
+
+ id->uid = strtoul(value, NULL, 10);
+ *type = SID_NAME_USER;
+
+ ret = True;
+ done:
+ TALLOC_FREE(mem_ctx);
+ return ret;
}
-/**********************************************************************
- Initialise the normal mode for pdb_ldap
- *********************************************************************/
+/*
+ * The following functions is called only if
+ * ldapsam:trusted and ldapsam:editposix are
+ * set to true
+ */
+
+/*
+ * ldapsam_create_user creates a new
+ * posixAccount and sambaSamAccount object
+ * in the ldap users subtree
+ *
+ * The uid is allocated by winbindd.
+ */
-NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
+ TALLOC_CTX *tmp_ctx, const char *name,
+ uint32 acb_info, uint32 *rid)
{
- NTSTATUS nt_status;
- struct ldapsam_privates *ldap_state;
- uint32 alg_rid_base;
- pstring alg_rid_base_string;
- LDAPMessage *result = NULL;
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
LDAPMessage *entry = NULL;
- DOM_SID ldap_domain_sid;
- DOM_SID secrets_domain_sid;
- pstring domain_sid_string;
- char *dn;
-
- if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
- return nt_status;
+ LDAPMessage *result = NULL;
+ uint32 num_result;
+ BOOL is_machine = False;
+ BOOL add_posix = False;
+ LDAPMod **mods = NULL;
+ struct samu *user;
+ char *filter;
+ char *username;
+ char *homedir;
+ char *gidstr;
+ char *uidstr;
+ char *shell;
+ const char *dn = NULL;
+ DOM_SID group_sid;
+ DOM_SID user_sid;
+ gid_t gid = -1;
+ uid_t uid = -1;
+ NTSTATUS ret;
+ int rc;
+
+ if (((acb_info & ACB_NORMAL) && name[strlen(name)-1] == '$') ||
+ acb_info & ACB_WSTRUST ||
+ acb_info & ACB_SVRTRUST ||
+ acb_info & ACB_DOMTRUST) {
+ is_machine = True;
}
- (*pdb_method)->name = "ldapsam";
+ username = escape_ldap_string_alloc(name);
+ filter = talloc_asprintf(tmp_ctx, "(&(uid=%s)(objectClass=%s))",
+ username, LDAP_OBJ_POSIXACCOUNT);
+ SAFE_FREE(username);
- (*pdb_method)->add_aliasmem = ldapsam_add_aliasmem;
- (*pdb_method)->del_aliasmem = ldapsam_del_aliasmem;
- (*pdb_method)->enum_aliasmem = ldapsam_enum_aliasmem;
- (*pdb_method)->enum_alias_memberships = ldapsam_alias_memberships;
- (*pdb_method)->search_users = ldapsam_search_users;
- (*pdb_method)->search_groups = ldapsam_search_groups;
- (*pdb_method)->search_aliases = ldapsam_search_aliases;
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_create_user: ldap search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
- ldap_state = (*pdb_method)->private_data;
- ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
- /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
-
- nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result,
- ldap_state->domain_name, True);
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_create_user: More than one user with name [%s] ?!\n", name));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
- if ( !NT_STATUS_IS_OK(nt_status) ) {
- DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain info, nor add one to the domain\n"));
- DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, will be unable to allocate new users/groups, \
-and will risk BDCs having inconsistant SIDs\n"));
- sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
- return NT_STATUS_OK;
+ if (num_result == 1) {
+ char *tmp;
+ /* check if it is just a posix account.
+ * or if there is a sid attached to this entry
+ */
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "sambaSID", tmp_ctx);
+ if (tmp) {
+ DEBUG (1, ("ldapsam_create_user: The user [%s] already exist!\n", name));
+ return NT_STATUS_USER_EXISTS;
+ }
+
+ /* it is just a posix account, retrieve the dn for later use */
+ dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_create_user: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
}
- /* Given that the above might fail, everything below this must be optional */
+ if (num_result == 0) {
+ add_posix = True;
+ }
- entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
- if (!entry) {
- DEBUG(0, ("pdb_init_ldapsam: Could not get domain info entry\n"));
- ldap_msgfree(result);
+ /* Create the basic samu structure and generate the mods for the ldap commit */
+ if (!NT_STATUS_IS_OK((ret = ldapsam_new_rid_internal(my_methods, rid)))) {
+ DEBUG(1, ("ldapsam_create_user: Could not allocate a new RID\n"));
+ return ret;
+ }
+
+ sid_compose(&user_sid, get_global_sam_sid(), *rid);
+
+ user = samu_new(tmp_ctx);
+ if (!user) {
+ DEBUG(1,("ldapsam_create_user: Unable to allocate user struct\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_username(user, name, PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ if (!pdb_set_domain(user, get_global_sam_name(), PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ if (is_machine) {
+ if (acb_info & ACB_NORMAL) {
+ if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ } else {
+ if (!pdb_set_acct_ctrl(user, acb_info, PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+ } else {
+ if (!pdb_set_acct_ctrl(user, ACB_NORMAL | ACB_DISABLED, PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ if (!pdb_set_user_sid(user, &user_sid, PDB_SET)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
return NT_STATUS_UNSUCCESSFUL;
}
- dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
- if (!dn) {
+ if (!init_ldap_from_sam(ldap_state, NULL, &mods, user, element_is_set_or_changed)) {
+ DEBUG(1,("ldapsam_create_user: Unable to fill user structs\n"));
return NT_STATUS_UNSUCCESSFUL;
}
- ldap_state->domain_dn = smb_xstrdup(dn);
- ldap_memfree(dn);
+ if (ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT) {
+ DEBUG(1,("ldapsam_create_user: Unsupported schema version\n"));
+ }
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
- if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
- domain_sid_string)) {
- BOOL found_sid;
- if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
- DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be read as a valid SID\n", domain_sid_string));
+ if (add_posix) {
+ char *escape_name;
+
+ DEBUG(3,("ldapsam_create_user: Creating new posix user\n"));
+
+ /* retrieve the Domain Users group gid */
+ if (!sid_compose(&group_sid, get_global_sam_sid(), DOMAIN_GROUP_RID_USERS) ||
+ !sid_to_gid(&group_sid, &gid)) {
+ DEBUG (0, ("ldapsam_create_user: Unable to get the Domain Users gid: bailing out!\n"));
+ return NT_STATUS_INVALID_PRIMARY_GROUP;
+ }
+
+ /* lets allocate a new userid for this user */
+ if (!winbind_allocate_uid(&uid)) {
+ DEBUG (0, ("ldapsam_create_user: Unable to allocate a new user id: bailing out!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+
+ if (is_machine) {
+ /* TODO: choose a more appropriate default for machines */
+ homedir = talloc_sub_specified(tmp_ctx, lp_template_homedir(), "SMB_workstations_home", ldap_state->domain_name, uid, gid);
+ shell = talloc_strdup(tmp_ctx, "/bin/false");
+ } else {
+ homedir = talloc_sub_specified(tmp_ctx, lp_template_homedir(), name, ldap_state->domain_name, uid, gid);
+ shell = talloc_sub_specified(tmp_ctx, lp_template_shell(), name, ldap_state->domain_name, uid, gid);
+ }
+ uidstr = talloc_asprintf(tmp_ctx, "%d", uid);
+ gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
+
+ escape_name = escape_rdn_val_string_alloc(name);
+ if (!escape_name) {
+ DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (is_machine) {
+ dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_machine_suffix ());
+ } else {
+ dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_user_suffix ());
+ }
+
+ SAFE_FREE(escape_name);
+
+ if (!homedir || !shell || !uidstr || !gidstr || !dn) {
+ DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_ACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_POSIXACCOUNT);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", homedir);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", shell);
+ }
+
+ talloc_autofree_ldapmod(tmp_ctx, mods);
+
+ if (add_posix) {
+ rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
+ } else {
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_create_user: failed to create a new user [%s] (dn = %s)\n", name ,dn));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ DEBUG(2,("ldapsam_create_user: added account [%s] in the LDAP database\n", name));
+
+ flush_pwnam_cache();
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_delete_user(struct pdb_methods *my_methods, TALLOC_CTX *tmp_ctx, struct samu *sam_acct)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ int num_result;
+ const char *dn;
+ char *filter;
+ int rc;
+
+ DEBUG(0,("ldapsam_delete_user: Attempt to delete user [%s]\n", pdb_get_username(sam_acct)));
+
+ filter = talloc_asprintf(tmp_ctx,
+ "(&(uid=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ pdb_get_username(sam_acct),
+ LDAP_OBJ_POSIXACCOUNT,
+ LDAP_OBJ_SAMBASAMACCOUNT);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_delete_user: user search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result == 0) {
+ DEBUG(0,("ldapsam_delete_user: user not found!\n"));
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_delete_user: More than one user with name [%s] ?!\n", pdb_get_username(sam_acct)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* it is just a posix account, retrieve the dn for later use */
+ dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_delete_user: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = smbldap_delete(ldap_state->smbldap_state, dn);
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ flush_pwnam_cache();
+
+ return NT_STATUS_OK;
+}
+
+/*
+ * ldapsam_create_group creates a new
+ * posixGroup and sambaGroupMapping object
+ * in the ldap groups subtree
+ *
+ * The gid is allocated by winbindd.
+ */
+
+static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
+ TALLOC_CTX *tmp_ctx,
+ const char *name,
+ uint32 *rid)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ NTSTATUS ret;
+ LDAPMessage *entry = NULL;
+ LDAPMessage *result = NULL;
+ uint32 num_result;
+ BOOL is_new_entry = False;
+ LDAPMod **mods = NULL;
+ char *filter;
+ char *groupsidstr;
+ char *groupname;
+ char *grouptype;
+ char *gidstr;
+ const char *dn = NULL;
+ DOM_SID group_sid;
+ gid_t gid = -1;
+ int rc;
+
+ groupname = escape_ldap_string_alloc(name);
+ filter = talloc_asprintf(tmp_ctx, "(&(cn=%s)(objectClass=%s))",
+ groupname, LDAP_OBJ_POSIXGROUP);
+ SAFE_FREE(groupname);
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_create_group: ldap search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_create_group: There exists more than one group with name [%s]: bailing out!\n", name));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (num_result == 1) {
+ char *tmp;
+ /* check if it is just a posix group.
+ * or if there is a sid attached to this entry
+ */
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "sambaSID", tmp_ctx);
+ if (tmp) {
+ DEBUG (1, ("ldapsam_create_group: The group [%s] already exist!\n", name));
+ return NT_STATUS_GROUP_EXISTS;
+ }
+
+ /* it is just a posix group, retrieve the gid and the dn for later use */
+ tmp = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
+ if (!tmp) {
+ DEBUG (1, ("ldapsam_create_group: Couldn't retrieve the gidNumber for [%s]?!?!\n", name));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ gid = strtoul(tmp, NULL, 10);
+
+ dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_create_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ if (num_result == 0) {
+ char *escape_name;
+
+ DEBUG(3,("ldapsam_create_user: Creating new posix group\n"));
+
+ is_new_entry = True;
+
+ /* lets allocate a new groupid for this group */
+ if (!winbind_allocate_gid(&gid)) {
+ DEBUG (0, ("ldapsam_create_group: Unable to allocate a new group id: bailing out!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
+
+ escape_name = escape_rdn_val_string_alloc(name);
+ if (!escape_name) {
+ DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", escape_name, lp_ldap_group_suffix());
+
+ SAFE_FREE(escape_name);
+
+ if (!gidstr || !dn) {
+ DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_POSIXGROUP);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "cn", name);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
+ }
+
+ if (!NT_STATUS_IS_OK((ret = ldapsam_new_rid_internal(my_methods, rid)))) {
+ DEBUG(1, ("ldapsam_create_group: Could not allocate a new RID\n"));
+ return ret;
+ }
+
+ sid_compose(&group_sid, get_global_sam_sid(), *rid);
+
+ groupsidstr = talloc_strdup(tmp_ctx, sid_string_static(&group_sid));
+ grouptype = talloc_asprintf(tmp_ctx, "%d", SID_NAME_DOM_GRP);
+
+ if (!groupsidstr || !grouptype) {
+ DEBUG(0,("ldapsam_create_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSid", groupsidstr);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaGroupType", grouptype);
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", name);
+ talloc_autofree_ldapmod(tmp_ctx, mods);
+
+ if (is_new_entry) {
+ rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
+#if 0
+ if (rc == LDAP_OBJECT_CLASS_VIOLATION) {
+ /* This call may fail with rfc2307bis schema */
+ /* Retry adding a structural class */
+ smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", "????");
+ rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
+ }
+#endif
+ } else {
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_create_group: failed to create a new group [%s] (dn = %s)\n", name ,dn));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ DEBUG(2,("ldapsam_create_group: added group [%s] in the LDAP database\n", name));
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_delete_dom_group(struct pdb_methods *my_methods, TALLOC_CTX *tmp_ctx, uint32 rid)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ int num_result;
+ const char *dn;
+ char *gidstr;
+ char *filter;
+ DOM_SID group_sid;
+ int rc;
+
+ /* get the group sid */
+ sid_compose(&group_sid, get_global_sam_sid(), rid);
+
+ filter = talloc_asprintf(tmp_ctx,
+ "(&(sambaSID=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ sid_string_static(&group_sid),
+ LDAP_OBJ_POSIXGROUP,
+ LDAP_OBJ_GROUPMAP);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1,("ldapsam_delete_dom_group: group search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result == 0) {
+ DEBUG(1,("ldapsam_delete_dom_group: group not found!\n"));
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_delete_dom_group: More than one group with the same SID ?!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* here it is, retrieve the dn for later use */
+ dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_delete_dom_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
+ if (!gidstr) {
+ DEBUG (0, ("ldapsam_delete_dom_group: Unable to find the group's gid!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ /* check no user have this group marked as primary group */
+ filter = talloc_asprintf(tmp_ctx,
+ "(&(gidNumber=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ gidstr,
+ LDAP_OBJ_POSIXACCOUNT,
+ LDAP_OBJ_SAMBASAMACCOUNT);
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1,("ldapsam_delete_dom_group: accounts search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result != 0) {
+ DEBUG(3,("ldapsam_delete_dom_group: Can't delete group, it is a primary group for %d users\n", num_result));
+ return NT_STATUS_MEMBERS_PRIMARY_GROUP;
+ }
+
+ rc = smbldap_delete(ldap_state->smbldap_state, dn);
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_change_groupmem(struct pdb_methods *my_methods,
+ TALLOC_CTX *tmp_ctx,
+ uint32 group_rid,
+ uint32 member_rid,
+ int modop)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ LDAPMessage *entry = NULL;
+ LDAPMessage *result = NULL;
+ uint32 num_result;
+ LDAPMod **mods = NULL;
+ char *filter;
+ char *uidstr;
+ const char *dn = NULL;
+ DOM_SID group_sid;
+ DOM_SID member_sid;
+ int rc;
+
+ switch (modop) {
+ case LDAP_MOD_ADD:
+ DEBUG(1,("ldapsam_change_groupmem: add new member(rid=%d) to a domain group(rid=%d)", member_rid, group_rid));
+ break;
+ case LDAP_MOD_DELETE:
+ DEBUG(1,("ldapsam_change_groupmem: delete member(rid=%d) from a domain group(rid=%d)", member_rid, group_rid));
+ break;
+ default:
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* get member sid */
+ sid_compose(&member_sid, get_global_sam_sid(), member_rid);
+
+ /* get the group sid */
+ sid_compose(&group_sid, get_global_sam_sid(), group_rid);
+
+ filter = talloc_asprintf(tmp_ctx,
+ "(&(sambaSID=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ sid_string_static(&member_sid),
+ LDAP_OBJ_POSIXACCOUNT,
+ LDAP_OBJ_SAMBASAMACCOUNT);
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* get the member uid */
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1,("ldapsam_change_groupmem: member search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result == 0) {
+ DEBUG(1,("ldapsam_change_groupmem: member not found!\n"));
+ return NT_STATUS_NO_SUCH_MEMBER;
+ }
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_change_groupmem: More than one account with the same SID ?!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (modop == LDAP_MOD_DELETE) {
+ /* check if we are trying to remove the member from his primary group */
+ char *gidstr;
+ gid_t user_gid, group_gid;
+
+ gidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "gidNumber", tmp_ctx);
+ if (!gidstr) {
+ DEBUG (0, ("ldapsam_change_groupmem: Unable to find the member's gid!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ user_gid = strtoul(gidstr, NULL, 10);
+
+ if (!sid_to_gid(&group_sid, &group_gid)) {
+ DEBUG (0, ("ldapsam_change_groupmem: Unable to get group gid from SID!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (user_gid == group_gid) {
+ DEBUG (3, ("ldapsam_change_groupmem: can't remove user from it's own primary group!\n"));
+ return NT_STATUS_MEMBERS_PRIMARY_GROUP;
+ }
+ }
+
+ /* here it is, retrieve the uid for later use */
+ uidstr = smbldap_talloc_single_attribute(priv2ld(ldap_state), entry, "uid", tmp_ctx);
+ if (!uidstr) {
+ DEBUG (0, ("ldapsam_change_groupmem: Unable to find the member's name!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ filter = talloc_asprintf(tmp_ctx,
+ "(&(sambaSID=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ sid_string_static(&group_sid),
+ LDAP_OBJ_POSIXGROUP,
+ LDAP_OBJ_GROUPMAP);
+
+ /* get the group */
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1,("ldapsam_change_groupmem: group search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(tmp_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result == 0) {
+ DEBUG(1,("ldapsam_change_groupmem: group not found!\n"));
+ return NT_STATUS_NO_SUCH_GROUP;
+ }
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_change_groupmem: More than one group with the same SID ?!\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* here it is, retrieve the dn for later use */
+ dn = smbldap_talloc_dn(tmp_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_change_groupmem: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ smbldap_set_mod(&mods, modop, "memberUid", uidstr);
+
+ talloc_autofree_ldapmod(tmp_ctx, mods);
+
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+ if (rc != LDAP_SUCCESS) {
+ if (rc == LDAP_TYPE_OR_VALUE_EXISTS && modop == LDAP_MOD_ADD) {
+ DEBUG(1,("ldapsam_change_groupmem: member is already in group, add failed!\n"));
+ return NT_STATUS_MEMBER_IN_GROUP;
+ }
+ if (rc == LDAP_NO_SUCH_ATTRIBUTE && modop == LDAP_MOD_DELETE) {
+ DEBUG(1,("ldapsam_change_groupmem: member is not in group, delete failed!\n"));
+ return NT_STATUS_MEMBER_NOT_IN_GROUP;
+ }
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_add_groupmem(struct pdb_methods *my_methods,
+ TALLOC_CTX *tmp_ctx,
+ uint32 group_rid,
+ uint32 member_rid)
+{
+ return ldapsam_change_groupmem(my_methods, tmp_ctx, group_rid, member_rid, LDAP_MOD_ADD);
+}
+static NTSTATUS ldapsam_del_groupmem(struct pdb_methods *my_methods,
+ TALLOC_CTX *tmp_ctx,
+ uint32 group_rid,
+ uint32 member_rid)
+{
+ return ldapsam_change_groupmem(my_methods, tmp_ctx, group_rid, member_rid, LDAP_MOD_DELETE);
+}
+
+static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
+ TALLOC_CTX *mem_ctx,
+ struct samu *sampass)
+{
+ struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+ LDAPMessage *entry = NULL;
+ LDAPMessage *result = NULL;
+ uint32 num_result;
+ LDAPMod **mods = NULL;
+ char *filter;
+ char *escape_username;
+ char *gidstr;
+ const char *dn = NULL;
+ gid_t gid;
+ int rc;
+
+ DEBUG(0,("ldapsam_set_primary_group: Attempt to set primary group for user [%s]\n", pdb_get_username(sampass)));
+
+ if (!sid_to_gid(pdb_get_group_sid(sampass), &gid)) {
+ DEBUG(0,("ldapsam_set_primary_group: failed to retieve gid from user's group SID!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ gidstr = talloc_asprintf(mem_ctx, "%d", gid);
+ if (!gidstr) {
+ DEBUG(0,("ldapsam_set_primary_group: Out of Memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ escape_username = escape_ldap_string_alloc(pdb_get_username(sampass));
+ if (escape_username== NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ filter = talloc_asprintf(mem_ctx,
+ "(&(uid=%s)"
+ "(objectClass=%s)"
+ "(objectClass=%s))",
+ escape_username,
+ LDAP_OBJ_POSIXACCOUNT,
+ LDAP_OBJ_SAMBASAMACCOUNT);
+
+ SAFE_FREE(escape_username);
+
+ if (filter == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_set_primary_group: user search failed!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+ talloc_autofree_ldapmsg(mem_ctx, result);
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result == 0) {
+ DEBUG(0,("ldapsam_set_primary_group: user not found!\n"));
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ if (num_result > 1) {
+ DEBUG (0, ("ldapsam_set_primary_group: More than one user with name [%s] ?!\n", pdb_get_username(sampass)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ entry = ldap_first_entry(priv2ld(ldap_state), result);
+ if (!entry) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* retrieve the dn for later use */
+ dn = smbldap_talloc_dn(mem_ctx, priv2ld(ldap_state), entry);
+ if (!dn) {
+ DEBUG(0,("ldapsam_set_primary_group: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* remove the old one, and add the new one, this way we do not risk races */
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "gidNumber", gidstr);
+
+ if (mods == NULL) {
+ return NT_STATUS_OK;
+ }
+
+ rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0,("ldapsam_set_primary_group: failed to modify [%s] primary group to [%s]\n",
+ pdb_get_username(sampass), gidstr));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ flush_pwnam_cache();
+
+ return NT_STATUS_OK;
+}
+
+
+/**********************************************************************
+ trusted domains functions
+ *********************************************************************/
+
+static char *trusteddom_dn(struct ldapsam_privates *ldap_state,
+ const char *domain)
+{
+ return talloc_asprintf(talloc_tos(), "sambaDomainName=%s,%s", domain,
+ ldap_state->domain_dn);
+}
+
+static BOOL get_trusteddom_pw_int(struct ldapsam_privates *ldap_state,
+ const char *domain, LDAPMessage **entry)
+{
+ int rc;
+ char *filter;
+ int scope = LDAP_SCOPE_SUBTREE;
+ const char **attrs = NULL; /* NULL: get all attrs */
+ int attrsonly = 0; /* 0: return values too */
+ LDAPMessage *result = NULL;
+ char *trusted_dn;
+ uint32 num_result;
+
+ filter = talloc_asprintf(talloc_tos(),
+ "(&(objectClass=%s)(sambaDomainName=%s))",
+ LDAP_OBJ_TRUSTDOM_PASSWORD, domain);
+
+ trusted_dn = trusteddom_dn(ldap_state, domain);
+ if (trusted_dn == NULL) {
+ return False;
+ }
+ rc = smbldap_search(ldap_state->smbldap_state, trusted_dn, scope,
+ filter, attrs, attrsonly, &result);
+
+ if (rc == LDAP_NO_SUCH_OBJECT) {
+ *entry = NULL;
+ return True;
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ return False;
+ }
+
+ num_result = ldap_count_entries(priv2ld(ldap_state), result);
+
+ if (num_result > 1) {
+ DEBUG(1, ("ldapsam_get_trusteddom_pw: more than one "
+ "sambaTrustedDomainPassword object for domain '%s'"
+ "?!\n", domain));
+ return False;
+ }
+
+ if (num_result == 0) {
+ DEBUG(1, ("ldapsam_get_trusteddom_pw: no "
+ "sambaTrustedDomainPassword object for domain %s.\n",
+ domain));
+ *entry = NULL;
+ } else {
+ *entry = ldap_first_entry(priv2ld(ldap_state), result);
+ }
+
+ return True;
+}
+
+static BOOL ldapsam_get_trusteddom_pw(struct pdb_methods *methods,
+ const char *domain,
+ char** pwd,
+ DOM_SID *sid,
+ time_t *pass_last_set_time)
+{
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+ LDAPMessage *entry = NULL;
+
+ DEBUG(10, ("ldapsam_get_trusteddom_pw called for domain %s\n", domain));
+
+ if (!get_trusteddom_pw_int(ldap_state, domain, &entry) ||
+ (entry == NULL))
+ {
+ return False;
+ }
+
+ /* password */
+ if (pwd != NULL) {
+ char *pwd_str;
+ pwd_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+ entry, "sambaClearTextPassword", talloc_tos());
+ if (pwd_str == NULL) {
+ return False;
+ }
+ /* trusteddom_pw routines do not use talloc yet... */
+ *pwd = SMB_STRDUP(pwd_str);
+ if (*pwd == NULL) {
+ return False;
+ }
+ }
+
+ /* last change time */
+ if (pass_last_set_time != NULL) {
+ char *time_str;
+ time_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+ entry, "sambaPwdLastSet", talloc_tos());
+ if (time_str == NULL) {
+ return False;
+ }
+ *pass_last_set_time = (time_t)atol(time_str);
+ }
+
+ /* domain sid */
+ if (sid != NULL) {
+ char *sid_str;
+ DOM_SID *dom_sid;
+ sid_str = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+ entry, "sambaSID",
+ talloc_tos());
+ if (sid_str == NULL) {
+ return False;
+ }
+ dom_sid = string_sid_talloc(talloc_tos(), sid_str);
+ if (dom_sid == NULL) {
+ return False;
+ }
+ sid_copy(sid, dom_sid);
+ }
+
+ return True;
+}
+
+static BOOL ldapsam_set_trusteddom_pw(struct pdb_methods *methods,
+ const char* domain,
+ const char* pwd,
+ const DOM_SID *sid)
+{
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+ LDAPMessage *entry = NULL;
+ LDAPMod **mods = NULL;
+ char *prev_pwd = NULL;
+ char *trusted_dn = NULL;
+ int rc;
+
+ DEBUG(10, ("ldapsam_set_trusteddom_pw called for domain %s\n", domain));
+
+ /*
+ * get the current entry (if there is one) in order to put the
+ * current password into the previous password attribute
+ */
+ if (!get_trusteddom_pw_int(ldap_state, domain, &entry)) {
+ return False;
+ }
+
+ mods = NULL;
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
+ "sambaTrustedDomainPassword");
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaDomainName",
+ domain);
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaSID",
+ sid_string_tos(sid));
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "sambaPwdLastSet",
+ talloc_asprintf(talloc_tos(), "%li", time(NULL)));
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+ "sambaClearTextPassword", pwd);
+ if (entry != NULL) {
+ prev_pwd = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+ entry, "sambaClearTextPassword", talloc_tos());
+ if (prev_pwd != NULL) {
+ smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+ "sambaPreviousClearTextPassword",
+ prev_pwd);
+ }
+ }
+
+ trusted_dn = trusteddom_dn(ldap_state, domain);
+ if (trusted_dn == NULL) {
+ return False;
+ }
+ if (entry == NULL) {
+ rc = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
+ } else {
+ rc = smbldap_modify(ldap_state->smbldap_state, trusted_dn, mods);
+ }
+
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(1, ("error writing trusted domain password!\n"));
+ return False;
+ }
+
+ return True;
+}
+
+static BOOL ldapsam_del_trusteddom_pw(struct pdb_methods *methods,
+ const char *domain)
+{
+ int rc;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+ LDAPMessage *entry = NULL;
+ const char *trusted_dn;
+
+ if (!get_trusteddom_pw_int(ldap_state, domain, &entry)) {
+ return False;
+ }
+
+ if (entry == NULL) {
+ DEBUG(5, ("ldapsam_del_trusteddom_pw: no such trusted domain: "
+ "%s\n", domain));
+ return True;
+ }
+
+ trusted_dn = smbldap_talloc_dn(talloc_tos(), priv2ld(ldap_state),
+ entry);
+ if (trusted_dn == NULL) {
+ DEBUG(0,("ldapsam_del_trusteddom_pw: Out of memory!\n"));
+ return False;
+ }
+
+ rc = smbldap_delete(ldap_state->smbldap_state, trusted_dn);
+ if (rc != LDAP_SUCCESS) {
+ return False;
+ }
+
+ return True;
+}
+
+static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ uint32 *num_domains,
+ struct trustdom_info ***domains)
+{
+ int rc;
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+ char *filter;
+ int scope = LDAP_SCOPE_SUBTREE;
+ const char *attrs[] = { "sambaDomainName", "sambaSID", NULL };
+ int attrsonly = 0; /* 0: return values too */
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+
+ filter = talloc_asprintf(talloc_tos(), "(objectClass=%s)",
+ LDAP_OBJ_TRUSTDOM_PASSWORD);
+
+ rc = smbldap_search(ldap_state->smbldap_state,
+ ldap_state->domain_dn,
+ scope,
+ filter,
+ attrs,
+ attrsonly,
+ &result);
+
+ if (rc != LDAP_SUCCESS) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ *num_domains = 0;
+ if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *, 1))) {
+ DEBUG(1, ("talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (entry = ldap_first_entry(priv2ld(ldap_state), result);
+ entry != NULL;
+ entry = ldap_next_entry(priv2ld(ldap_state), entry))
+ {
+ char *dom_name, *dom_sid_str;
+ struct trustdom_info *dom_info;
+
+ dom_info = TALLOC_P(*domains, struct trustdom_info);
+ if (dom_info == NULL) {
+ DEBUG(1, ("talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ dom_name = smbldap_talloc_single_attribute(priv2ld(ldap_state),
+ entry,
+ "sambaDomainName",
+ talloc_tos());
+ if (dom_name == NULL) {
+ DEBUG(1, ("talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ dom_info->name = dom_name;
+
+ dom_sid_str = smbldap_talloc_single_attribute(
+ priv2ld(ldap_state), entry, "sambaSID",
+ talloc_tos());
+ if (dom_sid_str == NULL) {
+ DEBUG(1, ("talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ if (!string_to_sid(&dom_info->sid, dom_sid_str)) {
+ DEBUG(1, ("Error calling string_to_sid on SID %s\n",
+ dom_sid_str));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ADD_TO_ARRAY(*domains, struct trustdom_info *, dom_info,
+ domains, num_domains);
+
+ if (*domains == NULL) {
+ DEBUG(1, ("talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ DEBUG(5, ("ldapsam_enum_trusteddoms: got %d domains\n", *num_domains));
+ return NT_STATUS_OK;
+}
+
+
+/**********************************************************************
+ Housekeeping
+ *********************************************************************/
+
+static void free_private_data(void **vp)
+{
+ struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp;
+
+ smbldap_free_struct(&(*ldap_state)->smbldap_state);
+
+ if ((*ldap_state)->result != NULL) {
+ ldap_msgfree((*ldap_state)->result);
+ (*ldap_state)->result = NULL;
+ }
+ if ((*ldap_state)->domain_dn != NULL) {
+ SAFE_FREE((*ldap_state)->domain_dn);
+ }
+
+ *ldap_state = NULL;
+
+ /* No need to free any further, as it is talloc()ed */
+}
+
+/*********************************************************************
+ Intitalise the parts of the pdb_methods structure that are common to
+ all pdb_ldap modes
+*********************************************************************/
+
+static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const char *location)
+{
+ NTSTATUS nt_status;
+ struct ldapsam_privates *ldap_state;
+
+ if (!NT_STATUS_IS_OK(nt_status = make_pdb_method( pdb_method ))) {
+ return nt_status;
+ }
+
+ (*pdb_method)->name = "ldapsam";
+
+ (*pdb_method)->setsampwent = ldapsam_setsampwent;
+ (*pdb_method)->endsampwent = ldapsam_endsampwent;
+ (*pdb_method)->getsampwent = ldapsam_getsampwent;
+ (*pdb_method)->getsampwnam = ldapsam_getsampwnam;
+ (*pdb_method)->getsampwsid = ldapsam_getsampwsid;
+ (*pdb_method)->add_sam_account = ldapsam_add_sam_account;
+ (*pdb_method)->update_sam_account = ldapsam_update_sam_account;
+ (*pdb_method)->delete_sam_account = ldapsam_delete_sam_account;
+ (*pdb_method)->rename_sam_account = ldapsam_rename_sam_account;
+
+ (*pdb_method)->getgrsid = ldapsam_getgrsid;
+ (*pdb_method)->getgrgid = ldapsam_getgrgid;
+ (*pdb_method)->getgrnam = ldapsam_getgrnam;
+ (*pdb_method)->add_group_mapping_entry = ldapsam_add_group_mapping_entry;
+ (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
+ (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
+ (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
+
+ (*pdb_method)->get_account_policy = ldapsam_get_account_policy;
+ (*pdb_method)->set_account_policy = ldapsam_set_account_policy;
+
+ (*pdb_method)->get_seq_num = ldapsam_get_seq_num;
+
+ (*pdb_method)->rid_algorithm = ldapsam_rid_algorithm;
+ (*pdb_method)->new_rid = ldapsam_new_rid;
+
+ (*pdb_method)->get_trusteddom_pw = ldapsam_get_trusteddom_pw;
+ (*pdb_method)->set_trusteddom_pw = ldapsam_set_trusteddom_pw;
+ (*pdb_method)->del_trusteddom_pw = ldapsam_del_trusteddom_pw;
+ (*pdb_method)->enum_trusteddoms = ldapsam_enum_trusteddoms;
+
+ /* TODO: Setup private data and free */
+
+ if ( !(ldap_state = TALLOC_ZERO_P(*pdb_method, struct ldapsam_privates)) ) {
+ DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ nt_status = smbldap_init(*pdb_method, pdb_get_event_context(),
+ location, &ldap_state->smbldap_state);
+
+ if ( !NT_STATUS_IS_OK(nt_status) ) {
+ return nt_status;
+ }
+
+ if ( !(ldap_state->domain_name = talloc_strdup(*pdb_method, get_global_sam_name()) ) ) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ (*pdb_method)->private_data = ldap_state;
+
+ (*pdb_method)->free_private_data = free_private_data;
+
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+ Initialise the 'compat' mode for pdb_ldap
+ *********************************************************************/
+
+NTSTATUS pdb_init_ldapsam_compat(struct pdb_methods **pdb_method, const char *location)
+{
+ NTSTATUS nt_status;
+ struct ldapsam_privates *ldap_state;
+ char *uri = talloc_strdup( NULL, location );
+
+ trim_char( uri, '\"', '\"' );
+ nt_status = pdb_init_ldapsam_common( pdb_method, uri );
+ if ( uri )
+ TALLOC_FREE( uri );
+
+ if ( !NT_STATUS_IS_OK(nt_status) ) {
+ return nt_status;
+ }
+
+ (*pdb_method)->name = "ldapsam_compat";
+
+ ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
+ ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT;
+
+ sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
+
+ return NT_STATUS_OK;
+}
+
+/**********************************************************************
+ Initialise the normal mode for pdb_ldap
+ *********************************************************************/
+
+NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
+{
+ NTSTATUS nt_status;
+ struct ldapsam_privates *ldap_state;
+ uint32 alg_rid_base;
+ pstring alg_rid_base_string;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry = NULL;
+ DOM_SID ldap_domain_sid;
+ DOM_SID secrets_domain_sid;
+ pstring domain_sid_string;
+ char *dn;
+ char *uri = talloc_strdup( NULL, location );
+
+ trim_char( uri, '\"', '\"' );
+ nt_status = pdb_init_ldapsam_common(pdb_method, uri);
+ if ( uri )
+ TALLOC_FREE( uri );
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ (*pdb_method)->name = "ldapsam";
+
+ (*pdb_method)->add_aliasmem = ldapsam_add_aliasmem;
+ (*pdb_method)->del_aliasmem = ldapsam_del_aliasmem;
+ (*pdb_method)->enum_aliasmem = ldapsam_enum_aliasmem;
+ (*pdb_method)->enum_alias_memberships = ldapsam_alias_memberships;
+ (*pdb_method)->search_users = ldapsam_search_users;
+ (*pdb_method)->search_groups = ldapsam_search_groups;
+ (*pdb_method)->search_aliases = ldapsam_search_aliases;
+
+ if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+ (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
+ (*pdb_method)->enum_group_memberships =
+ ldapsam_enum_group_memberships;
+ (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
+ (*pdb_method)->sid_to_id = ldapsam_sid_to_id;
+
+ if (lp_parm_bool(-1, "ldapsam", "editposix", False)) {
+ (*pdb_method)->create_user = ldapsam_create_user;
+ (*pdb_method)->delete_user = ldapsam_delete_user;
+ (*pdb_method)->create_dom_group = ldapsam_create_dom_group;
+ (*pdb_method)->delete_dom_group = ldapsam_delete_dom_group;
+ (*pdb_method)->add_groupmem = ldapsam_add_groupmem;
+ (*pdb_method)->del_groupmem = ldapsam_del_groupmem;
+ (*pdb_method)->set_unix_primary_group = ldapsam_set_primary_group;
+ }
+ }
+
+ ldap_state = (struct ldapsam_privates *)((*pdb_method)->private_data);
+ ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
+
+ /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
+
+ nt_status = smbldap_search_domain_info(ldap_state->smbldap_state,
+ &result,
+ ldap_state->domain_name, True);
+
+ if ( !NT_STATUS_IS_OK(nt_status) ) {
+ DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain "
+ "info, nor add one to the domain\n"));
+ DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, "
+ "will be unable to allocate new users/groups, "
+ "and will risk BDCs having inconsistant SIDs\n"));
+ sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
+ return NT_STATUS_OK;
+ }
+
+ /* Given that the above might fail, everything below this must be
+ * optional */
+
+ entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+ result);
+ if (!entry) {
+ DEBUG(0, ("pdb_init_ldapsam: Could not get domain info "
+ "entry\n"));
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ if (!dn) {
+ ldap_msgfree(result);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ldap_state->domain_dn = smb_xstrdup(dn);
+ ldap_memfree(dn);
+
+ if (smbldap_get_single_pstring(
+ ldap_state->smbldap_state->ldap_struct,
+ entry,
+ get_userattr_key2string(ldap_state->schema_ver,
+ LDAP_ATTR_USER_SID),
+ domain_sid_string)) {
+ BOOL found_sid;
+ if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
+ DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
+ "read as a valid SID\n", domain_sid_string));
+ ldap_msgfree(result);
return NT_STATUS_INVALID_PARAMETER;
}
- found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid);
- if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) {
+ found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
+ &secrets_domain_sid);
+ if (!found_sid || !sid_equal(&secrets_domain_sid,
+ &ldap_domain_sid)) {
fstring new_sid_str, old_sid_str;
- DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain %s based on pdb_ldap results %s -> %s\n",
- ldap_state->domain_name,
- sid_to_string(old_sid_str, &secrets_domain_sid),
- sid_to_string(new_sid_str, &ldap_domain_sid)));
+ DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain "
+ "%s based on pdb_ldap results %s -> %s\n",
+ ldap_state->domain_name,
+ sid_to_string(old_sid_str,
+ &secrets_domain_sid),
+ sid_to_string(new_sid_str,
+ &ldap_domain_sid)));
/* reset secrets.tdb sid */
- secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid);
- DEBUG(1, ("New global sam SID: %s\n", sid_to_string(new_sid_str, get_global_sam_sid())));
+ secrets_store_domain_sid(ldap_state->domain_name,
+ &ldap_domain_sid);
+ DEBUG(1, ("New global sam SID: %s\n",
+ sid_to_string(new_sid_str,
+ get_global_sam_sid())));
}
sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
}
- if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
- get_attr_key2string( dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE ),
- alg_rid_base_string)) {
+ if (smbldap_get_single_pstring(
+ ldap_state->smbldap_state->ldap_struct,
+ entry,
+ get_attr_key2string( dominfo_attr_list,
+ LDAP_ATTR_ALGORITHMIC_RID_BASE ),
+ alg_rid_base_string)) {
alg_rid_base = (uint32)atol(alg_rid_base_string);
if (alg_rid_base != algorithmic_rid_base()) {
- DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n"
+ DEBUG(0, ("The value of 'algorithmic RID base' has "
+ "changed since the LDAP\n"
"database was initialised. Aborting. \n"));
ldap_msgfree(result);
return NT_STATUS_UNSUCCESSFUL;