s4:samr RPC server - dcesrv_samr_SetUserInfo() - password expiration
[obnox/samba/samba-obnox.git] / source4 / rpc_server / samr / dcesrv_samr.c
index 8b53aef3efdad937f7d05e3724cb51d786346a75..7279fe02f724f1ff6defa3a749b3cbcbe67c260a 100644 (file)
@@ -28,8 +28,8 @@
 #include "rpc_server/common/common.h"
 #include "rpc_server/samr/dcesrv_samr.h"
 #include "system/time.h"
-#include "lib/ldb/include/ldb.h"
-#include "lib/ldb/include/ldb_errors.h"
+#include <ldb.h>
+#include <ldb_errors.h>
 #include "../libds/common/flags.h"
 #include "dsdb/samdb/samdb.h"
 #include "dsdb/common/util.h"
@@ -39,6 +39,7 @@
 #include "../lib/util/util_ldb.h"
 #include "param/param.h"
 #include "lib/util/tsort.h"
+#include "libds/common/flag_mapping.h"
 
 /* these query macros make samr_Query[User|Group|Alias]Info a bit easier to read */
 
@@ -499,7 +500,7 @@ static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state
        info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount",
                                                 0);
        switch (state->role) {
-       case ROLE_DOMAIN_CONTROLLER:
+       case ROLE_ACTIVE_DIRECTORY_DC:
                /* This pulls the NetBIOS name from the
                   cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
                   string */
@@ -509,6 +510,9 @@ static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state
                        info->role = SAMR_ROLE_DOMAIN_BDC;
                }
                break;
+       case ROLE_DOMAIN_PDC:
+       case ROLE_DOMAIN_BDC:
+               return NT_STATUS_INTERNAL_ERROR;
        case ROLE_DOMAIN_MEMBER:
                info->role = SAMR_ROLE_DOMAIN_MEMBER;
                break;
