diff options
author | Andrew Bartlett <abartlet@samba.org> | 2011-06-24 16:26:23 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2011-06-24 16:26:23 +1000 |
commit | 6da26870e0ae5acd6ff49a30ec2f6886b44d095e (patch) | |
tree | 850c71039563c16a5d563c47e7ba2ab645baf198 /source3/passdb | |
parent | 6925a799d04c6fa59dd2ddef1f5510f9bb7d17d1 (diff) | |
parent | 2610c05b5b95cc7036b3d6dfb894c6cfbdb68483 (diff) | |
download | samba-6da26870e0ae5acd6ff49a30ec2f6886b44d095e.tar.gz samba-6da26870e0ae5acd6ff49a30ec2f6886b44d095e.tar.bz2 samba-6da26870e0ae5acd6ff49a30ec2f6886b44d095e.zip |
Merge 2610c05b5b95cc7036b3d6dfb894c6cfbdb68483 as Samba-4.0alpha16
Diffstat (limited to 'source3/passdb')
-rw-r--r-- | source3/passdb/login_cache.c | 5 | ||||
-rw-r--r-- | source3/passdb/lookup_sid.c | 14 | ||||
-rw-r--r-- | source3/passdb/machine_account_secrets.c | 59 | ||||
-rw-r--r-- | source3/passdb/machine_sid.c | 8 | ||||
-rw-r--r-- | source3/passdb/machine_sid.h | 21 | ||||
-rw-r--r-- | source3/passdb/passdb.c | 17 | ||||
-rw-r--r-- | source3/passdb/pdb_get_set.c | 5 | ||||
-rw-r--r-- | source3/passdb/pdb_interface.c | 108 | ||||
-rw-r--r-- | source3/passdb/pdb_ipa.c | 6 | ||||
-rw-r--r-- | source3/passdb/pdb_ldap.c | 28 | ||||
-rw-r--r-- | source3/passdb/pdb_samba4.c | 2100 | ||||
-rw-r--r-- | source3/passdb/pdb_smbpasswd.c | 8 | ||||
-rw-r--r-- | source3/passdb/pdb_tdb.c | 1 | ||||
-rw-r--r-- | source3/passdb/pdb_wbc_sam.c | 2 | ||||
-rw-r--r-- | source3/passdb/proto.h | 40 | ||||
-rw-r--r-- | source3/passdb/secrets.c | 5 | ||||
-rw-r--r-- | source3/passdb/wscript_build | 13 |
17 files changed, 2388 insertions, 52 deletions
diff --git a/source3/passdb/login_cache.c b/source3/passdb/login_cache.c index 1785a4daca..a53fe5b24f 100644 --- a/source3/passdb/login_cache.c +++ b/source3/passdb/login_cache.c @@ -20,6 +20,7 @@ #include "includes.h" #include "system/filesys.h" #include "passdb.h" +#include "util_tdb.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_PASSDB @@ -58,10 +59,10 @@ bool login_cache_init(void) bool login_cache_shutdown(void) { - /* tdb_close routine returns -1 on error */ + /* tdb_close routine returns non-zero on error */ if (!cache) return False; DEBUG(5, ("Closing cache file\n")); - return tdb_close(cache) != -1; + return tdb_close(cache) == 0; } /* if we can't read the cache, oh well, no need to return anything */ diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 5cf391f11c..8b5330c097 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -482,8 +482,8 @@ static bool lookup_rids(TALLOC_CTX *mem_ctx, const struct dom_sid *domain_sid, sid_string_dbg(domain_sid))); if (num_rids) { - *names = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids); - *types = TALLOC_ARRAY(mem_ctx, enum lsa_SidType, num_rids); + *names = talloc_zero_array(mem_ctx, const char *, num_rids); + *types = talloc_array(mem_ctx, enum lsa_SidType, num_rids); if ((*names == NULL) || (*types == NULL)) { return false; @@ -750,7 +750,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, } if (num_sids) { - name_infos = TALLOC_ARRAY(mem_ctx, struct lsa_name_info, num_sids); + name_infos = talloc_array(mem_ctx, struct lsa_name_info, num_sids); if (name_infos == NULL) { result = NT_STATUS_NO_MEMORY; goto fail; @@ -759,7 +759,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, name_infos = NULL; } - dom_infos = TALLOC_ZERO_ARRAY(mem_ctx, struct lsa_dom_info, + dom_infos = talloc_zero_array(mem_ctx, struct lsa_dom_info, LSA_REF_DOMAIN_LIST_MULTIPLIER); if (dom_infos == NULL) { result = NT_STATUS_NO_MEMORY; @@ -896,7 +896,7 @@ NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids, } if (dom->num_idxs) { - if (!(rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs))) { + if (!(rids = talloc_array(tmp_ctx, uint32, dom->num_idxs))) { result = NT_STATUS_NO_MEMORY; goto fail; } @@ -1404,7 +1404,7 @@ bool sids_to_unix_ids(const struct dom_sid *sids, uint32_t num_sids, wbcErr err; bool ret = false; - wbc_sids = TALLOC_ARRAY(talloc_tos(), struct wbcDomainSid, num_sids); + wbc_sids = talloc_array(talloc_tos(), struct wbcDomainSid, num_sids); if (wbc_sids == NULL) { return false; } @@ -1455,7 +1455,7 @@ bool sids_to_unix_ids(const struct dom_sid *sids, uint32_t num_sids, if (num_not_cached == 0) { goto done; } - wbc_ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId, num_not_cached); + wbc_ids = talloc_array(talloc_tos(), struct wbcUnixId, num_not_cached); if (wbc_ids == NULL) { goto fail; } diff --git a/source3/passdb/machine_account_secrets.c b/source3/passdb/machine_account_secrets.c index a51a99c9a2..665e2f89a4 100644 --- a/source3/passdb/machine_account_secrets.c +++ b/source3/passdb/machine_account_secrets.c @@ -28,6 +28,7 @@ #include "secrets.h" #include "dbwrap.h" #include "../librpc/ndr/libndr.h" +#include "util_tdb.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_PASSDB @@ -56,6 +57,17 @@ bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid) { bool ret; +#ifdef _SAMBA_WAF_BUILD_ + if (strequal(domain, get_global_sam_name()) && + (pdb_capabilities() & PDB_CAP_ADS)) { + /* If we have a ADS-capable passdb backend, we + * must never make up our own SID, it will + * already be in the directory */ + DEBUG(0, ("Refusing to store a Domain SID, this should be read from the directory not stored here\n")); + return false; + } +#endif + ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid )); /* Force a re-query, in case we modified our domain */ @@ -69,6 +81,24 @@ bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid) struct dom_sid *dyn_sid; size_t size = 0; +#ifdef _SAMBA_WAF_BUILD_ + if (strequal(domain, get_global_sam_name()) && + (pdb_capabilities() & PDB_CAP_ADS)) { + struct pdb_domain_info *domain_info; + domain_info = pdb_get_domain_info(talloc_tos()); + if (!domain_info) { + /* If we have a ADS-capable passdb backend, we + * must never make up our own SID, it will + * already be in the directory */ + DEBUG(0, ("Unable to fetch a Domain SID from the directory!\n")); + return false; + } + + *sid = domain_info->sid; + return true; + } +#endif + dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size); if (dyn_sid == NULL) @@ -88,6 +118,17 @@ bool secrets_store_domain_guid(const char *domain, struct GUID *guid) { fstring key; +#ifdef _SAMBA_WAF_BUILD_ + if (strequal(domain, get_global_sam_name()) && + (pdb_capabilities() & PDB_CAP_ADS)) { + /* If we have a ADS-capable passdb backend, we + * must never make up our own GUID, it will + * already be in the directory */ + DEBUG(0, ("Refusing to store a Domain GUID, this should be read from the directory not stored here\n")); + return false; + } +#endif + slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper_m(key); return secrets_store(key, guid, sizeof(struct GUID)); @@ -100,6 +141,24 @@ bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid) size_t size = 0; struct GUID new_guid; +#ifdef _SAMBA_WAF_BUILD_ + if (strequal(domain, get_global_sam_name()) && + (pdb_capabilities() & PDB_CAP_ADS)) { + struct pdb_domain_info *domain_info; + domain_info = pdb_get_domain_info(talloc_tos()); + if (!domain_info) { + /* If we have a ADS-capable passdb backend, we + * must never make up our own SID, it will + * already be in the directory */ + DEBUG(0, ("Unable to fetch a Domain GUID from the directory!\n")); + return false; + } + + *guid = domain_info->guid; + return true; + } +#endif + slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper_m(key); dyn_guid = (struct GUID *)secrets_fetch(key, &size); diff --git a/source3/passdb/machine_sid.c b/source3/passdb/machine_sid.c index 8fd5103164..6d4cf237c7 100644 --- a/source3/passdb/machine_sid.c +++ b/source3/passdb/machine_sid.c @@ -97,7 +97,7 @@ static struct dom_sid *pdb_generate_sam_sid(void) } } - if (secrets_fetch_domain_sid(global_myname(), sam_sid)) { + if (secrets_fetch_domain_sid(lp_netbios_name(), sam_sid)) { /* We got our sid. If not a pdc/bdc, we're done. */ if ( !IS_DC ) @@ -120,7 +120,7 @@ static struct dom_sid *pdb_generate_sam_sid(void) /* Domain name sid doesn't match global sam sid. Re-store domain sid as 'local' sid. */ DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n")); - if (!secrets_store_domain_sid(global_myname(), &domain_sid)) { + if (!secrets_store_domain_sid(lp_netbios_name(), &domain_sid)) { DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID for local sid as PDC/BDC.\n")); SAFE_FREE(sam_sid); return NULL; @@ -139,7 +139,7 @@ static struct dom_sid *pdb_generate_sam_sid(void) if (read_sid_from_file(fname, sam_sid)) { /* remember it for future reference and unlink the old MACHINE.SID */ - if (!secrets_store_domain_sid(global_myname(), sam_sid)) { + if (!secrets_store_domain_sid(lp_netbios_name(), sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Failed to store SID from file.\n")); SAFE_FREE(fname); SAFE_FREE(sam_sid); @@ -166,7 +166,7 @@ static struct dom_sid *pdb_generate_sam_sid(void) generate one and save it */ generate_random_sid(sam_sid); - if (!secrets_store_domain_sid(global_myname(), sam_sid)) { + if (!secrets_store_domain_sid(lp_netbios_name(), sam_sid)) { DEBUG(0,("pdb_generate_sam_sid: Failed to store generated machine SID.\n")); SAFE_FREE(sam_sid); return NULL; diff --git a/source3/passdb/machine_sid.h b/source3/passdb/machine_sid.h index 2da281ac34..12fde2f3ac 100644 --- a/source3/passdb/machine_sid.h +++ b/source3/passdb/machine_sid.h @@ -1,3 +1,24 @@ +/* + * Unix SMB/CIFS implementation. + * Password and authentication handling + * Copyright (C) Jeremy Allison 1996-2002 + * Copyright (C) Andrew Tridgell 2002 + * Copyright (C) Gerald (Jerry) Carter 2000 + * Copyright (C) Stefan (metze) Metzmacher 2002 + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see <http://www.gnu.org/licenses/>. + */ /* The following definitions come from passdb/machine_sid.c */ diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 62af5be7eb..5116396cd1 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -29,6 +29,7 @@ #include "secrets.h" #include "../libcli/security/security.h" #include "../lib/util/util_pw.h" +#include "util_tdb.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_PASSDB @@ -45,7 +46,7 @@ const char *my_sam_name(void) { /* Standalone servers can only use the local netbios name */ if ( lp_server_role() == ROLE_STANDALONE ) - return global_myname(); + return lp_netbios_name(); /* Default to the DOMAIN name when not specified */ return lp_workgroup(); @@ -73,7 +74,7 @@ struct samu *samu_new( TALLOC_CTX *ctx ) { struct samu *user; - if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) { + if ( !(user = talloc_zero( ctx, struct samu )) ) { DEBUG(0,("samuser_new: Talloc failed!\n")); return NULL; } @@ -148,7 +149,7 @@ static int count_commas(const char *str) static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create) { const char *guest_account = lp_guestaccount(); - const char *domain = global_myname(); + const char *domain = lp_netbios_name(); char *fullname; uint32_t urid; @@ -384,9 +385,9 @@ void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32_t acct_ctrl) slprintf(&p[i*2], 3, "%02X", pwd[i]); } else { if (acct_ctrl & ACB_PWNOTREQ) - safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32); + strlcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33); else - safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32); + strlcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33); } } @@ -435,7 +436,7 @@ void pdb_sethexhours(char *p, const unsigned char *hours) slprintf(&p[i*2], 3, "%02X", hours[i]); } } else { - safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43); + strlcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 44); } } @@ -2354,7 +2355,7 @@ bool get_trust_pw_clear(const char *domain, char **ret_pwd, if (pwd != NULL) { *ret_pwd = pwd; if (account_name != NULL) { - *account_name = global_myname(); + *account_name = lp_netbios_name(); } return true; @@ -2392,7 +2393,7 @@ bool get_trust_pw_hash(const char *domain, uint8_t ret_pwd[16], channel)) { if (account_name != NULL) { - *account_name = global_myname(); + *account_name = lp_netbios_name(); } return true; diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 6c1a2ab23d..eec82f9c98 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -123,8 +123,7 @@ time_t pdb_get_pass_must_change_time(const struct samu *sampass) bool pdb_get_pass_can_change(const struct samu *sampass) { - if (sampass->pass_can_change_time == get_time_t_max() && - sampass->pass_last_set_time != 0) + if (sampass->pass_can_change_time == get_time_t_max()) return False; return True; } @@ -512,7 +511,7 @@ bool pdb_set_group_sid(struct samu *sampass, const struct dom_sid *g_sid, enum p if (!g_sid) return False; - if ( !(sampass->group_sid = TALLOC_P( sampass, struct dom_sid )) ) { + if ( !(sampass->group_sid = talloc( sampass, struct dom_sid )) ) { return False; } diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 36d5aaa01a..94ed355e2c 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -25,6 +25,8 @@ #include "passdb.h" #include "secrets.h" #include "../librpc/gen_ndr/samr.h" +#include "../librpc/gen_ndr/drsblobs.h" +#include "../librpc/gen_ndr/ndr_drsblobs.h" #include "memcache.h" #include "nsswitch/winbind_client.h" #include "../libcli/security/security.h" @@ -1518,7 +1520,7 @@ static NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods, if (num_uids == 0) return NT_STATUS_OK; - *pp_member_rids = TALLOC_ZERO_ARRAY(mem_ctx, uint32_t, num_uids); + *pp_member_rids = talloc_zero_array(mem_ctx, uint32_t, num_uids); for (i=0; i<num_uids; i++) { struct dom_sid sid; @@ -1570,7 +1572,7 @@ static NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods, smb_panic("primary group missing"); } - *pp_sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, *p_num_groups); + *pp_sids = talloc_array(mem_ctx, struct dom_sid, *p_num_groups); if (*pp_sids == NULL) { TALLOC_FREE(*pp_gids); @@ -2144,7 +2146,62 @@ static NTSTATUS pdb_default_get_trusted_domain(struct pdb_methods *methods, const char *domain, struct pdb_trusted_domain **td) { - return NT_STATUS_NOT_IMPLEMENTED; + struct trustAuthInOutBlob taiob; + struct AuthenticationInformation aia; + struct pdb_trusted_domain *tdom; + enum ndr_err_code ndr_err; + time_t last_set_time; + char *pwd; + bool ok; + + tdom = talloc(mem_ctx, struct pdb_trusted_domain); + if (!tdom) { + return NT_STATUS_NO_MEMORY; + } + + tdom->domain_name = talloc_strdup(tdom, domain); + tdom->netbios_name = talloc_strdup(tdom, domain); + if (!tdom->domain_name || !tdom->netbios_name) { + talloc_free(tdom); + return NT_STATUS_NO_MEMORY; + } + + tdom->trust_auth_incoming = data_blob_null; + + ok = pdb_get_trusteddom_pw(domain, &pwd, &tdom->security_identifier, + &last_set_time); + if (!ok) { + talloc_free(tdom); + return NT_STATUS_UNSUCCESSFUL; + } + + ZERO_STRUCT(taiob); + ZERO_STRUCT(aia); + taiob.count = 1; + taiob.current.count = 1; + taiob.current.array = &aia; + unix_to_nt_time(&aia.LastUpdateTime, last_set_time); + aia.AuthType = TRUST_AUTH_TYPE_CLEAR; + aia.AuthInfo.clear.password = (uint8_t *) pwd; + aia.AuthInfo.clear.size = strlen(pwd); + taiob.previous.count = 0; + taiob.previous.array = NULL; + + ndr_err = ndr_push_struct_blob(&tdom->trust_auth_outgoing, + tdom, &taiob, + (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(tdom); + return NT_STATUS_UNSUCCESSFUL; + } + + tdom->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND; + tdom->trust_type = LSA_TRUST_TYPE_DOWNLEVEL; + tdom->trust_attributes = 0; + tdom->trust_forest_trust_info = data_blob_null; + + *td = tdom; + return NT_STATUS_OK; } static NTSTATUS pdb_default_get_trusted_domain_by_sid(struct pdb_methods *methods, @@ -2155,11 +2212,54 @@ static NTSTATUS pdb_default_get_trusted_domain_by_sid(struct pdb_methods *method return NT_STATUS_NOT_IMPLEMENTED; } +#define IS_NULL_DATA_BLOB(d) ((d).data == NULL && (d).length == 0) + static NTSTATUS pdb_default_set_trusted_domain(struct pdb_methods *methods, const char* domain, const struct pdb_trusted_domain *td) { - return NT_STATUS_NOT_IMPLEMENTED; + struct trustAuthInOutBlob taiob; + struct AuthenticationInformation *aia; + enum ndr_err_code ndr_err; + char *pwd; + bool ok; + + if (td->trust_attributes != 0 || + td->trust_type != LSA_TRUST_TYPE_DOWNLEVEL || + td->trust_direction != LSA_TRUST_DIRECTION_OUTBOUND || + !IS_NULL_DATA_BLOB(td->trust_auth_incoming) || + !IS_NULL_DATA_BLOB(td->trust_forest_trust_info)) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + ZERO_STRUCT(taiob); + ndr_err = ndr_pull_struct_blob(&td->trust_auth_outgoing, talloc_tos(), + &taiob, + (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return NT_STATUS_UNSUCCESSFUL; + } + + aia = (struct AuthenticationInformation *) taiob.current.array; + + if (taiob.count != 1 || taiob.current.count != 1 || + taiob.previous.count != 0 || + aia->AuthType != TRUST_AUTH_TYPE_CLEAR) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + pwd = talloc_strndup(talloc_tos(), (char *) aia->AuthInfo.clear.password, + aia->AuthInfo.clear.size); + if (!pwd) { + return NT_STATUS_NO_MEMORY; + } + + ok = pdb_set_trusteddom_pw(domain, pwd, &td->security_identifier); + if (!ok) { + return NT_STATUS_UNSUCCESSFUL; + } + + return NT_STATUS_OK; } static NTSTATUS pdb_default_del_trusted_domain(struct pdb_methods *methods, diff --git a/source3/passdb/pdb_ipa.c b/source3/passdb/pdb_ipa.c index 5f89be7a29..02f7bb6888 100644 --- a/source3/passdb/pdb_ipa.c +++ b/source3/passdb/pdb_ipa.c @@ -636,7 +636,7 @@ static NTSTATUS ipasam_enum_trusted_domains(struct pdb_methods *methods, } *num_domains = 0; - if (!(*domains = TALLOC_ARRAY(mem_ctx, struct pdb_trusted_domain *, 1))) { + if (!(*domains = talloc_array(mem_ctx, struct pdb_trusted_domain *, 1))) { DEBUG(1, ("talloc failed\n")); return NT_STATUS_NO_MEMORY; } @@ -684,7 +684,7 @@ static NTSTATUS ipasam_enum_trusteddoms(struct pdb_methods *methods, return NT_STATUS_OK; } - if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *, + if (!(*domains = talloc_array(mem_ctx, struct trustdom_info *, *num_domains))) { DEBUG(1, ("talloc failed\n")); return NT_STATUS_NO_MEMORY; @@ -693,7 +693,7 @@ static NTSTATUS ipasam_enum_trusteddoms(struct pdb_methods *methods, for (i = 0; i < *num_domains; i++) { struct trustdom_info *dom_info; - dom_info = TALLOC_P(*domains, struct trustdom_info); + dom_info = talloc(*domains, struct trustdom_info); if (dom_info == NULL) { DEBUG(1, ("talloc failed\n")); return NT_STATUS_NO_MEMORY; diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 7ce5edcefa..f8da0ff255 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -208,7 +208,7 @@ static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_ if (mem_ctx == NULL) return NT_STATUS_NO_MEMORY; - if ((attrs = TALLOC_ARRAY(mem_ctx, const char *, 2)) == NULL) { + if ((attrs = talloc_array(mem_ctx, const char *, 2)) == NULL) { ntstatus = NT_STATUS_NO_MEMORY; goto done; } @@ -887,7 +887,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state, if (pwHistLen > 0){ uint8 *pwhist = NULL; int i; - char *history_string = TALLOC_ARRAY(ctx, char, + char *history_string = talloc_array(ctx, char, MAX_PW_HISTORY_LEN*64); if (!history_string) { @@ -896,7 +896,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state, pwHistLen = MIN(pwHistLen, MAX_PW_HISTORY_LEN); - pwhist = TALLOC_ARRAY(ctx, uint8, + pwhist = talloc_array(ctx, uint8, pwHistLen * PW_HISTORY_ENTRY_LEN); if (pwhist == NULL) { DEBUG(0, ("init_sam_from_ldap: talloc failed!\n")); @@ -1532,7 +1532,7 @@ static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list, ; } - (*attr_list) = TALLOC_REALLOC_ARRAY(mem_ctx, (*attr_list), + (*attr_list) = talloc_realloc(mem_ctx, (*attr_list), const char *, i+2); SMB_ASSERT((*attr_list) != NULL); (*attr_list)[i] = talloc_strdup((*attr_list), new_attr); @@ -4340,7 +4340,7 @@ static const char **talloc_attrs(TALLOC_CTX *mem_ctx, ...) num += 1; va_end(ap); - if ((result = TALLOC_ARRAY(mem_ctx, const char *, num+1)) == NULL) { + if ((result = talloc_array(mem_ctx, const char *, num+1)) == NULL) { return NULL; } @@ -4564,7 +4564,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state, return False; } if (!pull_utf8_talloc(mem_ctx, - CONST_DISCARD(char **, &result->account_name), + discard_const_p(char *, &result->account_name), vals[0], &converted_size)) { DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s", @@ -4577,7 +4577,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state, if ((vals == NULL) || (vals[0] == NULL)) DEBUG(8, ("\"displayName\" not found\n")); else if (!pull_utf8_talloc(mem_ctx, - CONST_DISCARD(char **, &result->fullname), + discard_const_p(char *, &result->fullname), vals[0], &converted_size)) { DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s", @@ -4590,7 +4590,7 @@ static bool ldapuser2displayentry(struct ldap_search_state *state, if ((vals == NULL) || (vals[0] == NULL)) DEBUG(8, ("\"description\" not found\n")); else if (!pull_utf8_talloc(mem_ctx, - CONST_DISCARD(char **, &result->description), + discard_const_p(char *, &result->description), vals[0], &converted_size)) { DEBUG(0,("ldapuser2displayentry: pull_utf8_talloc failed: %s", @@ -4724,7 +4724,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state, return False; } if (!pull_utf8_talloc(mem_ctx, - CONST_DISCARD(char **, + discard_const_p(char *, &result->account_name), vals[0], &converted_size)) { @@ -4733,7 +4733,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state, } } else if (!pull_utf8_talloc(mem_ctx, - CONST_DISCARD(char **, + discard_const_p(char *, &result->account_name), vals[0], &converted_size)) { @@ -4747,7 +4747,7 @@ static bool ldapgroup2displayentry(struct ldap_search_state *state, if ((vals == NULL) || (vals[0] == NULL)) DEBUG(8, ("\"description\" not found\n")); else if (!pull_utf8_talloc(mem_ctx, - CONST_DISCARD(char **, &result->description), + discard_const_p(char *, &result->description), vals[0], &converted_size)) { DEBUG(0,("ldapgroup2displayentry: pull_utf8_talloc failed: %s", @@ -6356,7 +6356,7 @@ static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods, } *num_domains = 0; - if (!(*domains = TALLOC_ARRAY(mem_ctx, struct trustdom_info *, 1))) { + if (!(*domains = talloc_array(mem_ctx, struct trustdom_info *, 1))) { DEBUG(1, ("talloc failed\n")); return NT_STATUS_NO_MEMORY; } @@ -6368,7 +6368,7 @@ static NTSTATUS ldapsam_enum_trusteddoms(struct pdb_methods *methods, char *dom_name, *dom_sid_str; struct trustdom_info *dom_info; - dom_info = TALLOC_P(*domains, struct trustdom_info); + dom_info = talloc(*domains, struct trustdom_info); if (dom_info == NULL) { DEBUG(1, ("talloc failed\n")); return NT_STATUS_NO_MEMORY; @@ -6480,7 +6480,7 @@ static NTSTATUS pdb_init_ldapsam_common(struct pdb_methods **pdb_method, const c /* TODO: Setup private data and free */ - if ( !(ldap_state = TALLOC_ZERO_P(*pdb_method, struct ldapsam_privates)) ) { + if ( !(ldap_state = talloc_zero(*pdb_method, struct ldapsam_privates)) ) { DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n")); return NT_STATUS_NO_MEMORY; } diff --git a/source3/passdb/pdb_samba4.c b/source3/passdb/pdb_samba4.c new file mode 100644 index 0000000000..5848c23de8 --- /dev/null +++ b/source3/passdb/pdb_samba4.c @@ -0,0 +1,2100 @@ +/* + Unix SMB/CIFS implementation. + pdb glue module for samba4 + Copyright (C) Volker Lendecke 2009-2011 + Copyright (C) Andrew Bartlett 2010 + Copyright (C) Matthias Dieter Wallnöfer 2009 + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see <http://www.gnu.org/licenses/>. +*/ + +/* This module, is a port of Volker's pdb_ads to ldb and DSDB APIs */ + +#include "includes.h" +#include "source3/include/passdb.h" +#include "source4/dsdb/samdb/samdb.h" +#include "ldb_errors.h" +#include "libcli/security/dom_sid.h" +#include "source4/winbind/idmap.h" +#include "librpc/gen_ndr/ndr_security.h" +#include "libds/common/flag_mapping.h" +#include "source4/lib/events/events.h" +#include "source4/auth/session.h" +#include "source4/auth/system_session_proto.h" +#include "source4/param/param.h" + +struct pdb_samba4_state { + struct tevent_context *ev; + struct ldb_context *ldb; + struct idmap_context *idmap_ctx; + struct loadparm_context *lp_ctx; +}; + +static NTSTATUS pdb_samba4_getsampwsid(struct pdb_methods *m, + struct samu *sam_acct, + const struct dom_sid *sid); +static NTSTATUS pdb_samba4_getsamupriv(struct pdb_samba4_state *state, + const char *filter, + TALLOC_CTX *mem_ctx, + struct ldb_message **pmsg); +static bool pdb_samba4_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid, + union unid_t *id, enum lsa_SidType *type); + +static bool pdb_samba4_pull_time(struct ldb_message *msg, const char *attr, + time_t *ptime) +{ + uint64_t tmp; + if (! ldb_msg_find_element(msg, attr)) { + return false; + } + tmp = ldb_msg_find_attr_as_uint64(msg, attr, 0); + *ptime = uint64s_nt_time_to_unix_abs(&tmp); + return true; +} + +static struct pdb_domain_info *pdb_samba4_get_domain_info( + struct pdb_methods *m, TALLOC_CTX *mem_ctx) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct pdb_domain_info *info; + struct dom_sid *domain_sid; + struct ldb_dn *forest_dn, *domain_dn; + struct ldb_result *dom_res = NULL; + const char *dom_attrs[] = { + "objectSid", + "objectGUID", + "nTMixedDomain", + "fSMORoleOwner", + NULL + }; + char *p; + int ret; + + info = talloc(mem_ctx, struct pdb_domain_info); + if (info == NULL) { + return NULL; + } + + domain_dn = ldb_get_default_basedn(state->ldb); + + ret = ldb_search(state->ldb, info, &dom_res, + domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL); + if (ret != LDB_SUCCESS) { + goto fail; + } + if (dom_res->count != 1) { + goto fail; + } + + info->guid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); + + domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid"); + if (!domain_sid) { + goto fail; + } + info->sid = *domain_sid; + + TALLOC_FREE(dom_res); + + info->name = talloc_strdup(info, lpcfg_sam_name(state->lp_ctx)); + info->dns_domain = ldb_dn_canonical_string(info, domain_dn); + + if (!info->dns_domain) { + goto fail; + } + p = strchr(info->dns_domain, '/'); + if (p) { + *p = '\0'; + } + + forest_dn = ldb_get_root_basedn(state->ldb); + if (!forest_dn) { + goto fail; + } + + info->dns_forest = ldb_dn_canonical_string(info, forest_dn); + if (!info->dns_forest) { + goto fail; + } + p = strchr(info->dns_forest, '/'); + if (p) { + *p = '\0'; + } + + return info; + +fail: + TALLOC_FREE(dom_res); + TALLOC_FREE(info); + return NULL; +} + +static struct ldb_message *pdb_samba4_get_samu_private( + struct pdb_methods *m, struct samu *sam) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct ldb_message *msg; + char *sidstr, *filter; + NTSTATUS status; + + msg = (struct ldb_message *) + pdb_get_backend_private_data(sam, m); + + if (msg != NULL) { + return talloc_get_type_abort(msg, struct ldb_message); + } + + sidstr = dom_sid_string(talloc_tos(), pdb_get_user_sid(sam)); + if (sidstr == NULL) { + return NULL; + } + + filter = talloc_asprintf( + talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr); + TALLOC_FREE(sidstr); + if (filter == NULL) { + return NULL; + } + + status = pdb_samba4_getsamupriv(state, filter, sam, &msg); + TALLOC_FREE(filter); + if (!NT_STATUS_IS_OK(status)) { + return NULL; + } + + return msg; +} + +static NTSTATUS pdb_samba4_init_sam_from_priv(struct pdb_methods *m, + struct samu *sam, + struct ldb_message *msg) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION; + const char *str; + time_t tmp_time; + struct dom_sid *sid, group_sid; + uint64_t n; + const DATA_BLOB *blob; + + str = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL); + if (str == NULL) { + DEBUG(10, ("no samAccountName\n")); + goto fail; + } + pdb_set_username(sam, str, PDB_SET); + + if (pdb_samba4_pull_time(msg, "lastLogon", &tmp_time)) { + pdb_set_logon_time(sam, tmp_time, PDB_SET); + } + if (pdb_samba4_pull_time(msg, "lastLogoff", &tmp_time)) { + pdb_set_logoff_time(sam, tmp_time, PDB_SET); + } + if (pdb_samba4_pull_time(msg, "pwdLastSet", &tmp_time)) { + pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET); + } + if (pdb_samba4_pull_time(msg, "accountExpires", &tmp_time)) { + pdb_set_kickoff_time(sam, tmp_time, PDB_SET); + } + + str = ldb_msg_find_attr_as_string(msg, "displayName", + NULL); + if (str != NULL) { + pdb_set_fullname(sam, str, PDB_SET); + } + + str = ldb_msg_find_attr_as_string(msg, "homeDirectory", + NULL); + if (str != NULL) { + pdb_set_homedir(sam, str, PDB_SET); + } + + str = ldb_msg_find_attr_as_string(msg, "homeDrive", NULL); + if (str != NULL) { + pdb_set_dir_drive(sam, str, PDB_SET); + } + + str = ldb_msg_find_attr_as_string(msg, "scriptPath", NULL); + if (str != NULL) { + pdb_set_logon_script(sam, str, PDB_SET); + } + + str = ldb_msg_find_attr_as_string(msg, "profilePath", + NULL); + if (str != NULL) { + pdb_set_profile_path(sam, str, PDB_SET); + } + + str = ldb_msg_find_attr_as_string(msg, "profilePath", + NULL); + if (str != NULL) { + pdb_set_profile_path(sam, str, PDB_SET); + } + + str = ldb_msg_find_attr_as_string(msg, "comment", + NULL); + if (str != NULL) { + pdb_set_comment(sam, str, PDB_SET); + } + + str = ldb_msg_find_attr_as_string(msg, "description", + NULL); + if (str != NULL) { + pdb_set_acct_desc(sam, str, PDB_SET); + } + + str = ldb_msg_find_attr_as_string(msg, "userWorkstations", + NULL); + if (str != NULL) { + pdb_set_workstations(sam, str, PDB_SET); + } + + str = ldb_msg_find_attr_as_string(msg, "userParameters", + NULL); + if (str != NULL) { + pdb_set_munged_dial(sam, str, PDB_SET); + } + + sid = samdb_result_dom_sid(talloc_tos(), msg, "objectSid"); + if (!sid) { + DEBUG(10, ("Could not pull SID\n")); + goto fail; + } + pdb_set_user_sid(sam, sid, PDB_SET); + + n = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0); + if (n == 0) { + DEBUG(10, ("Could not pull userAccountControl\n")); + goto fail; + } + pdb_set_acct_ctrl(sam, ds_uf2acb(n), PDB_SET); + + blob = ldb_msg_find_ldb_val(msg, "unicodePwd"); + if (blob) { + if (blob->length != NT_HASH_LEN) { + DEBUG(0, ("Got NT hash of length %d, expected %d\n", + (int)blob->length, NT_HASH_LEN)); + goto fail; + } + pdb_set_nt_passwd(sam, blob->data, PDB_SET); + } + + blob = ldb_msg_find_ldb_val(msg, "dBCSPwd"); + if (blob) { + if (blob->length != LM_HASH_LEN) { + DEBUG(0, ("Got LM hash of length %d, expected %d\n", + (int)blob->length, LM_HASH_LEN)); + goto fail; + } + pdb_set_lanman_passwd(sam, blob->data, PDB_SET); + } + + n = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", 0); + if (n == 0) { + DEBUG(10, ("Could not pull primaryGroupID\n")); + goto fail; + } + sid_compose(&group_sid, samdb_domain_sid(state->ldb), n); + pdb_set_group_sid(sam, &group_sid, PDB_SET); + + status = NT_STATUS_OK; +fail: + TALLOC_FREE(frame); + return status; +} + +static bool pdb_samba4_add_time(struct ldb_message *msg, + const char *attrib, time_t t) +{ + uint64_t nt_time; + + unix_to_nt_time(&nt_time, t); + + return ldb_msg_add_fmt(msg, attrib, "%llu", (unsigned long long) nt_time); +} + +/* Like in pdb_ldap(), this will need to be a function pointer when we + * start to support 'adds' for migrations from samba3 passdb backends + * to samba4 */ +static bool update_required(struct samu *sam, enum pdb_elements element) +{ + return (IS_SAM_CHANGED(sam, element)); +} + +static bool pdb_samba4_init_samba4_from_sam(struct pdb_samba4_state *state, + struct ldb_message *existing, + TALLOC_CTX *mem_ctx, + struct ldb_message **pmods, + struct samu *sam) +{ + int ret = LDB_SUCCESS; + const char *pw; + struct ldb_message *msg; + + /* TODO: All fields :-) */ + + msg = ldb_msg_new(mem_ctx); + if (!msg) { + return false; + } + + msg->dn = existing->dn; + + pw = pdb_get_plaintext_passwd(sam); + if (update_required(sam, PDB_PLAINTEXT_PW)) { + if (pw == NULL) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto fail; + } + + ret |= ldb_msg_add_string(msg, "clearTextPassword", pw); + } + + if (update_required(sam, PDB_FULLNAME)) { + ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam)); + } + + if (update_required(sam, PDB_SMBHOME)) { + ret |= ldb_msg_add_string(msg, "homeDirectory", + pdb_get_homedir(sam)); + } + + if (update_required(sam, PDB_PROFILE)) { + ret |= ldb_msg_add_string(msg, "profilePath", + pdb_get_profile_path(sam)); + } + + if (update_required(sam, PDB_DRIVE)) { + ret |= ldb_msg_add_string(msg, "homeDrive", + pdb_get_dir_drive(sam)); + } + + if (update_required(sam, PDB_LOGONSCRIPT)) { + ret |= ldb_msg_add_string(msg, "scriptPath", + pdb_get_logon_script(sam)); + } + + if (update_required(sam, PDB_KICKOFFTIME)) { + ret |= pdb_samba4_add_time(msg, "accountExpires", + pdb_get_kickoff_time(sam)); + } + + if (update_required(sam, PDB_USERNAME)) { + ret |= ldb_msg_add_string(msg, "samAccountName", + pdb_get_username(sam)); + } + + if (update_required(sam, PDB_HOURSLEN) || update_required(sam, PDB_HOURS)) { + struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam)); + ret |= ldb_msg_add_value(msg, "logonHours", + &hours, NULL); + } + + if (update_required(sam, PDB_ACCTCTRL)) { + ret |= ldb_msg_add_fmt(msg, "userAccountControl", + "%d", ds_acb2uf(pdb_get_acct_ctrl(sam))); + } + + if (update_required(sam, PDB_COMMENT)) { + ret |= ldb_msg_add_string(msg, "comment", + pdb_get_comment(sam)); + } + + if (update_required(sam, PDB_ACCTDESC)) { + ret |= ldb_msg_add_string(msg, "description", + pdb_get_acct_desc(sam)); + } + + if (update_required(sam, PDB_WORKSTATIONS)) { + ret |= ldb_msg_add_string(msg, "userWorkstations", + pdb_get_workstations(sam)); + } + + /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */ + if (update_required(sam, PDB_MUNGEDDIAL)) { + ret |= ldb_msg_add_string(msg, "userParameters", + pdb_get_munged_dial(sam)); + } + + if (update_required(sam, PDB_COUNTRY_CODE)) { + ret |= ldb_msg_add_fmt(msg, "countryCode", + "%i", (int)pdb_get_country_code(sam)); + } + + if (update_required(sam, PDB_CODE_PAGE)) { + ret |= ldb_msg_add_fmt(msg, "codePage", + "%i", (int)pdb_get_code_page(sam)); + } + + /* Not yet handled here or not meaningful for modifies on a Samba4 backend: + PDB_LOGONTIME, + PDB_LOGOFFTIME, + PDB_BAD_PASSWORD_TIME, + PDB_CANCHANGETIME, + PDB_MUSTCHANGETIME, + PDB_DOMAIN, + PDB_NTUSERNAME, + PDB_LOGONDIVS, + PDB_USERSID, + PDB_GROUPSID, + PDB_PASSLASTSET, + PDB_FIELDS_PRESENT, + PDB_BAD_PASSWORD_COUNT, + PDB_LOGON_COUNT, + PDB_UNKNOWN6, + PDB_LMPASSWD, + PDB_NTPASSWD, + PDB_PWHISTORY, + PDB_BACKEND_PRIVATE_DATA, + + */ + + *pmods = msg; +fail: + return ret == LDB_SUCCESS; +} + +static NTSTATUS pdb_samba4_getsamupriv(struct pdb_samba4_state *state, + const char *filter, + TALLOC_CTX *mem_ctx, + struct ldb_message **msg) +{ + const char * attrs[] = { + "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires", + "sAMAccountName", "displayName", "homeDirectory", + "homeDrive", "scriptPath", "profilePath", "description", + "userWorkstations", "comment", "userParameters", "objectSid", + "primaryGroupID", "userAccountControl", "logonHours", + "badPwdCount", "logonCount", "countryCode", "codePage", + "unicodePwd", "dBCSPwd", NULL }; + + int rc = dsdb_search_one(state->ldb, mem_ctx, msg, NULL, LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter); + if (rc != LDB_SUCCESS) { + DEBUG(10, ("ldap_search failed %s\n", + ldb_errstring(state->ldb))); + return NT_STATUS_LDAP(rc); + } + + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_getsampwfilter(struct pdb_methods *m, + struct pdb_samba4_state *state, + struct samu *sam_acct, + const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5) +{ + struct ldb_message *priv; + NTSTATUS status; + va_list ap; + char *expression = NULL; + TALLOC_CTX *tmp_ctx = talloc_new(state); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + va_start(ap, exp_fmt); + expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap); + va_end(ap); + + if (!expression) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + status = pdb_samba4_getsamupriv(state, expression, sam_acct, &priv); + talloc_free(tmp_ctx); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("pdb_samba4_getsamupriv failed: %s\n", + nt_errstr(status))); + return status; + } + + status = pdb_samba4_init_sam_from_priv(m, sam_acct, priv); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("pdb_samba4_init_sam_from_priv failed: %s\n", + nt_errstr(status))); + TALLOC_FREE(priv); + return status; + } + + pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET); + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_getsampwnam(struct pdb_methods *m, + struct samu *sam_acct, + const char *username) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + + return pdb_samba4_getsampwfilter(m, state, sam_acct, + "(&(samaccountname=%s)(objectclass=user))", + username); +} + +static NTSTATUS pdb_samba4_getsampwsid(struct pdb_methods *m, + struct samu *sam_acct, + const struct dom_sid *sid) +{ + NTSTATUS status; + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + char *sidstr; + + sidstr = dom_sid_string(talloc_tos(), sid); + NT_STATUS_HAVE_NO_MEMORY(sidstr); + + status = pdb_samba4_getsampwfilter(m, state, sam_acct, + "(&(objectsid=%s)(objectclass=user))", + sidstr); + talloc_free(sidstr); + return status; +} + +static NTSTATUS pdb_samba4_create_user(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + const char *name, uint32 acct_flags, + uint32 *rid) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct dom_sid *sid; + struct ldb_dn *dn; + NTSTATUS status; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + /* Internally this uses transactions to ensure all the steps + * happen or fail as one */ + status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, &sid, &dn); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + sid_peek_rid(sid, rid); + talloc_free(tmp_ctx); + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_delete_user(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + struct samu *sam) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct ldb_dn *dn; + int rc; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, pdb_get_user_sid(sam))); + if (!dn || !ldb_dn_validate(dn)) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + rc = ldb_delete(state->ldb, dn); + + if (rc != LDB_SUCCESS) { + DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn), + ldb_errstring(state->ldb))); + talloc_free(tmp_ctx); + return NT_STATUS_LDAP(rc); + } + talloc_free(tmp_ctx); + return NT_STATUS_OK; +} + +/* This interface takes a fully populated struct samu and places it in + * the database. This is not implemented at this time as we need to + * be careful around the creation of arbitary SIDs (ie, we must ensrue + * they are not left in a RID pool */ +static NTSTATUS pdb_samba4_add_sam_account(struct pdb_methods *m, + struct samu *sampass) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +/* + * Update the Samba4 LDB with the changes from a struct samu. + * + * This takes care not to update elements that have not been changed + * by the caller + */ +static NTSTATUS pdb_samba4_update_sam_account(struct pdb_methods *m, + struct samu *sam) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct ldb_message *msg = pdb_samba4_get_samu_private( + m, sam); + struct ldb_message *replace_msg; + int rc; + + if (!pdb_samba4_init_samba4_from_sam(state, msg, talloc_tos(), + &replace_msg, sam)) { + return NT_STATUS_NO_MEMORY; + } + + if (replace_msg->num_elements == 0) { + /* Nothing to do, just return success */ + return NT_STATUS_OK; + } + + rc = dsdb_replace(state->ldb, replace_msg, 0); + TALLOC_FREE(replace_msg); + if (rc != LDB_SUCCESS) { + DEBUG(10, ("dsdb_replace for %s failed: %s\n", ldb_dn_get_linearized(replace_msg->dn), + ldb_errstring(state->ldb))); + return NT_STATUS_LDAP(rc); + } + + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_delete_sam_account(struct pdb_methods *m, + struct samu *username) +{ + NTSTATUS status; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + status = pdb_samba4_delete_user(m, tmp_ctx, username); + talloc_free(tmp_ctx); + return status; +} + +static NTSTATUS pdb_samba4_rename_sam_account(struct pdb_methods *m, + struct samu *oldname, + const char *newname) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +/* This is not implemented, as this module is exptected to be used + * with auth_samba4, and this is responible for login counters etc + * + */ +static NTSTATUS pdb_samba4_update_login_attempts(struct pdb_methods *m, + struct samu *sam_acct, + bool success) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS pdb_samba4_getgrfilter(struct pdb_methods *m, GROUP_MAP *map, + const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + const char *attrs[] = { "objectSid", "description", "samAccountName", + NULL }; + struct ldb_message *msg; + va_list ap; + char *expression = NULL; + struct dom_sid *sid; + const char *str; + int rc; + union unid_t id; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + va_start(ap, exp_fmt); + expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap); + va_end(ap); + + if (!expression) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, NULL, LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression); + if (rc == LDB_ERR_NO_SUCH_OBJECT) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_SUCH_GROUP; + } else if (rc != LDB_SUCCESS) { + talloc_free(tmp_ctx); + DEBUG(10, ("dsdb_search_one failed %s\n", + ldb_errstring(state->ldb))); + return NT_STATUS_LDAP(rc); + } + + sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid"); + if (!sid) { + talloc_free(tmp_ctx); + DEBUG(10, ("Could not pull SID\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + map->sid = *sid; + + if (!pdb_samba4_sid_to_id(m, sid, &id, &map->sid_name_use)) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_SUCH_GROUP; + } + if (map->sid_name_use == SID_NAME_USER) { + DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s", expression)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + map->gid = id.gid; + + str = ldb_msg_find_attr_as_string(msg, "samAccountName", + NULL); + if (str == NULL) { + talloc_free(tmp_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + fstrcpy(map->nt_name, str); + + str = ldb_msg_find_attr_as_string(msg, "description", + NULL); + if (str != NULL) { + fstrcpy(map->comment, str); + } else { + map->comment[0] = '\0'; + } + + talloc_free(tmp_ctx); + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_getgrsid(struct pdb_methods *m, GROUP_MAP *map, + struct dom_sid sid) +{ + char *filter; + NTSTATUS status; + + filter = talloc_asprintf(talloc_tos(), + "(&(objectsid=%s)(objectclass=group))", + sid_string_talloc(talloc_tos(), &sid)); + if (filter == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = pdb_samba4_getgrfilter(m, map, filter); + TALLOC_FREE(filter); + return status; +} + +static NTSTATUS pdb_samba4_getgrgid(struct pdb_methods *m, GROUP_MAP *map, + gid_t gid) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + NTSTATUS status; + struct id_map id_map; + struct id_map *id_maps[2]; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + id_map.xid.id = gid; + id_map.xid.type = ID_TYPE_GID; + id_maps[0] = &id_map; + id_maps[1] = NULL; + + status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = pdb_samba4_getgrsid(m, map, *id_map.sid); + talloc_free(tmp_ctx); + return status; +} + +static NTSTATUS pdb_samba4_getgrnam(struct pdb_methods *m, GROUP_MAP *map, + const char *name) +{ + char *filter; + NTSTATUS status; + + filter = talloc_asprintf(talloc_tos(), + "(&(samaccountname=%s)(objectclass=group))", + name); + if (filter == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = pdb_samba4_getgrfilter(m, map, filter); + TALLOC_FREE(filter); + return status; +} + +static NTSTATUS pdb_samba4_create_dom_group(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, const char *name, + uint32 *rid) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + NTSTATUS status; + struct dom_sid *sid; + struct ldb_dn *dn; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + + sid_peek_rid(sid, rid); + talloc_free(tmp_ctx); + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_delete_dom_group(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, uint32 rid) +{ + const char *attrs[] = { NULL }; + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct dom_sid sid; + struct ldb_message *msg; + struct ldb_dn *dn; + int rc; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + sid_compose(&sid, samdb_domain_sid(state->ldb), rid); + + if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) { + DEBUG(0, ("Unable to start transaction in pdb_samba4_delete_dom_group()\n")); + return NT_STATUS_INTERNAL_ERROR; + } + + dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, &sid)); + if (!dn || !ldb_dn_validate(dn)) { + talloc_free(tmp_ctx); + ldb_transaction_cancel(state->ldb); + return NT_STATUS_NO_MEMORY; + } + rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group"); + if (rc == LDB_ERR_NO_SUCH_OBJECT) { + talloc_free(tmp_ctx); + ldb_transaction_cancel(state->ldb); + return NT_STATUS_NO_SUCH_GROUP; + } + rc = ldb_delete(state->ldb, dn); + if (rc == LDB_ERR_NO_SUCH_OBJECT) { + talloc_free(tmp_ctx); + ldb_transaction_cancel(state->ldb); + return NT_STATUS_NO_SUCH_GROUP; + } else if (rc != LDB_SUCCESS) { + DEBUG(10, ("ldb_delete failed %s\n", + ldb_errstring(state->ldb))); + ldb_transaction_cancel(state->ldb); + return NT_STATUS_LDAP(rc); + } + + if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) { + DEBUG(0, ("Unable to commit transaction in pdb_samba4_delete_dom_group()\n")); + return NT_STATUS_INTERNAL_ERROR; + } + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_add_group_mapping_entry(struct pdb_methods *m, + GROUP_MAP *map) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS pdb_samba4_update_group_mapping_entry(struct pdb_methods *m, + GROUP_MAP *map) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS pdb_samba4_delete_group_mapping_entry(struct pdb_methods *m, + struct dom_sid sid) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS pdb_samba4_enum_group_mapping(struct pdb_methods *m, + const struct dom_sid *sid, + enum lsa_SidType sid_name_use, + GROUP_MAP **pp_rmap, + size_t *p_num_entries, + bool unix_only) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS pdb_samba4_enum_group_members(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + const struct dom_sid *group, + uint32_t **pmembers, + size_t *pnum_members) +{ + unsigned int i, num_sids, num_members; + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct dom_sid *members_as_sids; + struct dom_sid *dom_sid; + uint32_t *members; + struct ldb_dn *dn; + NTSTATUS status; + + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, group)); + if (!dn || !ldb_dn_validate(dn)) { + return NT_STATUS_NO_MEMORY; + } + + status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + + *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(*pmembers, tmp_ctx); + num_members = 0; + + for (i = 0; i < num_sids; i++) { + if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) { + continue; + } + status = dom_sid_split_rid(NULL, &members_as_sids[i], + NULL, &members[num_members]); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + num_members++; + } + *pnum_members = num_members; + return NT_STATUS_OK; +} + +/* Just convert the primary group SID into a group */ +static NTSTATUS fake_enum_group_memberships(struct pdb_samba4_state *state, + TALLOC_CTX *mem_ctx, + struct samu *user, + struct dom_sid **pp_sids, + gid_t **pp_gids, + uint32_t *p_num_groups) +{ + NTSTATUS status; + size_t num_groups = 0; + struct dom_sid *group_sids; + gid_t *gids; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + if (user->group_sid) { + struct id_map *id_maps[2]; + struct id_map id_map; + + num_groups = 1; + + group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups); + if (group_sids == NULL) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + gids = talloc_array(tmp_ctx, gid_t, num_groups); + if (gids == NULL) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + group_sids[0] = *user->group_sid; + + ZERO_STRUCT(id_map); + id_map.sid = &group_sids[0]; + id_maps[0] = &id_map; + id_maps[1] = NULL; + + status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) { + gids[0] = id_map.xid.id; + } else { + DEBUG(1, (__location__ + "Group %s, of which %s is a member, could not be converted to a GID\n", + dom_sid_string(tmp_ctx, &group_sids[0]), + dom_sid_string(tmp_ctx, &user->user_sid))); + talloc_free(tmp_ctx); + /* We must error out, otherwise a user might + * avoid a DENY acl based on a group they + * missed out on */ + return NT_STATUS_NO_SUCH_GROUP; + } + } + + *pp_sids = talloc_steal(mem_ctx, group_sids); + *pp_gids = talloc_steal(mem_ctx, gids); + *p_num_groups = num_groups; + talloc_free(tmp_ctx); + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_enum_group_memberships(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + struct samu *user, + struct dom_sid **pp_sids, + gid_t **pp_gids, + uint32_t *p_num_groups) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct ldb_message *msg = pdb_samba4_get_samu_private( + m, user); + const char *attrs[] = { "tokenGroups", NULL}; + struct ldb_message *tokengroups_msg; + struct ldb_message_element *tokengroups; + int i, rc; + NTSTATUS status; + unsigned int count = 0; + size_t num_groups; + struct dom_sid *group_sids; + gid_t *gids; + TALLOC_CTX *tmp_ctx; + + if (msg == NULL) { + /* Fake up some things here */ + return fake_enum_group_memberships(state, + mem_ctx, + user, pp_sids, + pp_gids, p_num_groups); + } + + tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL); + + if (rc == LDB_ERR_NO_SUCH_OBJECT) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_SUCH_USER; + } else if (rc != LDB_SUCCESS) { + DEBUG(10, ("dsdb_search_one failed %s\n", + ldb_errstring(state->ldb))); + talloc_free(tmp_ctx); + return NT_STATUS_LDAP(rc); + } + + tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups"); + + if (tokengroups) { + count = tokengroups->num_values; + } + + group_sids = talloc_array(tmp_ctx, struct dom_sid, count); + if (group_sids == NULL) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + gids = talloc_array(tmp_ctx, gid_t, count); + if (gids == NULL) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + num_groups = 0; + + for (i=0; i<count; i++) { + struct id_map *id_maps[2]; + struct id_map id_map; + struct ldb_val *v = &tokengroups->values[i]; + enum ndr_err_code ndr_err + = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups], + (ndr_pull_flags_fn_t)ndr_pull_dom_sid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(tmp_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + ZERO_STRUCT(id_map); + id_map.sid = &group_sids[num_groups]; + id_maps[0] = &id_map; + id_maps[1] = NULL; + + status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) { + gids[num_groups] = id_map.xid.id; + } else { + DEBUG(1, (__location__ + "Group %s, of which %s is a member, could not be converted to a GID\n", + dom_sid_string(tmp_ctx, &group_sids[num_groups]), + ldb_dn_get_linearized(msg->dn))); + talloc_free(tmp_ctx); + /* We must error out, otherwise a user might + * avoid a DENY acl based on a group they + * missed out on */ + return NT_STATUS_NO_SUCH_GROUP; + } + + num_groups += 1; + if (num_groups == count) { + break; + } + } + + *pp_sids = talloc_steal(mem_ctx, group_sids); + *pp_gids = talloc_steal(mem_ctx, gids); + *p_num_groups = num_groups; + talloc_free(tmp_ctx); + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_set_unix_primary_group(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + struct samu *user) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS pdb_samba4_mod_groupmem_by_sid(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + const struct dom_sid *groupsid, + const struct dom_sid *membersid, + int mod_op) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct ldb_message *msg; + int ret; + struct ldb_message_element *el; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + msg = ldb_msg_new(tmp_ctx); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg, tmp_ctx); + + msg->dn = ldb_dn_new_fmt(msg, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, groupsid)); + if (!msg->dn || !ldb_dn_validate(msg->dn)) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + ret = ldb_msg_add_fmt(msg, "member", "<SID=%s>", dom_sid_string(tmp_ctx, membersid)); + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + el = ldb_msg_find_element(msg, "member"); + el->flags = mod_op; + + /* No need for transactions here, the ldb auto-transaction + * code will handle things for the single operation */ + ret = ldb_modify(state->ldb, msg); + talloc_free(tmp_ctx); + if (ret != LDB_SUCCESS) { + DEBUG(10, ("ldb_modify failed: %s\n", + ldb_errstring(state->ldb))); + if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) { + return NT_STATUS_MEMBER_IN_GROUP; + } + if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) { + return NT_STATUS_MEMBER_NOT_IN_GROUP; + } + return NT_STATUS_LDAP(ret); + } + + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_mod_groupmem(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + uint32 grouprid, uint32 memberrid, + int mod_op) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + const struct dom_sid *dom_sid, *groupsid, *membersid; + NTSTATUS status; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + dom_sid = samdb_domain_sid(state->ldb); + + groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(groupsid, tmp_ctx); + membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(membersid, tmp_ctx); + status = pdb_samba4_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op); + talloc_free(tmp_ctx); + return status; +} + +static NTSTATUS pdb_samba4_add_groupmem(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + uint32 group_rid, uint32 member_rid) +{ + return pdb_samba4_mod_groupmem(m, mem_ctx, group_rid, member_rid, + LDB_FLAG_MOD_ADD); +} + +static NTSTATUS pdb_samba4_del_groupmem(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + uint32 group_rid, uint32 member_rid) +{ + return pdb_samba4_mod_groupmem(m, mem_ctx, group_rid, member_rid, + LDB_FLAG_MOD_DELETE); +} + +static NTSTATUS pdb_samba4_create_alias(struct pdb_methods *m, + const char *name, uint32 *rid) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct dom_sid *sid; + + struct ldb_dn *dn; + NTSTATUS status; + + /* Internally this uses transactions to ensure all the steps + * happen or fail as one */ + status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + } + + sid_peek_rid(sid, rid); + TALLOC_FREE(frame); + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_delete_alias(struct pdb_methods *m, + const struct dom_sid *sid) +{ + const char *attrs[] = { NULL }; + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct ldb_message *msg; + struct ldb_dn *dn; + int rc; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid)); + if (!dn || !ldb_dn_validate(dn)) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) { + DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb))); + return NT_STATUS_INTERNAL_ERROR; + } + + rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)" + "(|(grouptype=%d)(grouptype=%d)))", + GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, + GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); + if (rc == LDB_ERR_NO_SUCH_OBJECT) { + talloc_free(tmp_ctx); + ldb_transaction_cancel(state->ldb); + return NT_STATUS_NO_SUCH_ALIAS; + } + rc = ldb_delete(state->ldb, dn); + if (rc == LDB_ERR_NO_SUCH_OBJECT) { + talloc_free(tmp_ctx); + ldb_transaction_cancel(state->ldb); + return NT_STATUS_NO_SUCH_ALIAS; + } else if (rc != LDB_SUCCESS) { + DEBUG(10, ("ldb_delete failed %s\n", + ldb_errstring(state->ldb))); + ldb_transaction_cancel(state->ldb); + return NT_STATUS_LDAP(rc); + } + + if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) { + DEBUG(0, ("Failed to commit transaction in pdb_samba4_delete_alias(): %s\n", + ldb_errstring(state->ldb))); + return NT_STATUS_INTERNAL_ERROR; + } + + return NT_STATUS_OK; +} + +#if 0 +static NTSTATUS pdb_samba4_set_aliasinfo(struct pdb_methods *m, + const struct dom_sid *sid, + struct acct_info *info) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct tldap_context *ld; + const char *attrs[3] = { "objectSid", "description", + "samAccountName" }; + struct ldb_message **msg; + char *sidstr, *dn; + int rc; + struct tldap_mod *mods; + int num_mods; + bool ok; + + ld = pdb_samba4_ld(state); + if (ld == NULL) { + return NT_STATUS_LDAP(TLDAP_SERVER_DOWN); + } + + sidstr = sid_binstring(talloc_tos(), sid); + NT_STATUS_HAVE_NO_MEMORY(sidstr); + + rc = pdb_samba4_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB, + attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), + &msg, "(&(objectSid=%s)(objectclass=group)" + "(|(grouptype=%d)(grouptype=%d)))", + sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, + GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); + TALLOC_FREE(sidstr) + if (rc != LDB_SUCCESS) { + DEBUG(10, ("ldap_search failed %s\n", + ldb_errstring(state->ldb))); + return NT_STATUS_LDAP(rc); + } + switch talloc_array_length(msg) { + case 0: + return NT_STATUS_NO_SUCH_ALIAS; + case 1: + break; + default: + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + if (!tldap_entry_dn(msg[0], &dn)) { + TALLOC_FREE(msg); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + mods = NULL; + num_mods = 0; + ok = true; + + ok &= tldap_make_mod_fmt( + msg[0], msg, &num_mods, &mods, "description", + "%s", info->acct_desc); + ok &= tldap_make_mod_fmt( + msg[0], msg, &num_mods, &mods, "samAccountName", + "%s", info->acct_name); + if (!ok) { + TALLOC_FREE(msg); + return NT_STATUS_NO_MEMORY; + } + if (num_mods == 0) { + /* no change */ + TALLOC_FREE(msg); + return NT_STATUS_OK; + } + + rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0); + TALLOC_FREE(msg); + if (rc != LDB_SUCCESS) { + DEBUG(10, ("ldap_modify failed: %s\n", + ldb_errstring(state->ldb))); + return NT_STATUS_LDAP(rc); + } + return NT_STATUS_OK; +} +#endif +static NTSTATUS pdb_samba4_add_aliasmem(struct pdb_methods *m, + const struct dom_sid *alias, + const struct dom_sid *member) +{ + NTSTATUS status; + TALLOC_CTX *frame = talloc_stackframe(); + status = pdb_samba4_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD); + talloc_free(frame); + return status; +} + +static NTSTATUS pdb_samba4_del_aliasmem(struct pdb_methods *m, + const struct dom_sid *alias, + const struct dom_sid *member) +{ + NTSTATUS status; + TALLOC_CTX *frame = talloc_stackframe(); + status = pdb_samba4_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE); + talloc_free(frame); + return status; +} + +static NTSTATUS pdb_samba4_enum_aliasmem(struct pdb_methods *m, + const struct dom_sid *alias, + TALLOC_CTX *mem_ctx, + struct dom_sid **pmembers, + size_t *pnum_members) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct ldb_dn *dn; + unsigned int num_members; + NTSTATUS status; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, alias)); + if (!dn || !ldb_dn_validate(dn)) { + return NT_STATUS_NO_MEMORY; + } + + status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members); + *pnum_members = num_members; + if (NT_STATUS_IS_OK(status)) { + talloc_steal(mem_ctx, pmembers); + } + talloc_free(tmp_ctx); + return status; +} + +static NTSTATUS pdb_samba4_enum_alias_memberships(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + const struct dom_sid *domain_sid, + const struct dom_sid *members, + size_t num_members, + uint32_t **palias_rids, + size_t *pnum_alias_rids) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + uint32_t *alias_rids = NULL; + size_t num_alias_rids = 0; + int i; + struct dom_sid *groupSIDs = NULL; + unsigned int num_groupSIDs = 0; + char *filter; + NTSTATUS status; + const char *sid_string; + const char *sid_dn; + DATA_BLOB sid_blob; + + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + /* + * TODO: Get the filter right so that we only get the aliases from + * either the SAM or BUILTIN + */ + + filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))", + GROUP_TYPE_BUILTIN_LOCAL_GROUP); + if (filter == NULL) { + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < num_members; i++) { + sid_string = dom_sid_string(tmp_ctx, &members[i]); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sid_string, tmp_ctx); + + sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string); + NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sid_dn, tmp_ctx); + + sid_blob = data_blob_string_const(sid_dn); + + status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter, + tmp_ctx, &groupSIDs, &num_groupSIDs); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return status; + } + } + + alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs); + if (alias_rids == NULL) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + for (i=0; i<num_groupSIDs; i++) { + if (sid_peek_check_rid(domain_sid, &groupSIDs[i], + &alias_rids[num_alias_rids])) { + num_alias_rids++;; + } + } + + *palias_rids = alias_rids; + *pnum_alias_rids = num_alias_rids; + return NT_STATUS_OK; +} + +static NTSTATUS pdb_samba4_lookup_rids(struct pdb_methods *m, + const struct dom_sid *domain_sid, + int num_rids, + uint32 *rids, + const char **names, + enum lsa_SidType *lsa_attrs) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + NTSTATUS status; + + TALLOC_CTX *tmp_ctx; + + if (num_rids == 0) { + return NT_STATUS_NONE_MAPPED; + } + + tmp_ctx = talloc_stackframe(); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs); + talloc_free(tmp_ctx); + return status; +} + +static NTSTATUS pdb_samba4_lookup_names(struct pdb_methods *m, + const struct dom_sid *domain_sid, + int num_names, + const char **pp_names, + uint32 *rids, + enum lsa_SidType *attrs) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS pdb_samba4_get_account_policy(struct pdb_methods *m, + enum pdb_policy_type type, + uint32_t *value) +{ + return account_policy_get(type, value) + ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; +} + +static NTSTATUS pdb_samba4_set_account_policy(struct pdb_methods *m, + enum pdb_policy_type type, + uint32_t value) +{ + return account_policy_set(type, value) + ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; +} + +static NTSTATUS pdb_samba4_get_seq_num(struct pdb_methods *m, + time_t *seq_num_out) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + uint64_t seq_num; + int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num); + if (ret == LDB_SUCCESS) { + *seq_num_out = seq_num; + return NT_STATUS_OK; + } else { + return NT_STATUS_UNSUCCESSFUL; + } +} + +struct pdb_samba4_search_state { + uint32_t acct_flags; + struct samr_displayentry *entries; + uint32_t num_entries; + ssize_t array_size; + uint32_t current; +}; + +static bool pdb_samba4_next_entry(struct pdb_search *search, + struct samr_displayentry *entry) +{ + struct pdb_samba4_search_state *state = talloc_get_type_abort( + search->private_data, struct pdb_samba4_search_state); + + if (state->current == state->num_entries) { + return false; + } + + entry->idx = state->entries[state->current].idx; + entry->rid = state->entries[state->current].rid; + entry->acct_flags = state->entries[state->current].acct_flags; + + entry->account_name = talloc_strdup( + search, state->entries[state->current].account_name); + entry->fullname = talloc_strdup( + search, state->entries[state->current].fullname); + entry->description = talloc_strdup( + search, state->entries[state->current].description); + + state->current += 1; + return true; +} + +static void pdb_samba4_search_end(struct pdb_search *search) +{ + struct pdb_samba4_search_state *state = talloc_get_type_abort( + search->private_data, struct pdb_samba4_search_state); + talloc_free(state); +} + +static bool pdb_samba4_search_filter(struct pdb_methods *m, + struct pdb_search *search, + struct pdb_samba4_search_state **pstate, + const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct pdb_samba4_search_state *sstate; + const char * attrs[] = { "objectSid", "sAMAccountName", "displayName", + "userAccountControl", "description", NULL }; + struct ldb_result *res; + int i, rc, num_users; + + va_list ap; + char *expression = NULL; + + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + if (!tmp_ctx) { + return false; + } + + va_start(ap, exp_fmt); + expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap); + va_end(ap); + + if (!expression) { + talloc_free(tmp_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + + sstate = talloc_zero(tmp_ctx, struct pdb_samba4_search_state); + if (sstate == NULL) { + talloc_free(tmp_ctx); + return false; + } + + rc = dsdb_search(state->ldb, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression); + if (rc != LDB_SUCCESS) { + talloc_free(tmp_ctx); + DEBUG(10, ("dsdb_search failed: %s\n", + ldb_errstring(state->ldb))); + return false; + } + + num_users = res->count; + + sstate->entries = talloc_array(sstate, struct samr_displayentry, + num_users); + if (sstate->entries == NULL) { + talloc_free(tmp_ctx); + DEBUG(10, ("talloc failed\n")); + return false; + } + + sstate->num_entries = 0; + + for (i=0; i<num_users; i++) { + struct samr_displayentry *e; + struct dom_sid *sid; + + e = &sstate->entries[sstate->num_entries]; + + e->idx = sstate->num_entries; + sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid"); + if (!sid) { + talloc_free(tmp_ctx); + DEBUG(10, ("Could not pull SID\n")); + return false; + } + sid_peek_rid(sid, &e->rid); + + e->acct_flags = samdb_result_acct_flags(state->ldb, tmp_ctx, + res->msgs[i], + ldb_get_default_basedn(state->ldb)); + e->account_name = ldb_msg_find_attr_as_string( + res->msgs[i], "samAccountName", NULL); + if (e->account_name == NULL) { + talloc_free(tmp_ctx); + return false; + } + e->fullname = ldb_msg_find_attr_as_string( + res->msgs[i], "displayName", ""); + e->description = ldb_msg_find_attr_as_string( + res->msgs[i], "description", ""); + + sstate->num_entries += 1; + if (sstate->num_entries >= num_users) { + break; + } + } + talloc_steal(sstate->entries, res->msgs); + search->private_data = talloc_steal(search, sstate); + search->next_entry = pdb_samba4_next_entry; + search->search_end = pdb_samba4_search_end; + *pstate = sstate; + talloc_free(tmp_ctx); + return true; +} + +static bool pdb_samba4_search_users(struct pdb_methods *m, + struct pdb_search *search, + uint32 acct_flags) +{ + struct pdb_samba4_search_state *sstate; + bool ret; + + ret = pdb_samba4_search_filter(m, search, &sstate, "(objectclass=user)"); + if (!ret) { + return false; + } + sstate->acct_flags = acct_flags; + return true; +} + +static bool pdb_samba4_search_groups(struct pdb_methods *m, + struct pdb_search *search) +{ + struct pdb_samba4_search_state *sstate; + bool ret; + + ret = pdb_samba4_search_filter(m, search, &sstate, + "(&(grouptype=%d)(objectclass=group))", + GTYPE_SECURITY_GLOBAL_GROUP); + if (!ret) { + return false; + } + sstate->acct_flags = 0; + return true; +} + +static bool pdb_samba4_search_aliases(struct pdb_methods *m, + struct pdb_search *search, + const struct dom_sid *sid) +{ + struct pdb_samba4_search_state *sstate; + bool ret; + + ret = pdb_samba4_search_filter(m, search, &sstate, + "(&(grouptype=%d)(objectclass=group))", + sid_check_is_builtin(sid) + ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP + : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP); + if (!ret) { + return false; + } + sstate->acct_flags = 0; + return true; +} + +static bool pdb_samba4_uid_to_sid(struct pdb_methods *m, uid_t uid, + struct dom_sid *sid) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + NTSTATUS status; + struct id_map id_map; + struct id_map *id_maps[2]; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + if (!tmp_ctx) { + return false; + } + + id_map.xid.id = uid; + id_map.xid.type = ID_TYPE_UID; + id_maps[0] = &id_map; + id_maps[1] = NULL; + + status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return false; + } + *sid = *id_map.sid; + talloc_free(tmp_ctx); + return true; +} + +static bool pdb_samba4_gid_to_sid(struct pdb_methods *m, gid_t gid, + struct dom_sid *sid) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + NTSTATUS status; + struct id_map id_map; + struct id_map *id_maps[2]; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + if (!tmp_ctx) { + return false; + } + + id_map.xid.id = gid; + id_map.xid.type = ID_TYPE_GID; + id_maps[0] = &id_map; + id_maps[1] = NULL; + + status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + *sid = *id_map.sid; + talloc_free(tmp_ctx); + return true; +} + +static bool pdb_samba4_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid, + union unid_t *id, enum lsa_SidType *type) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + m->private_data, struct pdb_samba4_state); + struct id_map id_map; + struct id_map *id_maps[2]; + const char *attrs[] = { "objectClass", "groupType", NULL }; + struct ldb_message *msg; + struct ldb_dn *dn; + NTSTATUS status; + int rc; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + if (!tmp_ctx) { + return false; + } + + ZERO_STRUCT(id_map); + + dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid)); + if (!dn || !ldb_dn_validate(dn)) { + talloc_free(tmp_ctx); + return false; + } + rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, NULL); + if (rc == LDB_ERR_NO_SUCH_OBJECT) { + DEBUG(5, (__location__ "SID to Unix ID lookup failed because SID %s could not be found in the samdb\n", dom_sid_string(tmp_ctx, sid))); + talloc_free(tmp_ctx); + return false; + } + if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) { + uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0); + switch (grouptype) { + case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP: + case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP: + *type = SID_NAME_ALIAS; + break; + case GTYPE_SECURITY_GLOBAL_GROUP: + *type = SID_NAME_DOM_GRP; + break; + default: + talloc_free(tmp_ctx); + DEBUG(10, ("Could not pull groupType\n")); + return false; + } + + *type = SID_NAME_DOM_GRP; + + ZERO_STRUCT(id_map); + id_map.sid = sid; + id_maps[0] = &id_map; + id_maps[1] = NULL; + + status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps); + talloc_free(tmp_ctx); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) { + id->gid = id_map.xid.id; + return true; + } + return false; + } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) { + *type = SID_NAME_USER; + ZERO_STRUCT(id_map); + id_map.sid = sid; + id_maps[0] = &id_map; + id_maps[1] = NULL; + + status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps); + talloc_free(tmp_ctx); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + if (id_map.xid.type == ID_TYPE_UID || id_map.xid.type == ID_TYPE_BOTH) { + id->uid = id_map.xid.id; + return true; + } + return false; + } + DEBUG(5, (__location__ "SID to Unix ID lookup failed because SID %s was found, but was not a user or group\n", dom_sid_string(tmp_ctx, sid))); + talloc_free(tmp_ctx); + return false; +} + +static uint32_t pdb_samba4_capabilities(struct pdb_methods *m) +{ + return PDB_CAP_STORE_RIDS | PDB_CAP_ADS; +} + +static bool pdb_samba4_new_rid(struct pdb_methods *m, uint32 *rid) +{ + return false; +} + +static bool pdb_samba4_get_trusteddom_pw(struct pdb_methods *m, + const char *domain, char** pwd, + struct dom_sid *sid, + time_t *pass_last_set_time) +{ + return false; +} + +static bool pdb_samba4_set_trusteddom_pw(struct pdb_methods *m, + const char* domain, const char* pwd, + const struct dom_sid *sid) +{ + return false; +} + +static bool pdb_samba4_del_trusteddom_pw(struct pdb_methods *m, + const char *domain) +{ + return false; +} + +static NTSTATUS pdb_samba4_enum_trusteddoms(struct pdb_methods *m, + TALLOC_CTX *mem_ctx, + uint32 *num_domains, + struct trustdom_info ***domains) +{ + *num_domains = 0; + *domains = NULL; + return NT_STATUS_OK; +} + +static void pdb_samba4_init_methods(struct pdb_methods *m) +{ + m->name = "samba4"; + m->get_domain_info = pdb_samba4_get_domain_info; + m->getsampwnam = pdb_samba4_getsampwnam; + m->getsampwsid = pdb_samba4_getsampwsid; + m->create_user = pdb_samba4_create_user; + m->delete_user = pdb_samba4_delete_user; + m->add_sam_account = pdb_samba4_add_sam_account; + m->update_sam_account = pdb_samba4_update_sam_account; + m->delete_sam_account = pdb_samba4_delete_sam_account; + m->rename_sam_account = pdb_samba4_rename_sam_account; + m->update_login_attempts = pdb_samba4_update_login_attempts; + m->getgrsid = pdb_samba4_getgrsid; + m->getgrgid = pdb_samba4_getgrgid; + m->getgrnam = pdb_samba4_getgrnam; + m->create_dom_group = pdb_samba4_create_dom_group; + m->delete_dom_group = pdb_samba4_delete_dom_group; + m->add_group_mapping_entry = pdb_samba4_add_group_mapping_entry; + m->update_group_mapping_entry = pdb_samba4_update_group_mapping_entry; + m->delete_group_mapping_entry = pdb_samba4_delete_group_mapping_entry; + m->enum_group_mapping = pdb_samba4_enum_group_mapping; + m->enum_group_members = pdb_samba4_enum_group_members; + m->enum_group_memberships = pdb_samba4_enum_group_memberships; + m->set_unix_primary_group = pdb_samba4_set_unix_primary_group; + m->add_groupmem = pdb_samba4_add_groupmem; + m->del_groupmem = pdb_samba4_del_groupmem; + m->create_alias = pdb_samba4_create_alias; + m->delete_alias = pdb_samba4_delete_alias; + m->get_aliasinfo = pdb_default_get_aliasinfo; + m->add_aliasmem = pdb_samba4_add_aliasmem; + m->del_aliasmem = pdb_samba4_del_aliasmem; + m->enum_aliasmem = pdb_samba4_enum_aliasmem; + m->enum_alias_memberships = pdb_samba4_enum_alias_memberships; + m->lookup_rids = pdb_samba4_lookup_rids; + m->lookup_names = pdb_samba4_lookup_names; + m->get_account_policy = pdb_samba4_get_account_policy; + m->set_account_policy = pdb_samba4_set_account_policy; + m->get_seq_num = pdb_samba4_get_seq_num; + m->search_users = pdb_samba4_search_users; + m->search_groups = pdb_samba4_search_groups; + m->search_aliases = pdb_samba4_search_aliases; + m->uid_to_sid = pdb_samba4_uid_to_sid; + m->gid_to_sid = pdb_samba4_gid_to_sid; + m->sid_to_id = pdb_samba4_sid_to_id; + m->capabilities = pdb_samba4_capabilities; + m->new_rid = pdb_samba4_new_rid; + m->get_trusteddom_pw = pdb_samba4_get_trusteddom_pw; + m->set_trusteddom_pw = pdb_samba4_set_trusteddom_pw; + m->del_trusteddom_pw = pdb_samba4_del_trusteddom_pw; + m->enum_trusteddoms = pdb_samba4_enum_trusteddoms; +} + +static void free_private_data(void **vp) +{ + struct pdb_samba4_state *state = talloc_get_type_abort( + *vp, struct pdb_samba4_state); + talloc_unlink(state, state->ldb); + return; +} + +static NTSTATUS pdb_init_samba4(struct pdb_methods **pdb_method, + const char *location) +{ + struct pdb_methods *m; + struct pdb_samba4_state *state; + NTSTATUS status; + + if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) { + return status; + } + + state = talloc_zero(m, struct pdb_samba4_state); + if (state == NULL) { + goto nomem; + } + m->private_data = state; + m->free_private_data = free_private_data; + pdb_samba4_init_methods(m); + + state->ev = s4_event_context_init(state); + if (!state->ev) { + DEBUG(10, ("s4_event_context_init failed\n")); + goto fail; + } + + state->lp_ctx = loadparm_init_s3(state, loadparm_s3_context()); + if (state->lp_ctx == NULL) { + DEBUG(10, ("loadparm_init_s3 failed\n")); + goto fail; + } + + state->ldb = samdb_connect(state, + state->ev, + state->lp_ctx, + system_session(state->lp_ctx), 0); + + if (!state->ldb) { + DEBUG(10, ("samdb_connect failed\n")); + goto fail; + } + + state->idmap_ctx = idmap_init(state, state->ev, + state->lp_ctx); + if (!state->idmap_ctx) { + DEBUG(10, ("samdb_connect failed\n")); + goto fail; + } + + *pdb_method = m; + return NT_STATUS_OK; +nomem: + status = NT_STATUS_NO_MEMORY; +fail: + TALLOC_FREE(m); + return status; +} + +NTSTATUS pdb_samba4_init(void); +NTSTATUS pdb_samba4_init(void) +{ + return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4", + pdb_init_samba4); +} diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 43d6eaf664..2cfacd3a13 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -549,7 +549,7 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s } if(*p == ':') { p++; - if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) { + if(*p && (strncasecmp_m((char *)p, "LCT-", 4)==0)) { int i; p += 4; for(i = 0; i < 8; i++) { @@ -975,7 +975,7 @@ This is no longer supported.!\n", pwd->smb_name)); p++; /* We should be pointing at the LCT entry. */ - if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (StrnCaseCmp((char *)p, "LCT-", 4) == 0)) { + if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (strncasecmp_m((char *)p, "LCT-", 4) == 0)) { p += 4; for(i = 0; i < 8; i++) { if(p[i] == '\0' || !isxdigit(p[i])) { @@ -990,7 +990,7 @@ This is no longer supported.!\n", pwd->smb_name)); */ got_pass_last_set_time = True; } /* i == 8 */ - } /* *p && StrnCaseCmp() */ + } /* *p && strncasecmp_m() */ } /* p == ':' */ } /* p == '[' */ @@ -1694,7 +1694,7 @@ static NTSTATUS pdb_init_smbpasswd( struct pdb_methods **pdb_method, const char /* Setup private data and free function */ - if ( !(privates = TALLOC_ZERO_P( *pdb_method, struct smbpasswd_privates )) ) { + if ( !(privates = talloc_zero( *pdb_method, struct smbpasswd_privates )) ) { DEBUG(0, ("talloc() failed for smbpasswd private_data!\n")); return NT_STATUS_NO_MEMORY; } diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index 79c0ed196a..28461d0ac3 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -27,6 +27,7 @@ #include "passdb.h" #include "dbwrap.h" #include "../libcli/security/security.h" +#include "util_tdb.h" #if 0 /* when made a module use this */ diff --git a/source3/passdb/pdb_wbc_sam.c b/source3/passdb/pdb_wbc_sam.c index 64529c7896..91adc8108b 100644 --- a/source3/passdb/pdb_wbc_sam.c +++ b/source3/passdb/pdb_wbc_sam.c @@ -112,7 +112,7 @@ static NTSTATUS pdb_wbc_sam_enum_group_memberships(struct pdb_methods *methods, smb_panic("primary group missing"); } - *pp_sids = TALLOC_ARRAY(mem_ctx, struct dom_sid, *p_num_groups); + *pp_sids = talloc_array(mem_ctx, struct dom_sid, *p_num_groups); if (*pp_sids == NULL) { TALLOC_FREE(*pp_gids); diff --git a/source3/passdb/proto.h b/source3/passdb/proto.h index a64985c709..8b95b72959 100644 --- a/source3/passdb/proto.h +++ b/source3/passdb/proto.h @@ -1,3 +1,41 @@ +/* + * Unix SMB/CIFS implementation. + * passdb - password and authentication handling + * + * Copyright (C) Andrew Tridgell 1992-1998 + * Copyright (C) Jeremy Allison 1995-2009 + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998 + * Copyright (C) Jean François Micouleau 1998-2001 + * Copyright (C) Gerald (Jerry) Carter 2000-2006 + * Copyright (C) Simo Sorce 2000-2003,2006 + * Copyright (C) Andrew Bartlett 2001-2002 + * Copyright (C) Shahms King 2001 + * Copyright (C) Jelmer Vernooij 2002 + * Copyright (C) Rafal Szczesniak 2002 + * Copyright (C) Stefan (metze) Metzmacher 2002-2003 + * Copyright (C) Guenther Deschner 2004-2005 + * Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2004-2005 + * Copyright (C) Vince Brimhall 2004-2005 + * Copyright (C) Volker Lendecke 2006 + * Copyright (C) Michael Adam 2007 + * Copyright (C) Dan Sledz 2009 + * + * 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _PASSDB_PROTO_H_ +#define _PASSDB_PROTO_H_ /* The following definitions come from passdb/account_pol.c */ @@ -300,3 +338,5 @@ NTSTATUS pdb_tdbsam_init(void); NTSTATUS create_builtin_users(const struct dom_sid *sid); NTSTATUS create_builtin_administrators(const struct dom_sid *sid); + +#endif /* _PASSDB_PROTO_H_ */ diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index c16d15807b..c9101ca050 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -30,6 +30,7 @@ #include "secrets.h" #include "dbwrap.h" #include "../libcli/security/security.h" +#include "util_tdb.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_PASSDB @@ -419,7 +420,7 @@ static int list_trusted_domain(struct db_record *rec, void *private_data) return 0; } - if (!(dom_info = TALLOC_P(state->domains, struct trustdom_info))) { + if (!(dom_info = talloc(state->domains, struct trustdom_info))) { DEBUG(0, ("talloc failed\n")); return 0; } @@ -458,7 +459,7 @@ NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains, * exists */ - if (!(state.domains = TALLOC_ARRAY( + if (!(state.domains = talloc_array( mem_ctx, struct trustdom_info *, 1))) { return NT_STATUS_NO_MEMORY; } diff --git a/source3/passdb/wscript_build b/source3/passdb/wscript_build index 79b143507f..90ce2c4c4d 100644 --- a/source3/passdb/wscript_build +++ b/source3/passdb/wscript_build @@ -14,6 +14,7 @@ bld.SAMBA3_SUBSYSTEM('pdb', bld.SAMBA3_MODULE('pdb_tdbsam', subsystem='pdb', source=PDB_TDBSAM_SRC, + deps='samba-util', init_function='', internal_module=bld.SAMBA3_IS_STATIC_MODULE('pdb_tdbsam'), enabled=bld.SAMBA3_IS_ENABLED_MODULE('pdb_tdbsam')) @@ -36,6 +37,7 @@ bld.SAMBA3_MODULE('pdb_ads', bld.SAMBA3_MODULE('pdb_smbpasswd', subsystem='pdb', source=PDB_SMBPASSWD_SRC, + deps='samba-util', init_function='', internal_module=bld.SAMBA3_IS_STATIC_MODULE('pdb_smbpasswd'), enabled=bld.SAMBA3_IS_ENABLED_MODULE('pdb_smbpasswd')) @@ -43,6 +45,17 @@ bld.SAMBA3_MODULE('pdb_smbpasswd', bld.SAMBA3_MODULE('pdb_wbc_sam', subsystem='pdb', source=PDB_WBC_SAM_SRC, + deps='samba-util', init_function='', internal_module=bld.SAMBA3_IS_STATIC_MODULE('pdb_wbc_sam'), enabled=bld.SAMBA3_IS_ENABLED_MODULE('pdb_wbc_sam')) + +bld.SAMBA3_MODULE('pdb_samba4', + subsystem='pdb', + source='pdb_samba4.c', + init_function='', + deps='IDMAP samdb', + allow_undefined_symbols=False, + internal_module=bld.SAMBA3_IS_STATIC_MODULE('pdb_samba4'), + enabled=bld.SAMBA3_IS_ENABLED_MODULE('pdb_samba4')) + |