s3-passdb: Only delete 1 entry from memcache.
[amitay/samba.git] / source3 / passdb / pdb_interface.c
index 9f3a1725a4829042c1b207e89640e6eb0ec5c62b..7a0279e1fb7279ff2cb0f1798b65c6d1722310a7 100644 (file)
 */
 
 #include "includes.h"
+#include "system/passwd.h"
+#include "passdb.h"
 #include "secrets.h"
+#include "messages.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/dom_sid.h"
+#include "../libcli/security/security.h"
+#include "../lib/util/util_pw.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_PASSDB
@@ -94,6 +100,12 @@ struct pdb_init_function_entry *pdb_find_backend_entry(const char *name)
        return NULL;
 }
 
+const struct pdb_init_function_entry *pdb_get_backends(void)
+{
+       return backends;
+}
+
+
 /*
  * The event context for the passdb backend. I know this is a bad hack and yet
  * another static variable, but our pdb API is a global thing per
@@ -235,7 +247,7 @@ static bool pdb_try_account_unlock(struct samu *sampass)
 {
        uint32_t acb_info = pdb_get_acct_ctrl(sampass);
 
-       if (acb_info & (ACB_NORMAL|ACB_AUTOLOCK)) {
+       if ((acb_info & ACB_NORMAL) && (acb_info & ACB_AUTOLOCK)) {
                uint32_t lockout_duration;
                time_t bad_password_time;
                time_t now = time(NULL);
@@ -352,7 +364,8 @@ static bool guest_user_info( struct samu *user )
        NTSTATUS result;
        const char *guestname = lp_guestaccount();
 
-       if ( !(pwd = getpwnam_alloc(talloc_autofree_context(), guestname ) ) ) {
+       pwd = Get_Pwnam_alloc(talloc_tos(), guestname);
+       if (pwd == NULL) {
                DEBUG(0,("guest_user_info: Unable to locate guest account [%s]!\n", 
                        guestname));
                return False;
@@ -475,11 +488,16 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
                flush_pwnam_cache();
 
                pwd = Get_Pwnam_alloc(tmp_ctx, name);
+
+               if(pwd == NULL) {
+                       DEBUG(3, ("Could not find user %s, add script did not work\n", name));
+                       return NT_STATUS_NO_SUCH_USER;
+               }
        }
 
        /* we have a valid SID coming out of this call */
 
-       status = samu_alloc_rid_unix( sam_pass, pwd );
+       status = samu_alloc_rid_unix(methods, sam_pass, pwd);
 
        TALLOC_FREE( pwd );
 
@@ -504,7 +522,7 @@ static NTSTATUS pdb_default_create_user(struct pdb_methods *methods,
 
        pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED);
 
-       status = pdb_add_sam_account(sam_pass);
+       status = methods->add_sam_account(methods, sam_pass);
 
        TALLOC_FREE(sam_pass);
 