@@ -602,7 +606,7 @@ static NTSTATUS dcesrv_samr_info_DomInfo7(struct samr_domain_state *state,
 {
 
        switch (state->role) {
-       case ROLE_DOMAIN_CONTROLLER:
+       case ROLE_ACTIVE_DIRECTORY_DC:
                /* This pulls the NetBIOS name from the
                   cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
                   string */
@@ -612,6 +616,9 @@ static NTSTATUS dcesrv_samr_info_DomInfo7(struct samr_domain_state *state,
                        info->role = SAMR_ROLE_DOMAIN_BDC;
                }
                break;
+       case ROLE_DOMAIN_PDC:
+               info->role = SAMR_ROLE_DOMAIN_PDC;
+               break;
        case ROLE_DOMAIN_MEMBER:
                info->role = SAMR_ROLE_DOMAIN_MEMBER;
                break;
@@ -984,9 +991,7 @@ static NTSTATUS dcesrv_samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TA
                DEBUG(1,("Failed to modify record %s: %s\n",
                         ldb_dn_get_linearized(d_state->domain_dn),
                         ldb_errstring(sam_ctx)));
-
-               /* we really need samdb.c to return NTSTATUS */
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 
        return NT_STATUS_OK;
@@ -1200,13 +1205,13 @@ static NTSTATUS dcesrv_samr_CreateUser2(struct dcesrv_call_state *dce_call, TALL
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       status = dsdb_add_user(d_state->sam_ctx, mem_ctx, account_name, r->in.acct_flags, &sid, &dn);
+       status = dsdb_add_user(d_state->sam_ctx, mem_ctx, account_name, r->in.acct_flags, NULL,
+                              &sid, &dn);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
        a_state = talloc(mem_ctx, struct samr_account_state);
        if (!a_state) {
-               ldb_transaction_cancel(d_state->sam_ctx);
                return NT_STATUS_NO_MEMORY;
        }
        a_state->sam_ctx = d_state->sam_ctx;
@@ -1920,8 +1925,7 @@ static NTSTATUS dcesrv_samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TAL
        /* modify the samdb record */
        ret = ldb_modify(g_state->sam_ctx, msg);
        if (ret != LDB_SUCCESS) {
-               /* we really need samdb.c to return NTSTATUS */
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 
        return NT_STATUS_OK;
@@ -1987,7 +1991,7 @@ static NTSTATUS dcesrv_samr_AddGroupMember(struct dcesrv_call_state *dce_call, T
        ret = samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
                                                                memberdn);
        if (ret != LDB_SUCCESS) {
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 
        ret = ldb_modify(a_state->sam_ctx, mod);
@@ -1999,7 +2003,7 @@ static NTSTATUS dcesrv_samr_AddGroupMember(struct dcesrv_call_state *dce_call, T
        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
                return NT_STATUS_ACCESS_DENIED;
        default:
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 }
 
@@ -2022,7 +2026,7 @@ static NTSTATUS dcesrv_samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call
 
        ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
        if (ret != LDB_SUCCESS) {
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 
        talloc_free(h);
@@ -2103,7 +2107,7 @@ static NTSTATUS dcesrv_samr_DeleteGroupMember(struct dcesrv_call_state *dce_call
        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
                return NT_STATUS_ACCESS_DENIED;
        default:
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 }
 
@@ -2370,8 +2374,7 @@ static NTSTATUS dcesrv_samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TAL
        /* modify the samdb record */
        ret = ldb_modify(a_state->sam_ctx, msg);
        if (ret != LDB_SUCCESS) {
-               /* we really need samdb.c to return NTSTATUS */
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 
        return NT_STATUS_OK;
@@ -2396,7 +2399,7 @@ static NTSTATUS dcesrv_samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, T
 
        ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
        if (ret != LDB_SUCCESS) {
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 
        talloc_free(h);
@@ -2460,7 +2463,7 @@ static NTSTATUS dcesrv_samr_AddAliasMember(struct dcesrv_call_state *dce_call, T
        ret = samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
                                 ldb_dn_alloc_linearized(mem_ctx, memberdn));
        if (ret != LDB_SUCCESS) {
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 
        ret = ldb_modify(a_state->sam_ctx, mod);
@@ -2472,7 +2475,7 @@ static NTSTATUS dcesrv_samr_AddAliasMember(struct dcesrv_call_state *dce_call, T
        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
                return NT_STATUS_ACCESS_DENIED;
        default:
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 }
 
@@ -2512,7 +2515,7 @@ static NTSTATUS dcesrv_samr_DeleteAliasMember(struct dcesrv_call_state *dce_call
        ret = samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
                                                                 memberdn);
        if (ret != LDB_SUCCESS) {
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 
        ret = ldb_modify(a_state->sam_ctx, mod);
@@ -2524,7 +2527,7 @@ static NTSTATUS dcesrv_samr_DeleteAliasMember(struct dcesrv_call_state *dce_call
        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
                return NT_STATUS_ACCESS_DENIED;
        default:
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 }
 
@@ -2675,7 +2678,7 @@ static NTSTATUS dcesrv_samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLO
                DEBUG(1, ("Failed to delete user: %s: %s\n",
                          ldb_dn_get_linearized(a_state->account_dn),
                          ldb_errstring(a_state->sam_ctx)));
-               return NT_STATUS_UNSUCCESSFUL;
+               return dsdb_ldb_err_to_ntstatus(ret);
        }
 
        talloc_free(h);
@@ -3507,8 +3510,14 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL
                }
 
                if (r->in.info->info26.password_expired > 0) {
+                       NTTIME t = 0;
                        struct ldb_message_element *set_el;
-                       if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) {
+                       if (r->in.info->info26.password_expired
+                                       == PASS_DONT_CHANGE_AT_NEXT_LOGON) {
+                               unix_to_nt_time(&t, time(NULL));
+                       }
+                       if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg,
+                                                "pwdLastSet", t) != LDB_SUCCESS) {
                                return NT_STATUS_NO_MEMORY;
                        }
                        set_el = ldb_msg_find_element(msg, "pwdLastSet");
@@ -3533,8 +3542,7 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL
                                 ldb_dn_get_linearized(a_state->account_dn),
                                 ldb_errstring(a_state->sam_ctx)));
 
-                       /* we really need samdb.c to return NTSTATUS */
-                       return NT_STATUS_UNSUCCESSFUL;
+                       return dsdb_ldb_err_to_ntstatus(ret);
                }
        }
 
@@ -3621,8 +3629,8 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
 {
        struct dcesrv_handle *h;
        struct samr_domain_state *d_state;
-       struct ldb_message **res;
-       int i, ldb_cnt;
+       struct ldb_result *res;
+       unsigned int i;
        uint32_t count;
        const char * const attrs[] = { "objectSid", "sAMAccountName",
                "displayName", "description", "userAccountControl",
@@ -3632,6 +3640,7 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
        struct samr_DispEntryAscii *entriesAscii = NULL;
        struct samr_DispEntryGeneral *entriesGeneral = NULL;
        const char *filter;
+       int ret;
 
        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
 
@@ -3661,39 +3670,38 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
                return NT_STATUS_INVALID_INFO_CLASS;
        }
 
-       /* search for all requested objects in this domain. This could
+       /* search for all requested objects in all domains. This could
           possibly be cached and resumed based on resume_key */
-       ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
-                                     d_state->domain_dn, &res, attrs,
-                                     d_state->domain_sid, "%s", filter);
-       if (ldb_cnt == -1) {
+       ret = dsdb_search(d_state->sam_ctx, mem_ctx, &res, ldb_get_default_basedn(d_state->sam_ctx),
+                         LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
+       if (ret != LDB_SUCCESS) {
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
-       if (ldb_cnt == 0 || r->in.max_entries == 0) {
+       if ((res->count == 0) || (r->in.max_entries == 0)) {
                return NT_STATUS_OK;
        }
 
        switch (r->in.level) {
        case 1:
                entriesGeneral = talloc_array(mem_ctx,
-                                            struct samr_DispEntryGeneral,
-                                            ldb_cnt);
+                                             struct samr_DispEntryGeneral,
+                                             res->count);
                break;
        case 2:
                entriesFull = talloc_array(mem_ctx,
-                                            struct samr_DispEntryFull,
-                                            ldb_cnt);
+                                          struct samr_DispEntryFull,
+                                          res->count);
                break;
        case 3:
                entriesFullGroup = talloc_array(mem_ctx,
-                                            struct samr_DispEntryFullGroup,
-                                            ldb_cnt);
+                                               struct samr_DispEntryFullGroup,
+                                               res->count);
                break;
        case 4:
        case 5:
                entriesAscii = talloc_array(mem_ctx,
-                                             struct samr_DispEntryAscii,
-                                             ldb_cnt);
+                                           struct samr_DispEntryAscii,
+                                           res->count);
                break;
        }
 
@@ -3703,10 +3711,10 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
 
        count = 0;
 
-       for (i=0; i<ldb_cnt; i++) {
+       for (i = 0; i < res->count; i++) {
                struct dom_sid *objectsid;
 
-               objectsid = samdb_result_dom_sid(mem_ctx, res[i],
+               objectsid = samdb_result_dom_sid(mem_ctx, res->msgs[i],
                                                 "objectSid");
                if (objectsid == NULL)
                        continue;
@@ -3717,16 +3725,19 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
                        entriesGeneral[count].rid =
                                objectsid->sub_auths[objectsid->num_auths-1];
                        entriesGeneral[count].acct_flags =
-                               samdb_result_acct_flags(d_state->sam_ctx, mem_ctx,
-                                                       res[i],
+                               samdb_result_acct_flags(d_state->sam_ctx,
+                                                       mem_ctx,
+                                                       res->msgs[i],
                                                        d_state->domain_dn);
                        entriesGeneral[count].account_name.string =
-                               ldb_msg_find_attr_as_string(res[i],
-                                                   "sAMAccountName", "");
+                               ldb_msg_find_attr_as_string(res->msgs[i],
+                                                           "sAMAccountName", "");
                        entriesGeneral[count].full_name.string =
-                               ldb_msg_find_attr_as_string(res[i], "displayName", "");
+                               ldb_msg_find_attr_as_string(res->msgs[i],
+                                                           "displayName", "");
                        entriesGeneral[count].description.string =
-                               ldb_msg_find_attr_as_string(res[i], "description", "");
+                               ldb_msg_find_attr_as_string(res->msgs[i],
+                                                           "description", "");
                        break;
                case 2:
                        entriesFull[count].idx = count + 1;
@@ -3735,14 +3746,16 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
 
                        /* No idea why we need to or in ACB_NORMAL here, but this is what Win2k3 seems to do... */
                        entriesFull[count].acct_flags =
-                               samdb_result_acct_flags(d_state->sam_ctx, mem_ctx,
-                                                       res[i],
+                               samdb_result_acct_flags(d_state->sam_ctx,
+                                                       mem_ctx,
+                                                       res->msgs[i],
                                                        d_state->domain_dn) | ACB_NORMAL;
                        entriesFull[count].account_name.string =
-                               ldb_msg_find_attr_as_string(res[i], "sAMAccountName",
-                                                   "");
+                               ldb_msg_find_attr_as_string(res->msgs[i],
+                                                           "sAMAccountName", "");
                        entriesFull[count].description.string =
-                               ldb_msg_find_attr_as_string(res[i], "description", "");
+                               ldb_msg_find_attr_as_string(res->msgs[i],
+                                                           "description", "");
                        break;
                case 3:
                        entriesFullGroup[count].idx = count + 1;
@@ -3752,17 +3765,18 @@ static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call,
                        entriesFullGroup[count].acct_flags
                                = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
                        entriesFullGroup[count].account_name.string =
-                               ldb_msg_find_attr_as_string(res[i], "sAMAccountName",
-                                                   "");
+                               ldb_msg_find_attr_as_string(res->msgs[i],
+                                                           "sAMAccountName", "");
                        entriesFullGroup[count].description.string =
-                               ldb_msg_find_attr_as_string(res[i], "description", "");
+                               ldb_msg_find_attr_as_string(res->msgs[i],
+                                                           "description", "");
                        break;
                case 4:
                case 5:
                        entriesAscii[count].idx = count + 1;
                        entriesAscii[count].account_name.string =
-                               ldb_msg_find_attr_as_string(res[i], "sAMAccountName",
-                                                   "");
+                               ldb_msg_find_attr_as_string(res->msgs[i],
+                                                           "sAMAccountName", "");
                        break;
                }
 
@@ -3927,6 +3941,7 @@ static NTSTATUS dcesrv_samr_RemoveMemberFromForeignDomain(struct dcesrv_call_sta
 
        for (i=0; i<count; i++) {
                struct ldb_message *mod;
+               int ret;
 
                mod = ldb_msg_new(mem_ctx);
                if (mod == NULL) {
@@ -3939,10 +3954,11 @@ static NTSTATUS dcesrv_samr_RemoveMemberFromForeignDomain(struct dcesrv_call_sta
                                         "member", memberdn) != LDB_SUCCESS)
                        return NT_STATUS_NO_MEMORY;
 
-               if (ldb_modify(d_state->sam_ctx, mod) != LDB_SUCCESS)
-                       return NT_STATUS_UNSUCCESSFUL;
-
+               ret = ldb_modify(d_state->sam_ctx, mod);
                talloc_free(mod);
+               if (ret != LDB_SUCCESS) {
+                       return dsdb_ldb_err_to_ntstatus(ret);
+               }
        }
 
        return NT_STATUS_OK;
@@ -4280,6 +4296,11 @@ static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call,
        DATA_BLOB password;
        enum samr_ValidationStatus res;
        NTSTATUS status;
+       enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
+
+       if (transport != NCACN_IP_TCP && transport != NCALRPC) {
+               DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
+       }
 
        (*r->out.rep) = talloc_zero(mem_ctx, union samr_ValidatePasswordRep);