@@ -562,7 +580,7 @@ static NTSTATUS pdb_default_delete_user(struct pdb_methods *methods,
        NTSTATUS status;
        fstring username;
 
-       status = pdb_delete_sam_account(sam_acct);
+       status = methods->delete_sam_account(methods, sam_acct);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -589,10 +607,15 @@ NTSTATUS pdb_delete_user(TALLOC_CTX *mem_ctx, struct samu *sam_acct)
 {
        struct pdb_methods *pdb = pdb_get_methods();
        uid_t uid = -1;
+       NTSTATUS status;
+       const struct dom_sid *user_sid;
+       char *msg_data;
+
+       user_sid = pdb_get_user_sid(sam_acct);
 
        /* sanity check to make sure we don't delete root */
 
-       if ( !sid_to_uid( pdb_get_user_sid(sam_acct), &uid ) ) {
+       if ( !sid_to_uid(user_sid, &uid ) ) {
                return NT_STATUS_NO_SUCH_USER;
        }
 
@@ -600,7 +623,30 @@ NTSTATUS pdb_delete_user(TALLOC_CTX *mem_ctx, struct samu *sam_acct)
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       return pdb->delete_user(pdb, mem_ctx, sam_acct);
+       memcache_delete(NULL,
+                       PDB_GETPWSID_CACHE,
+                       data_blob_const(user_sid, sizeof(*user_sid)));
+
+       status = pdb->delete_user(pdb, mem_ctx, sam_acct);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       msg_data = talloc_asprintf(mem_ctx, "USER %s",
+                                  pdb_get_username(sam_acct));
+       if (!msg_data) {
+               /* not fatal, and too late to rollback,
+                * just return */
+               return status;
+       }
+       message_send_all(server_messaging_context(),
+                        ID_CACHE_DELETE,
+                        msg_data,
+                        strlen(msg_data) + 1,
+                        NULL);
+
+       TALLOC_FREE(msg_data);
+       return status;
 }
 
 NTSTATUS pdb_add_sam_account(struct samu *sam_acct) 
@@ -621,8 +667,11 @@ NTSTATUS pdb_update_sam_account(struct samu *sam_acct)
 NTSTATUS pdb_delete_sam_account(struct samu *sam_acct) 
 {
        struct pdb_methods *pdb = pdb_get_methods();
+       const struct dom_sid *user_sid = pdb_get_user_sid(sam_acct);
 
-       memcache_flush(NULL, PDB_GETPWSID_CACHE);
+       memcache_delete(NULL,
+                       PDB_GETPWSID_CACHE,
+                       data_blob_const(user_sid, sizeof(*user_sid)));
 
        return pdb->delete_sam_account(pdb, sam_acct);
 }
@@ -837,7 +886,7 @@ NTSTATUS pdb_enum_group_members(TALLOC_CTX *mem_ctx,
 
 NTSTATUS pdb_enum_group_memberships(TALLOC_CTX *mem_ctx, struct samu *user,
                                    struct dom_sid **pp_sids, gid_t **pp_gids,
-                                   size_t *p_num_groups)
+                                   uint32_t *p_num_groups)
 {
        struct pdb_methods *pdb = pdb_get_methods();
        return pdb->enum_group_memberships(
@@ -882,7 +931,7 @@ static bool pdb_user_in_group(TALLOC_CTX *mem_ctx, struct samu *account,
 {
        struct dom_sid *sids;
        gid_t *gids;
-       size_t i, num_groups;
+       uint32_t i, num_groups;
 
        if (!NT_STATUS_IS_OK(pdb_enum_group_memberships(mem_ctx, account,
                                                        &sids, &gids,
@@ -1432,7 +1481,7 @@ static bool pdb_default_sid_to_id(struct pdb_methods *methods,
        return ret;
 }
 
-static bool get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, size_t *p_num)
+static bool get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **pp_uids, uint32_t *p_num)
 {
        struct group *grp;
        char **gr;
@@ -1495,7 +1544,7 @@ static NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
 {
        gid_t gid;
        uid_t *uids;
-       size_t i, num_uids;
+       uint32_t i, num_uids;
 
        *pp_member_rids = NULL;
        *p_num_members = 0;
@@ -1509,7 +1558,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;
@@ -1534,7 +1583,7 @@ static NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
                                                   struct samu *user,
                                                   struct dom_sid **pp_sids,
                                                   gid_t **pp_gids,
-                                                  size_t *p_num_groups)
+                                                  uint32_t *p_num_groups)
 {
        size_t i;
        gid_t gid;
@@ -1545,7 +1594,7 @@ static NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
        /* Ignore the primary group SID.  Honor the real Unix primary group.
           The primary group SID is only of real use to Windows clients */
 
-       if ( !(pw = getpwnam_alloc(mem_ctx, username)) ) {
+       if ( !(pw = Get_Pwnam_alloc(mem_ctx, username)) ) {
                return NT_STATUS_NO_SUCH_USER;
        }
 
@@ -1561,7 +1610,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);
@@ -1881,7 +1930,8 @@ static void search_end_groups(struct pdb_search *search)
        SAFE_FREE(state->groups);
 }
 
-static bool pdb_search_grouptype(struct pdb_search *search,
+static bool pdb_search_grouptype(struct pdb_methods *methods,
+                                struct pdb_search *search,
                                 const struct dom_sid *sid, enum lsa_SidType type)
 {
        struct group_search *state;
@@ -1892,8 +1942,9 @@ static bool pdb_search_grouptype(struct pdb_search *search,
                return False;
        }
 
-       if (!pdb_enum_group_mapping(sid, type, &state->groups, &state->num_groups,
-                                   True)) {
+       if (!NT_STATUS_IS_OK(methods->enum_group_mapping(methods, sid, type, 
+                                                        &state->groups, &state->num_groups,
+                                                        True))) {
                DEBUG(0, ("Could not enum groups\n"));
                return False;
        }
@@ -1908,7 +1959,7 @@ static bool pdb_search_grouptype(struct pdb_search *search,
 static bool pdb_default_search_groups(struct pdb_methods *methods,
                                      struct pdb_search *search)
 {
-       return pdb_search_grouptype(search, get_global_sam_sid(), SID_NAME_DOM_GRP);
+       return pdb_search_grouptype(methods, search, get_global_sam_sid(), SID_NAME_DOM_GRP);
 }
 
 static bool pdb_default_search_aliases(struct pdb_methods *methods,
@@ -1916,7 +1967,7 @@ static bool pdb_default_search_aliases(struct pdb_methods *methods,
                                       const struct dom_sid *sid)
 {
 
-       return pdb_search_grouptype(search, sid, SID_NAME_ALIAS);
+       return pdb_search_grouptype(methods, search, sid, SID_NAME_ALIAS);
 }
 
 static struct samr_displayentry *pdb_search_getentry(struct pdb_search *search,
@@ -2092,12 +2143,257 @@ static NTSTATUS pdb_default_enum_trusteddoms(struct pdb_methods *methods,
        return secrets_trusted_domains(mem_ctx, num_domains, domains);
 }
 
+/*******************************************************************
+ trusted_domain methods
+ *******************************************************************/
+
+NTSTATUS pdb_get_trusted_domain(TALLOC_CTX *mem_ctx, const char *domain,
+                               struct pdb_trusted_domain **td)
+{
+       struct pdb_methods *pdb = pdb_get_methods();
+       return pdb->get_trusted_domain(pdb, mem_ctx, domain, td);
+}
+
+NTSTATUS pdb_get_trusted_domain_by_sid(TALLOC_CTX *mem_ctx, struct dom_sid *sid,
+                               struct pdb_trusted_domain **td)
+{
+       struct pdb_methods *pdb = pdb_get_methods();
+       return pdb->get_trusted_domain_by_sid(pdb, mem_ctx, sid, td);
+}
+
+NTSTATUS pdb_set_trusted_domain(const char* domain,
+                               const struct pdb_trusted_domain *td)
+{
+       struct pdb_methods *pdb = pdb_get_methods();
+       return pdb->set_trusted_domain(pdb, domain, td);
+}
+
+NTSTATUS pdb_del_trusted_domain(const char *domain)
+{
+       struct pdb_methods *pdb = pdb_get_methods();
+       return pdb->del_trusted_domain(pdb, domain);
+}
+
+NTSTATUS pdb_enum_trusted_domains(TALLOC_CTX *mem_ctx, uint32_t *num_domains,
+                                 struct pdb_trusted_domain ***domains)
+{
+       struct pdb_methods *pdb = pdb_get_methods();
+       return pdb->enum_trusted_domains(pdb, mem_ctx, num_domains, domains);
+}
+
+static NTSTATUS pdb_default_get_trusted_domain(struct pdb_methods *methods,
+                                              TALLOC_CTX *mem_ctx,
+                                              const char *domain,
+                                              struct pdb_trusted_domain **td)
+{
+       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,
+                                                     TALLOC_CTX *mem_ctx,
+                                                     struct dom_sid *sid,
+                                                     struct pdb_trusted_domain **td)
+{
+       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)
+{
+       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,
+                                              const char *domain)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS pdb_default_enum_trusted_domains(struct pdb_methods *methods,
+                                                TALLOC_CTX *mem_ctx,
+                                                uint32_t *num_domains,
+                                                struct pdb_trusted_domain ***domains)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
 static struct pdb_domain_info *pdb_default_get_domain_info(
        struct pdb_methods *m, TALLOC_CTX *mem_ctx)
 {
        return NULL;
 }
 
+/*******************************************************************
+ secret methods
+ *******************************************************************/
+
+NTSTATUS pdb_get_secret(TALLOC_CTX *mem_ctx,
+                       const char *secret_name,
+                       DATA_BLOB *secret_current,
+                       NTTIME *secret_current_lastchange,
+                       DATA_BLOB *secret_old,
+                       NTTIME *secret_old_lastchange,
+                       struct security_descriptor **sd)
+{
+       struct pdb_methods *pdb = pdb_get_methods();
+       return pdb->get_secret(pdb, mem_ctx, secret_name,
+                              secret_current, secret_current_lastchange,
+                              secret_old, secret_old_lastchange,
+                              sd);
+}
+
+NTSTATUS pdb_set_secret(const char *secret_name,
+                       DATA_BLOB *secret_current,
+                       DATA_BLOB *secret_old,
+                       struct security_descriptor *sd)
+{
+       struct pdb_methods *pdb = pdb_get_methods();
+       return pdb->set_secret(pdb, secret_name,
+                              secret_current,
+                              secret_old,
+                              sd);
+}
+
+NTSTATUS pdb_delete_secret(const char *secret_name)
+{
+       struct pdb_methods *pdb = pdb_get_methods();
+       return pdb->delete_secret(pdb, secret_name);
+}
+
+static NTSTATUS pdb_default_get_secret(struct pdb_methods *methods,
+                                      TALLOC_CTX *mem_ctx,
+                                      const char *secret_name,
+                                      DATA_BLOB *secret_current,
+                                      NTTIME *secret_current_lastchange,
+                                      DATA_BLOB *secret_old,
+                                      NTTIME *secret_old_lastchange,
+                                      struct security_descriptor **sd)
+{
+       return lsa_secret_get(mem_ctx, secret_name,
+                             secret_current,
+                             secret_current_lastchange,
+                             secret_old,
+                             secret_old_lastchange,
+                             sd);
+}
+
+static NTSTATUS pdb_default_set_secret(struct pdb_methods *methods,
+                                      const char *secret_name,
+                                      DATA_BLOB *secret_current,
+                                      DATA_BLOB *secret_old,
+                                      struct security_descriptor *sd)
+{
+       return lsa_secret_set(secret_name,
+                             secret_current,
+                             secret_old,
+                             sd);
+}
+
+static NTSTATUS pdb_default_delete_secret(struct pdb_methods *methods,
+                                         const char *secret_name)
+{
+       return lsa_secret_delete(secret_name);
+}
+
 /*******************************************************************
  Create a pdb_methods structure and initialize it with the default
  operations.  In this way a passdb module can simply implement
@@ -2109,7 +2405,7 @@ NTSTATUS make_pdb_method( struct pdb_methods **methods )
 {
        /* allocate memory for the structure as its own talloc CTX */
 
-       *methods = talloc_zero(talloc_autofree_context(), struct pdb_methods);
+       *methods = talloc_zero(NULL, struct pdb_methods);
        if (*methods == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -2163,5 +2459,15 @@ NTSTATUS make_pdb_method( struct pdb_methods **methods )
        (*methods)->del_trusteddom_pw = pdb_default_del_trusteddom_pw;
        (*methods)->enum_trusteddoms  = pdb_default_enum_trusteddoms;
 
+       (*methods)->get_trusted_domain = pdb_default_get_trusted_domain;
+       (*methods)->get_trusted_domain_by_sid = pdb_default_get_trusted_domain_by_sid;
+       (*methods)->set_trusted_domain = pdb_default_set_trusted_domain;
+       (*methods)->del_trusted_domain = pdb_default_del_trusted_domain;
+       (*methods)->enum_trusted_domains = pdb_default_enum_trusted_domains;
+
+       (*methods)->get_secret = pdb_default_get_secret;
+       (*methods)->set_secret = pdb_default_set_secret;
+       (*methods)->delete_secret = pdb_default_delete_secret;
+
        return NT_STATUS_OK;
 }