Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source4/rpc_server/samr/dcesrv_samr.c

    r414 r745  
    1 /* 
     1/*
    22   Unix SMB/CIFS implementation.
    33
     
    88   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
    99   Copyright (C) Matthias Dieter Wallnöfer 2009
    10    
     10
    1111   This program is free software; you can redistribute it and/or modify
    1212   it under the terms of the GNU General Public License as published by
    1313   the Free Software Foundation; either version 3 of the License, or
    1414   (at your option) any later version.
    15    
     15
    1616   This program is distributed in the hope that it will be useful,
    1717   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1818   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1919   GNU General Public License for more details.
    20    
     20
    2121   You should have received a copy of the GNU General Public License
    2222   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2929#include "rpc_server/samr/dcesrv_samr.h"
    3030#include "system/time.h"
    31 #include "lib/ldb/include/ldb.h"
    32 #include "lib/ldb/include/ldb_errors.h"
     31#include <ldb.h>
     32#include <ldb_errors.h>
    3333#include "../libds/common/flags.h"
    3434#include "dsdb/samdb/samdb.h"
     35#include "dsdb/common/util.h"
    3536#include "libcli/ldap/ldap_ndr.h"
    3637#include "libcli/security/security.h"
     
    3839#include "../lib/util/util_ldb.h"
    3940#include "param/param.h"
     41#include "lib/util/tsort.h"
     42#include "libds/common/flag_mapping.h"
    4043
    4144/* these query macros make samr_Query[User|Group|Alias]Info a bit easier to read */
    4245
    4346#define QUERY_STRING(msg, field, attr) \
    44         info->field.string = samdb_result_string(msg, attr, "");
     47        info->field.string = ldb_msg_find_attr_as_string(msg, attr, "");
    4548#define QUERY_UINT(msg, field, attr) \
    46         info->field = samdb_result_uint(msg, attr, 0);
     49        info->field = ldb_msg_find_attr_as_uint(msg, attr, 0);
    4750#define QUERY_RID(msg, field, attr) \
    4851        info->field = samdb_result_rid_from_sid(mem_ctx, msg, attr, 0);
    4952#define QUERY_UINT64(msg, field, attr) \
    50         info->field = samdb_result_uint64(msg, attr, 0);
     53        info->field = ldb_msg_find_attr_as_uint64(msg, attr, 0);
    5154#define QUERY_APASSC(msg, field, attr) \
    5255        info->field = samdb_result_allow_password_change(sam_ctx, mem_ctx, \
     
    6972        if (r->in.info->field.string == NULL) return NT_STATUS_INVALID_PARAMETER; \
    7073        if (r->in.info->field.string[0] == '\0') {                      \
    71                 if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, NULL)) { \
     74                if (ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, NULL) != LDB_SUCCESS) { \
    7275                        return NT_STATUS_NO_MEMORY;                     \
    7376                }                                                       \
    7477        }                                                               \
    75         if (ldb_msg_add_string(msg, attr, r->in.info->field.string) != 0) { \
     78        if (ldb_msg_add_string(msg, attr, r->in.info->field.string) != LDB_SUCCESS) { \
    7679                return NT_STATUS_NO_MEMORY;                             \
    7780        }                                                               \
     
    8285#define SET_UINT(msg, field, attr) do {                                 \
    8386        struct ldb_message_element *set_el;                             \
    84         if (samdb_msg_add_uint(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
     87        if (samdb_msg_add_uint(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != LDB_SUCCESS) { \
    8588                return NT_STATUS_NO_MEMORY;                             \
    8689        }                                                               \
    8790        set_el = ldb_msg_find_element(msg, attr);                       \
    8891        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
    89 } while (0)                                                             
    90                                                                        
     92} while (0)
     93
    9194#define SET_INT64(msg, field, attr) do {                                \
    9295        struct ldb_message_element *set_el;                             \
    93         if (samdb_msg_add_int64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
     96        if (samdb_msg_add_int64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != LDB_SUCCESS) { \
    9497                return NT_STATUS_NO_MEMORY;                             \
    9598        }                                                               \
    9699        set_el = ldb_msg_find_element(msg, attr);                       \
    97100        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
    98 } while (0)                                                             
    99                                                                        
     101} while (0)
     102
    100103#define SET_UINT64(msg, field, attr) do {                               \
    101104        struct ldb_message_element *set_el;                             \
    102         if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != 0) { \
     105        if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, attr, r->in.info->field) != LDB_SUCCESS) { \
    103106                return NT_STATUS_NO_MEMORY;                             \
    104107        }                                                               \
    105108        set_el = ldb_msg_find_element(msg, attr);                       \
    106109        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
    107 } while (0)                                                             
     110} while (0)
    108111
    109112#define CHECK_FOR_MULTIPLES(value, flag, poss_flags)    \
     
    113116                }                                                       \
    114117        } while (0)                                                     \
    115        
    116 /* Set account flags, discarding flags that cannot be set with SAMR */                                                         
     118
     119/* Set account flags, discarding flags that cannot be set with SAMR */
    117120#define SET_AFLAGS(msg, field, attr) do {                               \
    118121        struct ldb_message_element *set_el;                             \
     
    129132        set_el = ldb_msg_find_element(msg, attr);                       \
    130133        set_el->flags = LDB_FLAG_MOD_REPLACE;                           \
    131 } while (0)                                                             
    132                                                                        
     134} while (0)
     135
    133136#define SET_LHOURS(msg, field, attr) do {                               \
    134137        struct ldb_message_element *set_el;                             \
    135         if (samdb_msg_add_logon_hours(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
     138        if (samdb_msg_add_logon_hours(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != LDB_SUCCESS) { \
    136139                return NT_STATUS_NO_MEMORY;                             \
    137140        }                                                               \
     
    143146        struct ldb_message_element *set_el;                             \
    144147        if (r->in.info->field.length != 0) {                            \
    145                 if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != 0) { \
     148                if (samdb_msg_add_parameters(sam_ctx, mem_ctx, msg, attr, &r->in.info->field) != LDB_SUCCESS) { \
    146149                        return NT_STATUS_NO_MEMORY;                     \
    147150                }                                                       \
     
    153156
    154157
    155 /* 
    156   samr_Connect 
     158/*
     159  samr_Connect
    157160
    158161  create a connection to the SAM database
     
    166169        ZERO_STRUCTP(r->out.connect_handle);
    167170
    168         c_state = talloc(dce_call->conn, struct samr_connect_state);
     171        c_state = talloc(mem_ctx, struct samr_connect_state);
    169172        if (!c_state) {
    170173                return NT_STATUS_NO_MEMORY;
     
    172175
    173176        /* make sure the sam database is accessible */
    174         c_state->sam_ctx = samdb_connect(c_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
     177        c_state->sam_ctx = samdb_connect(c_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info, 0);
    175178        if (c_state->sam_ctx == NULL) {
    176179                talloc_free(c_state);
     
    194197
    195198
    196 /* 
    197   samr_Close 
     199/*
     200  samr_Close
    198201*/
    199202static NTSTATUS dcesrv_samr_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    214217
    215218
    216 /* 
    217   samr_SetSecurity 
     219/*
     220  samr_SetSecurity
    218221*/
    219222static NTSTATUS dcesrv_samr_SetSecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    224227
    225228
    226 /* 
    227   samr_QuerySecurity 
     229/*
     230  samr_QuerySecurity
    228231*/
    229232static NTSTATUS dcesrv_samr_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    250253
    251254
    252 /* 
    253   samr_Shutdown 
     255/*
     256  samr_Shutdown
    254257
    255258  we refuse this operation completely. If a admin wants to shutdown samr
     
    263266
    264267
    265 /* 
    266   samr_LookupDomain 
     268/*
     269  samr_LookupDomain
    267270
    268271  this maps from a domain name to a SID
     
    292295                                   mem_ctx, NULL, &dom_msgs, dom_attrs,
    293296                                   "(objectClass=builtinDomain)");
    294         } else if (strcasecmp_m(r->in.domain_name->string, lp_sam_name(dce_call->conn->dce_ctx->lp_ctx)) == 0) {
     297        } else if (strcasecmp_m(r->in.domain_name->string, lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx)) == 0) {
    295298                ret = gendb_search_dn(c_state->sam_ctx,
    296                                       mem_ctx, ldb_get_default_basedn(c_state->sam_ctx), 
     299                                      mem_ctx, ldb_get_default_basedn(c_state->sam_ctx),
    297300                                      &dom_msgs, dom_attrs);
    298301        } else {
     
    302305                return NT_STATUS_NO_SUCH_DOMAIN;
    303306        }
    304        
     307
    305308        sid = samdb_result_dom_sid(mem_ctx, dom_msgs[0],
    306309                                   "objectSid");
    307                
     310
    308311        if (sid == NULL) {
    309312                return NT_STATUS_NO_SUCH_DOMAIN;
     
    316319
    317320
    318 /* 
    319   samr_EnumDomains 
     321/*
     322  samr_EnumDomains
    320323
    321324  list the domains in the SAM
     
    327330        struct dcesrv_handle *h;
    328331        struct samr_SamArray *array;
    329         int i, start_i;
     332        uint32_t i, start_i;
    330333
    331334        *r->out.resume_handle = 0;
     
    350353                return NT_STATUS_NO_MEMORY;
    351354        }
    352                
     355
    353356        array->count = 0;
    354357        array->entries = NULL;
     
    362365                array->entries[i].idx = start_i + i;
    363366                if (i == 0) {
    364                         array->entries[i].name.string = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
     367                        array->entries[i].name.string = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
    365368                } else {
    366369                        array->entries[i].name.string = "BUILTIN";
     
    376379
    377380
    378 /* 
    379   samr_OpenDomain 
     381/*
     382  samr_OpenDomain
    380383*/
    381384static NTSTATUS dcesrv_samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    399402        }
    400403
    401         d_state = talloc(c_state, struct samr_domain_state);
     404        d_state = talloc(mem_ctx, struct samr_domain_state);
    402405        if (!d_state) {
    403406                return NT_STATUS_NO_MEMORY;
     
    411414        } else {
    412415                d_state->builtin = false;
    413                 d_state->domain_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
     416                d_state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
    414417        }
    415418
    416419        ret = gendb_search(c_state->sam_ctx,
    417420                           mem_ctx, ldb_get_default_basedn(c_state->sam_ctx), &dom_msgs, dom_attrs,
    418                            "(objectSid=%s)", 
     421                           "(objectSid=%s)",
    419422                           ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
    420        
     423
    421424        if (ret == 0) {
    422425                talloc_free(d_state);
     
    432435
    433436        d_state->domain_dn = talloc_steal(d_state, dom_msgs[0]->dn);
    434         d_state->role = lp_server_role(dce_call->conn->dce_ctx->lp_ctx);
     437        d_state->role = lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx);
    435438        d_state->connect_state = talloc_reference(d_state, c_state);
    436439        d_state->sam_ctx = c_state->sam_ctx;
     
    444447                return NT_STATUS_NO_MEMORY;
    445448        }
    446        
     449
    447450        h_domain->data = talloc_steal(h_domain, d_state);
    448451
     
    456459*/
    457460static NTSTATUS dcesrv_samr_info_DomInfo1(struct samr_domain_state *state,
    458                                    TALLOC_CTX *mem_ctx,
    459                                     struct ldb_message **dom_msgs,
    460                                    struct samr_DomInfo1 *info)
     461                                          TALLOC_CTX *mem_ctx,
     462                                          struct ldb_message **dom_msgs,
     463                                          struct samr_DomInfo1 *info)
    461464{
    462465        info->min_password_length =
    463                 samdb_result_uint(dom_msgs[0], "minPwdLength", 0);
     466                ldb_msg_find_attr_as_uint(dom_msgs[0], "minPwdLength", 0);
    464467        info->password_history_length =
    465                 samdb_result_uint(dom_msgs[0], "pwdHistoryLength", 0);
    466         info->password_properties = 
    467                 samdb_result_uint(dom_msgs[0], "pwdProperties", 0);
    468         info->max_password_age = 
    469                 samdb_result_int64(dom_msgs[0], "maxPwdAge", 0);
    470         info->min_password_age = 
    471                 samdb_result_int64(dom_msgs[0], "minPwdAge", 0);
     468                ldb_msg_find_attr_as_uint(dom_msgs[0], "pwdHistoryLength", 0);
     469        info->password_properties =
     470                ldb_msg_find_attr_as_uint(dom_msgs[0], "pwdProperties", 0);
     471        info->max_password_age =
     472                ldb_msg_find_attr_as_int64(dom_msgs[0], "maxPwdAge", 0);
     473        info->min_password_age =
     474                ldb_msg_find_attr_as_int64(dom_msgs[0], "minPwdAge", 0);
    472475
    473476        return NT_STATUS_OK;
     
    477480  return DomInfo2
    478481*/
    479 static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state *state, 
     482static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state *state,
    480483                                                       TALLOC_CTX *mem_ctx,
    481484                                                       struct ldb_message **dom_msgs,
    482485                                                       struct samr_DomGeneralInformation *info)
    483486{
    484         /* This pulls the NetBIOS name from the
    485            cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
    486            string */
    487         info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx, dom_msgs[0], "fSMORoleOwner");
    488 
    489         if (!info->primary.string) {
    490                 info->primary.string = lp_netbios_name(state->lp_ctx);
    491         }
    492 
    493         info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff",
     487        /* MS-SAMR 2.2.4.1 - ReplicaSourceNodeName: "domainReplica" attribute */
     488        info->primary.string = ldb_msg_find_attr_as_string(dom_msgs[0],
     489                                                           "domainReplica",
     490                                                           "");
     491
     492        info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff",
    494493                                                            0x8000000000000000LL);
    495494
    496         info->oem_information.string = samdb_result_string(dom_msgs[0], "oEMInformation", NULL);
     495        info->oem_information.string = ldb_msg_find_attr_as_string(dom_msgs[0],
     496                                                                   "oEMInformation",
     497                                                                   "");
    497498        info->domain_name.string  = state->domain_name;
    498499
    499         info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 
     500        info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount",
    500501                                                 0);
    501502        switch (state->role) {
    502503        case ROLE_DOMAIN_CONTROLLER:
    503                 /* This pulls the NetBIOS name from the 
     504                /* This pulls the NetBIOS name from the
    504505                   cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
    505506                   string */
     
    518519        }
    519520
    520         /* No users in BUILTIN, and the LOCAL group types are only in builtin, and the global group type is never in BUILTIN */
    521         info->num_users = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
     521        info->num_users = samdb_search_count(state->sam_ctx, mem_ctx,
     522                                             state->domain_dn,
    522523                                             "(objectClass=user)");
    523         info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
    524                                               "(&(objectClass=group)(sAMAccountType=%u))",
    525                                               ATYPE_GLOBAL_GROUP);
    526         info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx, state->domain_dn,
    527                                                "(&(objectClass=group)(sAMAccountType=%u))",
    528                                                ATYPE_LOCAL_GROUP);
     524        info->num_groups = samdb_search_count(state->sam_ctx, mem_ctx,
     525                                              state->domain_dn,
     526                                              "(&(objectClass=group)(|(groupType=%d)(groupType=%d)))",
     527                                              GTYPE_SECURITY_UNIVERSAL_GROUP,
     528                                              GTYPE_SECURITY_GLOBAL_GROUP);
     529        info->num_aliases = samdb_search_count(state->sam_ctx, mem_ctx,
     530                                               state->domain_dn,
     531                                               "(&(objectClass=group)(|(groupType=%d)(groupType=%d)))",
     532                                               GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
     533                                               GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
    529534
    530535        return NT_STATUS_OK;
     
    535540*/
    536541static NTSTATUS dcesrv_samr_info_DomInfo3(struct samr_domain_state *state,
    537                                    TALLOC_CTX *mem_ctx,
    538                                     struct ldb_message **dom_msgs,
    539                                    struct samr_DomInfo3 *info)
    540 {
    541         info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff", 
     542                                          TALLOC_CTX *mem_ctx,
     543                                          struct ldb_message **dom_msgs,
     544                                          struct samr_DomInfo3 *info)
     545{
     546        info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff",
    542547                                                      0x8000000000000000LL);
    543548
     
    553558                                   struct samr_DomOEMInformation *info)
    554559{
    555         info->oem_information.string = samdb_result_string(dom_msgs[0], "oEMInformation", NULL);
     560        info->oem_information.string = ldb_msg_find_attr_as_string(dom_msgs[0],
     561                                                                   "oEMInformation",
     562                                                                   "");
    556563
    557564        return NT_STATUS_OK;
     
    562569*/
    563570static NTSTATUS dcesrv_samr_info_DomInfo5(struct samr_domain_state *state,
    564                                    TALLOC_CTX *mem_ctx,
    565                                     struct ldb_message **dom_msgs,
    566                                    struct samr_DomInfo5 *info)
     571                                          TALLOC_CTX *mem_ctx,
     572                                          struct ldb_message **dom_msgs,
     573                                          struct samr_DomInfo5 *info)
    567574{
    568575        info->domain_name.string  = state->domain_name;
     
    575582*/
    576583static NTSTATUS dcesrv_samr_info_DomInfo6(struct samr_domain_state *state,
    577                                    TALLOC_CTX *mem_ctx,
    578                                    struct ldb_message **dom_msgs,
    579                                    struct samr_DomInfo6 *info)
    580 {
    581         /* This pulls the NetBIOS name from the
    582            cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
    583            string */
    584         info->primary.string = samdb_result_fsmo_name(state->sam_ctx, mem_ctx,
    585                                                       dom_msgs[0], "fSMORoleOwner");
    586 
    587         if (!info->primary.string) {
    588                 info->primary.string = lp_netbios_name(state->lp_ctx);
    589         }
     584                                          TALLOC_CTX *mem_ctx,
     585                                          struct ldb_message **dom_msgs,
     586                                          struct samr_DomInfo6 *info)
     587{
     588        /* MS-SAMR 2.2.4.1 - ReplicaSourceNodeName: "domainReplica" attribute */
     589        info->primary.string = ldb_msg_find_attr_as_string(dom_msgs[0],
     590                                                           "domainReplica",
     591                                                           "");
    590592
    591593        return NT_STATUS_OK;
     
    596598*/
    597599static NTSTATUS dcesrv_samr_info_DomInfo7(struct samr_domain_state *state,
    598                                    TALLOC_CTX *mem_ctx,
    599                                     struct ldb_message **dom_msgs,
    600                                    struct samr_DomInfo7 *info)
     600                                          TALLOC_CTX *mem_ctx,
     601                                          struct ldb_message **dom_msgs,
     602                                          struct samr_DomInfo7 *info)
    601603{
    602604
    603605        switch (state->role) {
    604606        case ROLE_DOMAIN_CONTROLLER:
    605                 /* This pulls the NetBIOS name from the 
     607                /* This pulls the NetBIOS name from the
    606608                   cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
    607609                   string */
     
    627629*/
    628630static NTSTATUS dcesrv_samr_info_DomInfo8(struct samr_domain_state *state,
    629                                    TALLOC_CTX *mem_ctx,
    630                                     struct ldb_message **dom_msgs,
    631                                    struct samr_DomInfo8 *info)
    632 {
    633         info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 
     631                                          TALLOC_CTX *mem_ctx,
     632                                          struct ldb_message **dom_msgs,
     633                                          struct samr_DomInfo8 *info)
     634{
     635        info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount",
    634636                                               time(NULL));
    635637
     
    644646*/
    645647static NTSTATUS dcesrv_samr_info_DomInfo9(struct samr_domain_state *state,
    646                                    TALLOC_CTX *mem_ctx,
    647                                     struct ldb_message **dom_msgs,
    648                                    struct samr_DomInfo9 *info)
     648                                          TALLOC_CTX *mem_ctx,
     649                                          struct ldb_message **dom_msgs,
     650                                          struct samr_DomInfo9 *info)
    649651{
    650652        info->domain_server_state = DOMAIN_SERVER_ENABLED;
     
    657659*/
    658660static NTSTATUS dcesrv_samr_info_DomGeneralInformation2(struct samr_domain_state *state,
    659                                     TALLOC_CTX *mem_ctx,
    660                                     struct ldb_message **dom_msgs,
    661                                     struct samr_DomGeneralInformation2 *info)
     661                                                        TALLOC_CTX *mem_ctx,
     662                                                        struct ldb_message **dom_msgs,
     663                                                        struct samr_DomGeneralInformation2 *info)
    662664{
    663665        NTSTATUS status;
     
    666668                return status;
    667669        }
    668        
    669         info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration", 
     670
     671        info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration",
    670672                                                    -18000000000LL);
    671673        info->lockout_window = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockOutObservationWindow",
     
    680682*/
    681683static NTSTATUS dcesrv_samr_info_DomInfo12(struct samr_domain_state *state,
    682                                    TALLOC_CTX *mem_ctx,
    683                                     struct ldb_message **dom_msgs,
    684                                    struct samr_DomInfo12 *info)
    685 {
    686         info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration", 
     684                                           TALLOC_CTX *mem_ctx,
     685                                           struct ldb_message **dom_msgs,
     686                                           struct samr_DomInfo12 *info)
     687{
     688        info->lockout_duration = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockoutDuration",
    687689                                                    -18000000000LL);
    688690        info->lockout_window = ldb_msg_find_attr_as_int64(dom_msgs[0], "lockOutObservationWindow",
     
    697699*/
    698700static NTSTATUS dcesrv_samr_info_DomInfo13(struct samr_domain_state *state,
    699                                     TALLOC_CTX *mem_ctx,
    700                                     struct ldb_message **dom_msgs,
    701                                     struct samr_DomInfo13 *info)
    702 {
    703         info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", 
     701                                           TALLOC_CTX *mem_ctx,
     702                                           struct ldb_message **dom_msgs,
     703                                           struct samr_DomInfo13 *info)
     704{
     705        info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount",
    704706                                               time(NULL));
    705707
     
    712714}
    713715
    714 /*
    715   samr_QueryDomainInfo
    716 */
    717 static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    718                                      struct samr_QueryDomainInfo *r)
     716/*
     717  samr_QueryDomainInfo
     718*/
     719static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call,
     720                                            TALLOC_CTX *mem_ctx,
     721                                            struct samr_QueryDomainInfo *r)
    719722{
    720723        struct dcesrv_handle *h;
     
    724727        struct ldb_message **dom_msgs;
    725728        const char * const *attrs = NULL;
    726        
     729
    727730        *r->out.info = NULL;
    728731
     
    731734        d_state = h->data;
    732735
    733         info = talloc(mem_ctx, union samr_DomainInfo);
    734         if (!info) {
    735                 return NT_STATUS_NO_MEMORY;
    736         }
    737 
    738736        switch (r->in.level) {
    739         case 1: 
     737        case 1:
    740738        {
    741739                static const char * const attrs2[] = { "minPwdLength",
     
    751749        {
    752750                static const char * const attrs2[] = {"forceLogoff",
    753                                                       "oEMInformation", 
    754                                                       "modifiedCount", 
    755                                                       "fSMORoleOwner",
     751                                                      "oEMInformation",
     752                                                      "modifiedCount",
     753                                                      "domainReplica",
    756754                                                      NULL};
    757755                attrs = attrs2;
     
    760758        case 3:
    761759        {
    762                 static const char * const attrs2[] = {"forceLogoff", 
     760                static const char * const attrs2[] = {"forceLogoff",
    763761                                                      NULL};
    764762                attrs = attrs2;
     
    767765        case 4:
    768766        {
    769                 static const char * const attrs2[] = {"oEMInformation", 
     767                static const char * const attrs2[] = {"oEMInformation",
    770768                                                      NULL};
    771769                attrs = attrs2;
     
    779777        case 6:
    780778        {
    781                 static const char * const attrs2[] = {"fSMORoleOwner",
    782                                                       NULL};
     779                static const char * const attrs2[] = { "domainReplica",
     780                                                       NULL };
    783781                attrs = attrs2;
    784782                break;
     
    791789        case 8:
    792790        {
    793                 static const char * const attrs2[] = { "modifiedCount", 
    794                                                        "creationTime", 
     791                static const char * const attrs2[] = { "modifiedCount",
     792                                                       "creationTime",
    795793                                                       NULL };
    796794                attrs = attrs2;
     
    798796        }
    799797        case 9:
     798        {
    800799                attrs = NULL;
    801                 break;         
     800                break;
     801        }
    802802        case 11:
    803803        {
    804804                static const char * const attrs2[] = { "oEMInformation",
    805805                                                       "forceLogoff",
    806                                                        "modifiedCount", 
    807                                                        "lockoutDuration", 
    808                                                        "lockOutObservationWindow", 
    809                                                        "lockoutThreshold", 
     806                                                       "modifiedCount",
     807                                                       "lockoutDuration",
     808                                                       "lockOutObservationWindow",
     809                                                       "lockoutThreshold",
    810810                                                       NULL};
    811811                attrs = attrs2;
     
    814814        case 12:
    815815        {
    816                 static const char * const attrs2[] = { "lockoutDuration", 
    817                                                        "lockOutObservationWindow", 
    818                                                        "lockoutThreshold", 
     816                static const char * const attrs2[] = { "lockoutDuration",
     817                                                       "lockOutObservationWindow",
     818                                                       "lockoutThreshold",
    819819                                                       NULL};
    820820                attrs = attrs2;
     
    823823        case 13:
    824824        {
    825                 static const char * const attrs2[] = { "modifiedCount", 
    826                                                        "creationTime", 
     825                static const char * const attrs2[] = { "modifiedCount",
     826                                                       "creationTime",
    827827                                                       NULL };
    828828                attrs = attrs2;
    829829                break;
     830        }
     831        default:
     832        {
     833                return NT_STATUS_INVALID_INFO_CLASS;
    830834        }
    831835        }
     
    836840                ret = gendb_search_dn(d_state->sam_ctx, mem_ctx,
    837841                                      d_state->domain_dn, &dom_msgs, attrs);
     842                if (ret == 0) {
     843                        return NT_STATUS_NO_SUCH_DOMAIN;
     844                }
    838845                if (ret != 1) {
    839846                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     
    841848        }
    842849
     850        /* allocate the info structure */
     851        info = talloc_zero(mem_ctx, union samr_DomainInfo);
     852        if (info == NULL) {
     853                return NT_STATUS_NO_MEMORY;
     854        }
     855
    843856        *r->out.info = info;
    844 
    845         ZERO_STRUCTP(info);
    846857
    847858        switch (r->in.level) {
    848859        case 1:
    849                 return dcesrv_samr_info_DomInfo1(d_state, mem_ctx, dom_msgs, 
     860                return dcesrv_samr_info_DomInfo1(d_state, mem_ctx, dom_msgs,
    850861                                                 &info->info1);
    851862        case 2:
    852                 return dcesrv_samr_info_DomGeneralInformation(d_state, mem_ctx, dom_msgs, 
     863                return dcesrv_samr_info_DomGeneralInformation(d_state, mem_ctx, dom_msgs,
    853864                                                              &info->general);
    854865        case 3:
    855                 return dcesrv_samr_info_DomInfo3(d_state, mem_ctx, dom_msgs, 
     866                return dcesrv_samr_info_DomInfo3(d_state, mem_ctx, dom_msgs,
    856867                                                 &info->info3);
    857868        case 4:
    858                 return dcesrv_samr_info_DomOEMInformation(d_state, mem_ctx, dom_msgs, 
     869                return dcesrv_samr_info_DomOEMInformation(d_state, mem_ctx, dom_msgs,
    859870                                                          &info->oem);
    860871        case 5:
    861                 return dcesrv_samr_info_DomInfo5(d_state, mem_ctx, dom_msgs, 
     872                return dcesrv_samr_info_DomInfo5(d_state, mem_ctx, dom_msgs,
    862873                                                 &info->info5);
    863874        case 6:
    864                 return dcesrv_samr_info_DomInfo6(d_state, mem_ctx, dom_msgs, 
     875                return dcesrv_samr_info_DomInfo6(d_state, mem_ctx, dom_msgs,
    865876                                                 &info->info6);
    866877        case 7:
    867                 return dcesrv_samr_info_DomInfo7(d_state, mem_ctx, dom_msgs, 
     878                return dcesrv_samr_info_DomInfo7(d_state, mem_ctx, dom_msgs,
    868879                                                 &info->info7);
    869880        case 8:
    870                 return dcesrv_samr_info_DomInfo8(d_state, mem_ctx, dom_msgs, 
     881                return dcesrv_samr_info_DomInfo8(d_state, mem_ctx, dom_msgs,
    871882                                                 &info->info8);
    872883        case 9:
    873                 return dcesrv_samr_info_DomInfo9(d_state, mem_ctx, dom_msgs, 
     884                return dcesrv_samr_info_DomInfo9(d_state, mem_ctx, dom_msgs,
    874885                                                 &info->info9);
    875886        case 11:
    876                 return dcesrv_samr_info_DomGeneralInformation2(d_state, mem_ctx, dom_msgs, 
     887                return dcesrv_samr_info_DomGeneralInformation2(d_state, mem_ctx, dom_msgs,
    877888                                                               &info->general2);
    878889        case 12:
    879                 return dcesrv_samr_info_DomInfo12(d_state, mem_ctx, dom_msgs, 
     890                return dcesrv_samr_info_DomInfo12(d_state, mem_ctx, dom_msgs,
    880891                                                  &info->info12);
    881892        case 13:
    882                 return dcesrv_samr_info_DomInfo13(d_state, mem_ctx, dom_msgs, 
     893                return dcesrv_samr_info_DomInfo13(d_state, mem_ctx, dom_msgs,
    883894                                                  &info->info13);
    884         }
    885 
    886         return NT_STATUS_INVALID_INFO_CLASS;
    887 }
    888 
    889 
    890 /* 
    891   samr_SetDomainInfo 
     895        default:
     896                return NT_STATUS_INVALID_INFO_CLASS;
     897        }
     898}
     899
     900
     901/*
     902  samr_SetDomainInfo
    892903*/
    893904static NTSTATUS dcesrv_samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    937948
    938949        case 12:
    939                
     950                /*
     951                 * It is not possible to set lockout_duration < lockout_window.
     952                 * (The test is the other way around since the negative numbers
     953                 *  are stored...)
     954                 *
     955                 * TODO:
     956                 *   This check should be moved to the backend, i.e. to some
     957                 *   ldb module under dsdb/samdb/ldb_modules/ .
     958                 *
     959                 * This constraint is documented here for the samr rpc service:
     960                 * MS-SAMR 3.1.1.6 Attribute Constraints for Originating Updates
     961                 * http://msdn.microsoft.com/en-us/library/cc245667%28PROT.10%29.aspx
     962                 *
     963                 * And here for the ldap backend:
     964                 * MS-ADTS 3.1.1.5.3.2 Constraints
     965                 * http://msdn.microsoft.com/en-us/library/cc223462(PROT.10).aspx
     966                 */
     967                if (r->in.info->info12.lockout_duration >
     968                    r->in.info->info12.lockout_window)
     969                {
     970                        return NT_STATUS_INVALID_PARAMETER;
     971                }
    940972                SET_INT64  (msg, info12.lockout_duration,      "lockoutDuration");
    941973                SET_INT64  (msg, info12.lockout_window,        "lockOutObservationWindow");
     
    950982        /* modify the samdb record */
    951983        ret = ldb_modify(sam_ctx, msg);
    952         if (ret != 0) {
     984        if (ret != LDB_SUCCESS) {
    953985                DEBUG(1,("Failed to modify record %s: %s\n",
    954986                         ldb_dn_get_linearized(d_state->domain_dn),
     
    962994}
    963995
    964 /* 
    965   samr_CreateDomainGroup 
     996/*
     997  samr_CreateDomainGroup
    966998*/
    967999static NTSTATUS dcesrv_samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    9681000                                       struct samr_CreateDomainGroup *r)
    9691001{
     1002        NTSTATUS status;
    9701003        struct samr_domain_state *d_state;
    9711004        struct samr_account_state *a_state;
    9721005        struct dcesrv_handle *h;
    973         const char *name;
    974         struct ldb_message *msg;
    975         struct dom_sid *sid;
    9761006        const char *groupname;
     1007        struct dom_sid *group_sid;
     1008        struct ldb_dn *group_dn;
    9771009        struct dcesrv_handle *g_handle;
    978         int ret;
    9791010
    9801011        ZERO_STRUCTP(r->out.group_handle);
     
    9961027        }
    9971028
    998         /* check if the group already exists */
    999         name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
    1000                                    "sAMAccountName",
    1001                                    "(&(sAMAccountName=%s)(objectclass=group))",
    1002                                    ldb_binary_encode_string(mem_ctx, groupname));
    1003         if (name != NULL) {
    1004                 return NT_STATUS_GROUP_EXISTS;
    1005         }
    1006 
    1007         msg = ldb_msg_new(mem_ctx);
    1008         if (msg == NULL) {
    1009                 return NT_STATUS_NO_MEMORY;
    1010         }
    1011 
    1012         /* add core elements to the ldb_message for the user */
    1013         msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
    1014         ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", groupname);
    1015         if (!msg->dn) {
    1016                 return NT_STATUS_NO_MEMORY;
    1017         }
    1018         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", groupname);
    1019         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");
    1020                              
    1021         /* create the group */
    1022         ret = ldb_add(d_state->sam_ctx, msg);
    1023         switch (ret) {
    1024         case  LDB_SUCCESS:
    1025                 break;
    1026         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
    1027                 DEBUG(0,("Failed to create group record %s: %s\n",
    1028                          ldb_dn_get_linearized(msg->dn),
    1029                          ldb_errstring(d_state->sam_ctx)));
    1030                 return NT_STATUS_GROUP_EXISTS;
    1031         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
    1032                 DEBUG(0,("Failed to create group record %s: %s\n",
    1033                          ldb_dn_get_linearized(msg->dn),
    1034                          ldb_errstring(d_state->sam_ctx)));
    1035                 return NT_STATUS_ACCESS_DENIED;
    1036         default:
    1037                 DEBUG(0,("Failed to create group record %s: %s\n",
    1038                          ldb_dn_get_linearized(msg->dn),
    1039                          ldb_errstring(d_state->sam_ctx)));
    1040                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1041         }
    1042 
    1043         a_state = talloc(d_state, struct samr_account_state);
     1029        status = dsdb_add_domain_group(d_state->sam_ctx, mem_ctx, groupname, &group_sid, &group_dn);
     1030        if (!NT_STATUS_IS_OK(status)) {
     1031                return status;
     1032        }
     1033
     1034        a_state = talloc(mem_ctx, struct samr_account_state);
    10441035        if (!a_state) {
    10451036                return NT_STATUS_NO_MEMORY;
     
    10481039        a_state->access_mask = r->in.access_mask;
    10491040        a_state->domain_state = talloc_reference(a_state, d_state);
    1050         a_state->account_dn = talloc_steal(a_state, msg->dn);
    1051 
    1052         /* retrieve the sid for the group just created */
    1053         sid = samdb_search_dom_sid(d_state->sam_ctx, a_state,
    1054                                    msg->dn, "objectSid", NULL);
    1055         if (sid == NULL) {
    1056                 return NT_STATUS_UNSUCCESSFUL;
    1057         }
    1058 
    1059         a_state->account_name = talloc_strdup(a_state, groupname);
    1060         if (!a_state->account_name) {
    1061                 return NT_STATUS_NO_MEMORY;
    1062         }
     1041        a_state->account_dn = talloc_steal(a_state, group_dn);
     1042
     1043        a_state->account_name = talloc_steal(a_state, groupname);
    10631044
    10641045        /* create the policy handle */
     
    10711052
    10721053        *r->out.group_handle = g_handle->wire_handle;
    1073         *r->out.rid = sid->sub_auths[sid->num_auths-1];
     1054        *r->out.rid = group_sid->sub_auths[group_sid->num_auths-1];
    10741055
    10751056        return NT_STATUS_OK;
     
    10851066}
    10861067
    1087 /* 
    1088   samr_EnumDomainGroups 
     1068/*
     1069  samr_EnumDomainGroups
    10891070*/
    10901071static NTSTATUS dcesrv_samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    10941075        struct samr_domain_state *d_state;
    10951076        struct ldb_message **res;
    1096         int ldb_cnt, count, i, first;
     1077        int i, ldb_cnt;
     1078        uint32_t first, count;
    10971079        struct samr_SamEntry *entries;
    1098         const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
     1080        const char * const attrs[] = { "objectSid", "sAMAccountName", NULL };
    10991081        struct samr_SamArray *sam;
    11001082
     
    11121094                                      d_state->domain_dn, &res, attrs,
    11131095                                      d_state->domain_sid,
    1114                                       "(&(grouptype=%d)(objectclass=group))",
     1096                                      "(&(|(groupType=%d)(groupType=%d))(objectClass=group))",
     1097                                      GTYPE_SECURITY_UNIVERSAL_GROUP,
    11151098                                      GTYPE_SECURITY_GLOBAL_GROUP);
    1116         if (ldb_cnt == -1) {
     1099        if (ldb_cnt < 0) {
    11171100                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    11181101        }
     
    11311114                group_sid = samdb_result_dom_sid(mem_ctx, res[i],
    11321115                                                 "objectSid");
    1133                 if (group_sid == NULL)
    1134                         continue;
     1116                if (group_sid == NULL) {
     1117                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1118                }
    11351119
    11361120                entries[count].idx =
    11371121                        group_sid->sub_auths[group_sid->num_auths-1];
    11381122                entries[count].name.string =
    1139                         samdb_result_string(res[i], "sAMAccountName", "");
     1123                        ldb_msg_find_attr_as_string(res[i], "sAMAccountName", "");
    11401124                count += 1;
    11411125        }
    11421126
    11431127        /* sort the results by rid */
    1144         qsort(entries, count, sizeof(struct samr_SamEntry),
    1145               (comparison_fn_t)compare_SamEntry);
     1128        TYPESAFE_QSORT(entries, count, compare_SamEntry);
    11461129
    11471130        /* find the first entry to return */
     
    11501133             first++) ;
    11511134
    1152         /* return the rest, limit by max_size. Note that we 
     1135        /* return the rest, limit by max_size. Note that we
    11531136           use the w2k3 element size value of 54 */
    11541137        *r->out.num_entries = count - first;
     
    11661149        *r->out.sam = sam;
    11671150
     1151        if (first == count) {
     1152                return NT_STATUS_OK;
     1153        }
     1154
    11681155        if (*r->out.num_entries < count - first) {
    11691156                *r->out.resume_handle = entries[first+*r->out.num_entries-1].idx;
     
    11751162
    11761163
    1177 /* 
    1178   samr_CreateUser2 
     1164/*
     1165  samr_CreateUser2
    11791166
    11801167  This call uses transactions to ensure we don't get a new conflicting
     
    11851172                                 struct samr_CreateUser2 *r)
    11861173{
     1174        NTSTATUS status;
    11871175        struct samr_domain_state *d_state;
    11881176        struct samr_account_state *a_state;
    11891177        struct dcesrv_handle *h;
    1190         const char *name;
    1191         struct ldb_message *msg;
     1178        struct ldb_dn *dn;
    11921179        struct dom_sid *sid;
     1180        struct dcesrv_handle *u_handle;
    11931181        const char *account_name;
    1194         struct dcesrv_handle *u_handle;
    1195         int ret;
    1196         const char *container, *obj_class=NULL;
    1197         char *cn_name;
    1198         int cn_name_len;
    1199 
    1200         const char *attrs[] = {
    1201                 "objectSid",
    1202                 "userAccountControl",
    1203                 NULL
    1204         };
    1205 
    1206         uint32_t user_account_control;
    1207 
    1208         struct ldb_message **msgs;
    12091182
    12101183        ZERO_STRUCTP(r->out.user_handle);
     
    12291202        }
    12301203
    1231         /*
    1232          * Start a transaction, so we can query and do a subsequent atomic
    1233          * modify
    1234          */
    1235 
    1236         ret = ldb_transaction_start(d_state->sam_ctx);
    1237         if (ret != 0) {
    1238                 DEBUG(0,("Failed to start a transaction for user creation: %s\n",
    1239                          ldb_errstring(d_state->sam_ctx)));
    1240                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1241         }
    1242 
    1243         /* check if the user already exists */
    1244         name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
    1245                                    "sAMAccountName",
    1246                                    "(&(sAMAccountName=%s)(objectclass=user))",
    1247                                    ldb_binary_encode_string(mem_ctx, account_name));
    1248         if (name != NULL) {
    1249                 ldb_transaction_cancel(d_state->sam_ctx);
    1250                 return NT_STATUS_USER_EXISTS;
    1251         }
    1252 
    1253         msg = ldb_msg_new(mem_ctx);
    1254         if (msg == NULL) {
    1255                 ldb_transaction_cancel(d_state->sam_ctx);
    1256                 return NT_STATUS_NO_MEMORY;
    1257         }
    1258 
    1259         cn_name   = talloc_strdup(mem_ctx, account_name);
    1260         if (!cn_name) {
    1261                 ldb_transaction_cancel(d_state->sam_ctx);
    1262                 return NT_STATUS_NO_MEMORY;
    1263         }
    1264 
    1265         cn_name_len = strlen(cn_name);
    1266 
    1267         /* This must be one of these values *only* */
    1268         if (r->in.acct_flags == ACB_NORMAL) {
    1269                 container = "CN=Users";
    1270                 obj_class = "user";
    1271 
    1272         } else if (r->in.acct_flags == ACB_WSTRUST) {
    1273                 if (cn_name[cn_name_len - 1] != '$') {
    1274                         ldb_transaction_cancel(d_state->sam_ctx);
    1275                         return NT_STATUS_FOOBAR;
    1276                 }
    1277                 cn_name[cn_name_len - 1] = '\0';
    1278                 container = "CN=Computers";
    1279                 obj_class = "computer";
    1280                 samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg,
    1281                         "primaryGroupID", DOMAIN_RID_DOMAIN_MEMBERS);
    1282 
    1283         } else if (r->in.acct_flags == ACB_SVRTRUST) {
    1284                 if (cn_name[cn_name_len - 1] != '$') {
    1285                         ldb_transaction_cancel(d_state->sam_ctx);
    1286                         return NT_STATUS_FOOBAR;               
    1287                 }
    1288                 cn_name[cn_name_len - 1] = '\0';
    1289                 container = "OU=Domain Controllers";
    1290                 obj_class = "computer";
    1291                 samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg,
    1292                         "primaryGroupID", DOMAIN_RID_DCS);
    1293         } else {
    1294                 ldb_transaction_cancel(d_state->sam_ctx);
    1295                 return NT_STATUS_INVALID_PARAMETER;
    1296         }
    1297 
    1298         /* add core elements to the ldb_message for the user */
    1299         msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
    1300         if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s,%s", cn_name, container)) {
    1301                 ldb_transaction_cancel(d_state->sam_ctx);
    1302                 return NT_STATUS_FOOBAR;
    1303         }
    1304 
    1305         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName",
    1306                 account_name);
    1307         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass",
    1308                 obj_class);
    1309 
    1310         /* create the user */
    1311         ret = ldb_add(d_state->sam_ctx, msg);
    1312         switch (ret) {
    1313         case LDB_SUCCESS:
    1314                 break;
    1315         case LDB_ERR_ENTRY_ALREADY_EXISTS:
    1316                 ldb_transaction_cancel(d_state->sam_ctx);
    1317                 DEBUG(0,("Failed to create user record %s: %s\n",
    1318                          ldb_dn_get_linearized(msg->dn),
    1319                          ldb_errstring(d_state->sam_ctx)));
    1320                 return NT_STATUS_USER_EXISTS;
    1321         case LDB_ERR_UNWILLING_TO_PERFORM:
    1322         case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
    1323                 ldb_transaction_cancel(d_state->sam_ctx);
    1324                 DEBUG(0,("Failed to create user record %s: %s\n",
    1325                          ldb_dn_get_linearized(msg->dn),
    1326                          ldb_errstring(d_state->sam_ctx)));
    1327                 return NT_STATUS_ACCESS_DENIED;
    1328         default:
    1329                 ldb_transaction_cancel(d_state->sam_ctx);
    1330                 DEBUG(0,("Failed to create user record %s: %s\n",
    1331                          ldb_dn_get_linearized(msg->dn),
    1332                          ldb_errstring(d_state->sam_ctx)));
    1333                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1334         }
    1335 
    1336         a_state = talloc(d_state, struct samr_account_state);
     1204        status = dsdb_add_user(d_state->sam_ctx, mem_ctx, account_name, r->in.acct_flags, &sid, &dn);
     1205        if (!NT_STATUS_IS_OK(status)) {
     1206                return status;
     1207        }
     1208        a_state = talloc(mem_ctx, struct samr_account_state);
    13371209        if (!a_state) {
    13381210                ldb_transaction_cancel(d_state->sam_ctx);
     
    13421214        a_state->access_mask = r->in.access_mask;
    13431215        a_state->domain_state = talloc_reference(a_state, d_state);
    1344         a_state->account_dn = talloc_steal(a_state, msg->dn);
    1345 
    1346         /* retrieve the sid and account control bits for the user just created */
    1347         ret = gendb_search_dn(d_state->sam_ctx, a_state,
    1348                               msg->dn, &msgs, attrs);
    1349 
    1350         if (ret != 1) {
    1351                 ldb_transaction_cancel(d_state->sam_ctx);
    1352                 DEBUG(0,("Apparently we failed to create an account record, as %s now doesn't exist\n",
    1353                          ldb_dn_get_linearized(msg->dn)));
    1354                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1355         }
    1356         sid = samdb_result_dom_sid(mem_ctx, msgs[0], "objectSid");
    1357         if (sid == NULL) {
    1358                 ldb_transaction_cancel(d_state->sam_ctx);
    1359                 DEBUG(0,("Apparently we failed to get the objectSid of the just created account record %s\n",
    1360                          ldb_dn_get_linearized(msg->dn)));
    1361                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1362         }
    1363 
    1364         /* Change the account control to be the correct account type.
    1365          * The default is for a workstation account */
    1366         user_account_control = samdb_result_uint(msgs[0], "userAccountControl", 0);
    1367         user_account_control = (user_account_control &
    1368                                 ~(UF_NORMAL_ACCOUNT |
    1369                                   UF_INTERDOMAIN_TRUST_ACCOUNT |
    1370                                   UF_WORKSTATION_TRUST_ACCOUNT |
    1371                                   UF_SERVER_TRUST_ACCOUNT));
    1372         user_account_control |= ds_acb2uf(r->in.acct_flags);
    1373 
    1374         talloc_free(msg);
    1375         msg = ldb_msg_new(mem_ctx);
    1376         if (msg == NULL) {
    1377                 ldb_transaction_cancel(d_state->sam_ctx);
    1378                 return NT_STATUS_NO_MEMORY;
    1379         }
    1380 
    1381         msg->dn = ldb_dn_copy(msg, a_state->account_dn);
    1382 
    1383         if (samdb_msg_add_uint(a_state->sam_ctx, mem_ctx, msg,
    1384                                "userAccountControl",
    1385                                user_account_control) != 0) {
    1386                 ldb_transaction_cancel(d_state->sam_ctx);
    1387                 return NT_STATUS_NO_MEMORY;
    1388         }
    1389 
    1390         /* modify the samdb record */
    1391         ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg);
    1392         if (ret != 0) {
    1393                 DEBUG(0,("Failed to modify account record %s to set userAccountControl: %s\n",
    1394                          ldb_dn_get_linearized(msg->dn),
    1395                          ldb_errstring(d_state->sam_ctx)));
    1396                 ldb_transaction_cancel(d_state->sam_ctx);
    1397 
    1398                 /* we really need samdb.c to return NTSTATUS */
    1399                 return NT_STATUS_UNSUCCESSFUL;
    1400         }
    1401 
    1402         ret = ldb_transaction_commit(d_state->sam_ctx);
    1403         if (ret != 0) {
    1404                 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
    1405                          ldb_dn_get_linearized(msg->dn),
    1406                          ldb_errstring(d_state->sam_ctx)));
    1407                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1408         }
     1216        a_state->account_dn = talloc_steal(a_state, dn);
    14091217
    14101218        a_state->account_name = talloc_steal(a_state, account_name);
     
    14301238
    14311239
    1432 /* 
    1433   samr_CreateUser 
     1240/*
     1241  samr_CreateUser
    14341242*/
    14351243static NTSTATUS dcesrv_samr_CreateUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    14521260}
    14531261
    1454 /* 
    1455   samr_EnumDomainUsers 
     1262/*
     1263  samr_EnumDomainUsers
    14561264*/
    14571265static NTSTATUS dcesrv_samr_EnumDomainUsers(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    14601268        struct dcesrv_handle *h;
    14611269        struct samr_domain_state *d_state;
    1462         struct ldb_result *res;
    1463         int ret, num_filtered_entries, i, first;
     1270        struct ldb_message **res;
     1271        int i, ldb_cnt;
     1272        uint32_t first, count;
    14641273        struct samr_SamEntry *entries;
    14651274        const char * const attrs[] = { "objectSid", "sAMAccountName",
     
    14741283
    14751284        d_state = h->data;
    1476        
    1477         /* don't have to worry about users in the builtin domain, as there are none */
    1478         ret = ldb_search(d_state->sam_ctx, mem_ctx, &res, d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs, "objectClass=user");
    1479 
    1480         if (ret != LDB_SUCCESS) {
    1481                 DEBUG(3, ("Failed to search for Domain Users in %s: %s\n",
    1482                           ldb_dn_get_linearized(d_state->domain_dn), ldb_errstring(d_state->sam_ctx)));
     1285
     1286        /* search for all domain users in this domain. This could possibly be
     1287           cached and resumed on resume_key */
     1288        ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
     1289                                      d_state->domain_dn,
     1290                                      &res, attrs,
     1291                                      d_state->domain_sid,
     1292                                      "(objectClass=user)");
     1293        if (ldb_cnt < 0) {
    14831294                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    14841295        }
    14851296
    14861297        /* convert to SamEntry format */
    1487         entries = talloc_array(mem_ctx, struct samr_SamEntry, res->count);
     1298        entries = talloc_array(mem_ctx, struct samr_SamEntry, ldb_cnt);
    14881299        if (!entries) {
    14891300                return NT_STATUS_NO_MEMORY;
    14901301        }
    1491         num_filtered_entries = 0;
    1492         for (i=0;i<res->count;i++) {
     1302
     1303        count = 0;
     1304
     1305        for (i=0;i<ldb_cnt;i++) {
    14931306                /* Check if a mask has been requested */
    14941307                if (r->in.acct_flags
    1495                     && ((samdb_result_acct_flags(d_state->sam_ctx, mem_ctx, res->msgs[i],
    1496                                                  d_state->domain_dn) & r->in.acct_flags) == 0)) {
     1308                    && ((samdb_result_acct_flags(d_state->sam_ctx, mem_ctx,
     1309                                                 res[i], d_state->domain_dn) & r->in.acct_flags) == 0)) {
    14971310                        continue;
    14981311                }
    1499                 entries[num_filtered_entries].idx = samdb_result_rid_from_sid(mem_ctx, res->msgs[i], "objectSid", 0);
    1500                 entries[num_filtered_entries].name.string = samdb_result_string(res->msgs[i], "sAMAccountName", "");
    1501                 num_filtered_entries++;
     1312                entries[count].idx = samdb_result_rid_from_sid(mem_ctx, res[i],
     1313                                                               "objectSid", 0);
     1314                entries[count].name.string = ldb_msg_find_attr_as_string(res[i],
     1315                                                                 "sAMAccountName", "");
     1316                count += 1;
    15021317        }
    15031318
    15041319        /* sort the results by rid */
    1505         qsort(entries, num_filtered_entries, sizeof(struct samr_SamEntry),
    1506               (comparison_fn_t)compare_SamEntry);
     1320        TYPESAFE_QSORT(entries, count, compare_SamEntry);
    15071321
    15081322        /* find the first entry to return */
    15091323        for (first=0;
    1510              first<num_filtered_entries && entries[first].idx <= *r->in.resume_handle;
     1324             first<count && entries[first].idx <= *r->in.resume_handle;
    15111325             first++) ;
    15121326
    1513         /* return the rest, limit by max_size. Note that we 
     1327        /* return the rest, limit by max_size. Note that we
    15141328           use the w2k3 element size value of 54 */
    1515         *r->out.num_entries = num_filtered_entries - first;
     1329        *r->out.num_entries = count - first;
    15161330        *r->out.num_entries = MIN(*r->out.num_entries,
    15171331                                 1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
     
    15271341        *r->out.sam = sam;
    15281342
    1529         if (first == num_filtered_entries) {
     1343        if (first == count) {
    15301344                return NT_STATUS_OK;
    15311345        }
    15321346
    1533         if (*r->out.num_entries < num_filtered_entries - first) {
     1347        if (*r->out.num_entries < count - first) {
    15341348                *r->out.resume_handle = entries[first+*r->out.num_entries-1].idx;
    15351349                return STATUS_MORE_ENTRIES;
     
    15401354
    15411355
    1542 /* 
    1543   samr_CreateDomAlias 
     1356/*
     1357  samr_CreateDomAlias
    15441358*/
    15451359static NTSTATUS dcesrv_samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    15491363        struct samr_account_state *a_state;
    15501364        struct dcesrv_handle *h;
    1551         const char *alias_name, *name;
    1552         struct ldb_message *msg;
     1365        const char *alias_name;
    15531366        struct dom_sid *sid;
    15541367        struct dcesrv_handle *a_handle;
    1555         int ret;
     1368        struct ldb_dn *dn;
     1369        NTSTATUS status;
    15561370
    15571371        ZERO_STRUCTP(r->out.alias_handle);
     
    15731387        }
    15741388
    1575         /* Check if alias already exists */
    1576         name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
    1577                                    "sAMAccountName",
    1578                                    "(sAMAccountName=%s)(objectclass=group))",
    1579                                    ldb_binary_encode_string(mem_ctx, alias_name));
    1580 
    1581         if (name != NULL) {
    1582                 return NT_STATUS_ALIAS_EXISTS;
    1583         }
    1584 
    1585         msg = ldb_msg_new(mem_ctx);
    1586         if (msg == NULL) {
    1587                 return NT_STATUS_NO_MEMORY;
    1588         }
    1589 
    1590         /* add core elements to the ldb_message for the alias */
    1591         msg->dn = ldb_dn_copy(mem_ctx, d_state->domain_dn);
    1592         ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", alias_name);
    1593         if (!msg->dn) {
    1594                 return NT_STATUS_NO_MEMORY;
    1595         }
    1596 
    1597         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", alias_name);
    1598         samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");
    1599         samdb_msg_add_int(d_state->sam_ctx, mem_ctx, msg, "groupType", GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
    1600 
    1601         /* create the alias */
    1602         ret = ldb_add(d_state->sam_ctx, msg);
    1603         switch (ret) {
    1604         case LDB_SUCCESS:
    1605                 break;
    1606         case LDB_ERR_ENTRY_ALREADY_EXISTS:
    1607                 return NT_STATUS_ALIAS_EXISTS;
    1608         case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
    1609                 return NT_STATUS_ACCESS_DENIED;
    1610         default:
    1611                 DEBUG(0,("Failed to create alias record %s: %s\n",
    1612                          ldb_dn_get_linearized(msg->dn),
    1613                          ldb_errstring(d_state->sam_ctx)));
    1614                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1615         }
    1616 
    1617         a_state = talloc(d_state, struct samr_account_state);
     1389        status = dsdb_add_domain_alias(d_state->sam_ctx, mem_ctx, alias_name, &sid, &dn);
     1390        if (!NT_STATUS_IS_OK(status)) {
     1391                return status;
     1392        }
     1393
     1394        a_state = talloc(mem_ctx, struct samr_account_state);
    16181395        if (!a_state) {
    16191396                return NT_STATUS_NO_MEMORY;
     
    16231400        a_state->access_mask = r->in.access_mask;
    16241401        a_state->domain_state = talloc_reference(a_state, d_state);
    1625         a_state->account_dn = talloc_steal(a_state, msg->dn);
    1626 
    1627         /* retrieve the sid for the alias just created */
    1628         sid = samdb_search_dom_sid(d_state->sam_ctx, a_state,
    1629                                    msg->dn, "objectSid", NULL);
    1630 
    1631         a_state->account_name = talloc_strdup(a_state, alias_name);
    1632         if (!a_state->account_name) {
    1633                 return NT_STATUS_NO_MEMORY;
    1634         }
     1402        a_state->account_dn = talloc_steal(a_state, dn);
     1403
     1404        a_state->account_name = talloc_steal(a_state, alias_name);
    16351405
    16361406        /* create the policy handle */
     
    16491419
    16501420
    1651 /* 
    1652   samr_EnumDomainAliases 
     1421/*
     1422  samr_EnumDomainAliases
    16531423*/
    16541424static NTSTATUS dcesrv_samr_EnumDomainAliases(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    16581428        struct samr_domain_state *d_state;
    16591429        struct ldb_message **res;
    1660         int ldb_cnt, count, i, first;
     1430        int i, ldb_cnt;
     1431        uint32_t first, count;
    16611432        struct samr_SamEntry *entries;
    1662         const char * const attrs[3] = { "objectSid", "sAMAccountName", NULL };
     1433        const char * const attrs[] = { "objectSid", "sAMAccountName", NULL };
    16631434        struct samr_SamArray *sam;
    16641435
     
    16711442        d_state = h->data;
    16721443
    1673         /* search for all domain groups in this domain. This could possibly be
     1444        /* search for all domain aliases in this domain. This could possibly be
    16741445           cached and resumed based on resume_key */
    1675         ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
    1676                                       d_state->domain_dn,
    1677                                       &res, attrs,
     1446        ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx, NULL,
     1447                                      &res, attrs,
    16781448                                      d_state->domain_sid,
    16791449                                      "(&(|(grouptype=%d)(grouptype=%d)))"
     
    16811451                                      GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
    16821452                                      GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
    1683         if (ldb_cnt == -1) {
     1453        if (ldb_cnt < 0) {
    16841454                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1685         }
    1686         if (ldb_cnt == 0) {
    1687                 return NT_STATUS_OK;
    16881455        }
    16891456
     
    17021469                                                 "objectSid");
    17031470
    1704                 if (alias_sid == NULL)
    1705                         continue;
     1471                if (alias_sid == NULL) {
     1472                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1473                }
    17061474
    17071475                entries[count].idx =
    17081476                        alias_sid->sub_auths[alias_sid->num_auths-1];
    17091477                entries[count].name.string =
    1710                         samdb_result_string(res[i], "sAMAccountName", "");
     1478                        ldb_msg_find_attr_as_string(res[i], "sAMAccountName", "");
    17111479                count += 1;
    17121480        }
    17131481
    17141482        /* sort the results by rid */
    1715         qsort(entries, count, sizeof(struct samr_SamEntry),
    1716               (comparison_fn_t)compare_SamEntry);
     1483        TYPESAFE_QSORT(entries, count, compare_SamEntry);
    17171484
    17181485        /* find the first entry to return */
     
    17211488             first++) ;
    17221489
     1490        /* return the rest, limit by max_size. Note that we
     1491           use the w2k3 element size value of 54 */
     1492        *r->out.num_entries = count - first;
     1493        *r->out.num_entries = MIN(*r->out.num_entries,
     1494                                  1+(r->in.max_size/SAMR_ENUM_USERS_MULTIPLIER));
     1495
     1496        sam = talloc(mem_ctx, struct samr_SamArray);
     1497        if (!sam) {
     1498                return NT_STATUS_NO_MEMORY;
     1499        }
     1500
     1501        sam->entries = entries+first;
     1502        sam->count = *r->out.num_entries;
     1503
     1504        *r->out.sam = sam;
     1505
    17231506        if (first == count) {
    17241507                return NT_STATUS_OK;
    17251508        }
    1726 
    1727         *r->out.num_entries = count - first;
    1728         *r->out.num_entries = MIN(*r->out.num_entries, 1000);
    1729 
    1730         sam = talloc(mem_ctx, struct samr_SamArray);
    1731         if (!sam) {
    1732                 return NT_STATUS_NO_MEMORY;
    1733         }
    1734 
    1735         sam->entries = entries+first;
    1736         sam->count = *r->out.num_entries;
    1737 
    1738         *r->out.sam = sam;
    17391509
    17401510        if (*r->out.num_entries < count - first) {
     
    17481518
    17491519
    1750 /* 
    1751   samr_GetAliasMembership 
     1520/*
     1521  samr_GetAliasMembership
    17521522*/
    17531523static NTSTATUS dcesrv_samr_GetAliasMembership(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    17561526        struct dcesrv_handle *h;
    17571527        struct samr_domain_state *d_state;
     1528        const char *filter;
     1529        const char * const attrs[] = { "objectSid", NULL };
    17581530        struct ldb_message **res;
    1759         int i, count = 0;
     1531        uint32_t i;
     1532        int count = 0;
    17601533
    17611534        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
     
    17631536        d_state = h->data;
    17641537
    1765         if (r->in.sids->num_sids > 0) {
    1766                 const char *filter;
    1767                 const char * const attrs[2] = { "objectSid", NULL };
    1768 
    1769                 filter = talloc_asprintf(mem_ctx,
    1770                                          "(&(|(grouptype=%d)(grouptype=%d))"
    1771                                          "(objectclass=group)(|",
    1772                                          GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
    1773                                          GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
    1774                 if (filter == NULL)
     1538        filter = talloc_asprintf(mem_ctx,
     1539                                 "(&(|(grouptype=%d)(grouptype=%d))"
     1540                                 "(objectclass=group)(|",
     1541                                 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
     1542                                 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
     1543        if (filter == NULL) {
     1544                return NT_STATUS_NO_MEMORY;
     1545        }
     1546
     1547        for (i=0; i<r->in.sids->num_sids; i++) {
     1548                const char *memberdn;
     1549
     1550                memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
     1551                                               "distinguishedName",
     1552                                               "(objectSid=%s)",
     1553                                               ldap_encode_ndr_dom_sid(mem_ctx,
     1554                                                                       r->in.sids->sids[i].sid));
     1555                if (memberdn == NULL) {
     1556                        continue;
     1557                }
     1558
     1559                filter = talloc_asprintf(mem_ctx, "%s(member=%s)", filter,
     1560                                         memberdn);
     1561                if (filter == NULL) {
    17751562                        return NT_STATUS_NO_MEMORY;
    1776 
    1777                 for (i=0; i<r->in.sids->num_sids; i++) {
    1778                         const char *memberdn;
    1779 
    1780                         memberdn =
    1781                                 samdb_search_string(d_state->sam_ctx,
    1782                                                     mem_ctx, NULL,
    1783                                                     "distinguishedName",
    1784                                                     "(objectSid=%s)",
    1785                                                     ldap_encode_ndr_dom_sid(mem_ctx,
    1786                                                                             r->in.sids->sids[i].sid));
    1787 
    1788                         if (memberdn == NULL)
    1789                                 continue;
    1790 
    1791                         filter = talloc_asprintf(mem_ctx, "%s(member=%s)",
    1792                                                  filter, memberdn);
    1793                         if (filter == NULL)
    1794                                 return NT_STATUS_NO_MEMORY;
    17951563                }
    1796 
    1797                 count = samdb_search_domain(d_state->sam_ctx, mem_ctx,
    1798                                             d_state->domain_dn, &res, attrs,
    1799                                             d_state->domain_sid, "%s))", filter);
    1800                 if (count < 0)
     1564        }
     1565
     1566        /* Find out if we had at least one valid member SID passed - otherwise
     1567         * just skip the search. */
     1568        if (strstr(filter, "member") != NULL) {
     1569                count = samdb_search_domain(d_state->sam_ctx, mem_ctx, NULL,
     1570                                            &res, attrs, d_state->domain_sid,
     1571                                            "%s))", filter);
     1572                if (count < 0) {
    18011573                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1574                }
    18021575        }
    18031576
     
    18111584
    18121585                alias_sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
    1813 
    18141586                if (alias_sid == NULL) {
    1815                         DEBUG(0, ("Could not find objectSid\n"));
    1816                         continue;
     1587                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
    18171588                }
    18181589
     
    18261597
    18271598
    1828 /* 
    1829   samr_LookupNames 
     1599/*
     1600  samr_LookupNames
    18301601*/
    18311602static NTSTATUS dcesrv_samr_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    18341605        struct dcesrv_handle *h;
    18351606        struct samr_domain_state *d_state;
    1836         int i, num_mapped;
     1607        uint32_t i, num_mapped;
    18371608        NTSTATUS status = NT_STATUS_OK;
    18381609        const char * const attrs[] = { "sAMAccountType", "objectSid", NULL };
     
    18681639                r->out.types->ids[i] = SID_NAME_UNKNOWN;
    18691640
    1870                 count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs, 
    1871                                      "sAMAccountName=%s", 
     1641                count = gendb_search(d_state->sam_ctx, mem_ctx, d_state->domain_dn, &res, attrs,
     1642                                     "sAMAccountName=%s",
    18721643                                     ldb_binary_encode_string(mem_ctx, r->in.names[i].string));
    18731644                if (count != 1) {
     
    18811652                        continue;
    18821653                }
    1883                
    1884                 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
     1654
     1655                atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0);
    18851656                if (atype == 0) {
    18861657                        status = STATUS_SOME_UNMAPPED;
     
    18891660
    18901661                rtype = ds_atype_map(atype);
    1891                
     1662
    18921663                if (rtype == SID_NAME_UNKNOWN) {
    18931664                        status = STATUS_SOME_UNMAPPED;
     
    18991670                num_mapped++;
    19001671        }
    1901        
     1672
    19021673        if (num_mapped == 0) {
    19031674                return NT_STATUS_NONE_MAPPED;
     
    19071678
    19081679
    1909 /* 
    1910   samr_LookupRids 
     1680/*
     1681  samr_LookupRids
    19111682*/
    19121683static NTSTATUS dcesrv_samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    19131684                       struct samr_LookupRids *r)
    19141685{
     1686        NTSTATUS status;
    19151687        struct dcesrv_handle *h;
    19161688        struct samr_domain_state *d_state;
    1917         int i, total;
    1918         NTSTATUS status = NT_STATUS_OK;
    1919         struct lsa_String *names;
    1920         uint32_t *ids;
     1689        const char **names;
     1690        struct lsa_String *lsa_names;
     1691        enum lsa_SidType *ids;
    19211692
    19221693        ZERO_STRUCTP(r->out.names);
     
    19301701                return NT_STATUS_OK;
    19311702
    1932         names = talloc_array(mem_ctx, struct lsa_String, r->in.num_rids);
    1933         ids = talloc_array(mem_ctx, uint32_t, r->in.num_rids);
    1934 
    1935         if ((names == NULL) || (ids == NULL))
    1936                 return NT_STATUS_NO_MEMORY;
    1937 
    1938         total = 0;
    1939 
    1940         for (i=0; i<r->in.num_rids; i++) {
    1941                 struct ldb_message **res;
    1942                 int count;
    1943                 const char * const attrs[] = {  "sAMAccountType",
    1944                                                 "sAMAccountName", NULL };
    1945                 uint32_t atype;
    1946                 struct dom_sid *sid;
    1947 
    1948                 ids[i] = SID_NAME_UNKNOWN;
    1949 
    1950                 sid = dom_sid_add_rid(mem_ctx, d_state->domain_sid,
    1951                         r->in.rids[i]);
    1952                 if (sid == NULL) {
    1953                         names[i].string = NULL;
    1954                         status = STATUS_SOME_UNMAPPED;
    1955                         continue;
     1703        lsa_names = talloc_zero_array(mem_ctx, struct lsa_String, r->in.num_rids);
     1704        names = talloc_zero_array(mem_ctx, const char *, r->in.num_rids);
     1705        ids = talloc_zero_array(mem_ctx, enum lsa_SidType, r->in.num_rids);
     1706
     1707        if ((lsa_names == NULL) || (names == NULL) || (ids == NULL))
     1708                return NT_STATUS_NO_MEMORY;
     1709
     1710        r->out.names->names = lsa_names;
     1711        r->out.names->count = r->in.num_rids;
     1712
     1713        r->out.types->ids = (uint32_t *) ids;
     1714        r->out.types->count = r->in.num_rids;
     1715
     1716        status = dsdb_lookup_rids(d_state->sam_ctx, mem_ctx, d_state->domain_sid,
     1717                                  r->in.num_rids, r->in.rids, names, ids);
     1718        if (NT_STATUS_IS_OK(status) || NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED) || NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
     1719                uint32_t i;
     1720                for (i = 0; i < r->in.num_rids; i++) {
     1721                        lsa_names[i].string = names[i];
    19561722                }
    1957                
    1958                 count = gendb_search(d_state->sam_ctx, mem_ctx,
    1959                                      d_state->domain_dn, &res, attrs,
    1960                                      "(objectSid=%s)",
    1961                                      ldap_encode_ndr_dom_sid(mem_ctx, sid));
    1962                 if (count != 1) {
    1963                         names[i].string = NULL;
    1964                         status = STATUS_SOME_UNMAPPED;
    1965                         continue;
    1966                 }
    1967 
    1968                 names[i].string = samdb_result_string(res[0], "sAMAccountName",
    1969                                                       NULL);
    1970 
    1971                 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
    1972                 if (atype == 0) {
    1973                         status = STATUS_SOME_UNMAPPED;
    1974                         continue;
    1975                 }
    1976 
    1977                 ids[i] = ds_atype_map(atype);
    1978                
    1979                 if (ids[i] == SID_NAME_UNKNOWN) {
    1980                         status = STATUS_SOME_UNMAPPED;
    1981                         continue;
    1982                 }
    1983         }
    1984 
    1985         r->out.names->names = names;
    1986         r->out.names->count = r->in.num_rids;
    1987 
    1988         r->out.types->ids = ids;
    1989         r->out.types->count = r->in.num_rids;
    1990 
     1723        }
    19911724        return status;
    19921725}
    19931726
    19941727
    1995 /* 
    1996   samr_OpenGroup 
     1728/*
     1729  samr_OpenGroup
    19971730*/
    19981731static NTSTATUS dcesrv_samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    20241757        ret = gendb_search(d_state->sam_ctx,
    20251758                           mem_ctx, d_state->domain_dn, &msgs, attrs,
    2026                            "(&(objectSid=%s)(objectclass=group)"
    2027                            "(grouptype=%d))",
     1759                           "(&(objectSid=%s)(objectClass=group)"
     1760                           "(|(groupType=%d)(groupType=%d)))",
    20281761                           ldap_encode_ndr_dom_sid(mem_ctx, sid),
     1762                           GTYPE_SECURITY_UNIVERSAL_GROUP,
    20291763                           GTYPE_SECURITY_GLOBAL_GROUP);
    20301764        if (ret == 0) {
     
    20321766        }
    20331767        if (ret != 1) {
    2034                 DEBUG(0,("Found %d records matching sid %s\n", 
     1768                DEBUG(0,("Found %d records matching sid %s\n",
    20351769                         ret, dom_sid_string(mem_ctx, sid)));
    20361770                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    20371771        }
    20381772
    2039         groupname = samdb_result_string(msgs[0], "sAMAccountName", NULL);
     1773        groupname = ldb_msg_find_attr_as_string(msgs[0], "sAMAccountName", NULL);
    20401774        if (groupname == NULL) {
    2041                 DEBUG(0,("sAMAccountName field missing for sid %s\n", 
     1775                DEBUG(0,("sAMAccountName field missing for sid %s\n",
    20421776                         dom_sid_string(mem_ctx, sid)));
    20431777                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    20441778        }
    20451779
    2046         a_state = talloc(d_state, struct samr_account_state);
     1780        a_state = talloc(mem_ctx, struct samr_account_state);
    20471781        if (!a_state) {
    20481782                return NT_STATUS_NO_MEMORY;
     
    20711805}
    20721806
    2073 /* 
    2074   samr_QueryGroupInfo 
     1807/*
     1808  samr_QueryGroupInfo
    20751809*/
    20761810static NTSTATUS dcesrv_samr_QueryGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    20791813        struct dcesrv_handle *h;
    20801814        struct samr_account_state *a_state;
    2081         struct ldb_message *msg;
    2082         struct ldb_result *res;
     1815        struct ldb_message *msg, **res;
    20831816        const char * const attrs[4] = { "sAMAccountName", "description",
    20841817                                        "numMembers", NULL };
     
    20911824
    20921825        a_state = h->data;
    2093        
    2094         ret = ldb_search(a_state->sam_ctx, mem_ctx, &res, a_state->account_dn,
    2095                 LDB_SCOPE_SUBTREE, attrs, "objectClass=*");
    2096        
    2097         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     1826
     1827        /* pull all the group attributes */
     1828        ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
     1829                              a_state->account_dn, &res, attrs);
     1830        if (ret == 0) {
    20981831                return NT_STATUS_NO_SUCH_GROUP;
    2099         } else if (ret != LDB_SUCCESS) {
    2100                 DEBUG(2, ("Error reading group info: %s\n", ldb_errstring(a_state->sam_ctx)));
     1832        }
     1833        if (ret != 1) {
    21011834                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    21021835        }
    2103 
    2104         if (res->count != 1) {
    2105                 DEBUG(2, ("Error finding group info, got %d entries\n", res->count));
    2106                
    2107                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2108         }
    2109         msg = res->msgs[0];
     1836        msg = res[0];
    21101837
    21111838        /* allocate the info structure */
     
    21491876
    21501877
    2151 /* 
    2152   samr_SetGroupInfo 
     1878/*
     1879  samr_SetGroupInfo
    21531880*/
    21541881static NTSTATUS dcesrv_samr_SetGroupInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    21691896        if (msg == NULL) {
    21701897                return NT_STATUS_NO_MEMORY;
    2171         }       
     1898        }
    21721899
    21731900        msg->dn = ldb_dn_copy(mem_ctx, g_state->account_dn);
     
    21941921        /* modify the samdb record */
    21951922        ret = ldb_modify(g_state->sam_ctx, msg);
    2196         if (ret != 0) {
     1923        if (ret != LDB_SUCCESS) {
    21971924                /* we really need samdb.c to return NTSTATUS */
    21981925                return NT_STATUS_UNSUCCESSFUL;
     
    22031930
    22041931
    2205 /* 
    2206   samr_AddGroupMember 
     1932/*
     1933  samr_AddGroupMember
    22071934*/
    22081935static NTSTATUS dcesrv_samr_AddGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    22251952
    22261953        membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
    2227         if (membersid == NULL)
    2228                 return NT_STATUS_NO_MEMORY;
    2229 
    2230         /* In native mode, AD can also nest domain groups. Not sure yet
    2231          * whether this is also available via RPC. */
     1954        if (membersid == NULL) {
     1955                return NT_STATUS_NO_MEMORY;
     1956        }
     1957
     1958        /* according to MS-SAMR 3.1.5.8.2 all type of accounts are accepted */
    22321959        ret = ldb_search(d_state->sam_ctx, mem_ctx, &res,
    2233                                 d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
    2234                                  "(&(objectSid=%s)(objectclass=user))",
    2235                                 ldap_encode_ndr_dom_sid(mem_ctx, membersid));
    2236 
    2237         if (ret != 0) {
     1960                        d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
     1961                         "(objectSid=%s)",
     1962                        ldap_encode_ndr_dom_sid(mem_ctx, membersid));
     1963
     1964        if (ret != LDB_SUCCESS) {
    22381965                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    22391966        }
     
    22421969                return NT_STATUS_NO_SUCH_USER;
    22431970        }
    2244                
     1971
    22451972        if (res->count > 1) {
    22461973                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     
    22591986        mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
    22601987
    2261         if (samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
    2262                                  memberdn) != 0)
     1988        ret = samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
     1989                                                                memberdn);
     1990        if (ret != LDB_SUCCESS) {
    22631991                return NT_STATUS_UNSUCCESSFUL;
     1992        }
    22641993
    22651994        ret = ldb_modify(a_state->sam_ctx, mod);
     
    22671996        case LDB_SUCCESS:
    22681997                return NT_STATUS_OK;
    2269         case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
     1998        case LDB_ERR_ENTRY_ALREADY_EXISTS:
    22701999                return NT_STATUS_MEMBER_IN_GROUP;
    22712000        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
     
    22742003                return NT_STATUS_UNSUCCESSFUL;
    22752004        }
    2276 
    2277 }
    2278 
    2279 
    2280 /*
    2281   samr_DeleteDomainGroup
     2005}
     2006
     2007
     2008/*
     2009  samr_DeleteDomainGroup
    22822010*/
    22832011static NTSTATUS dcesrv_samr_DeleteDomainGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    22952023
    22962024        ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
    2297         if (ret != 0) {
     2025        if (ret != LDB_SUCCESS) {
    22982026                return NT_STATUS_UNSUCCESSFUL;
    22992027        }
    23002028
     2029        talloc_free(h);
    23012030        ZERO_STRUCTP(r->out.group_handle);
    23022031
     
    23052034
    23062035
    2307 /* 
    2308   samr_DeleteGroupMember 
     2036/*
     2037  samr_DeleteGroupMember
    23092038*/
    23102039static NTSTATUS dcesrv_samr_DeleteGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    23272056
    23282057        membersid = dom_sid_add_rid(mem_ctx, d_state->domain_sid, r->in.rid);
    2329         if (membersid == NULL)
    2330                 return NT_STATUS_NO_MEMORY;
    2331 
    2332         /* In native mode, AD can also nest domain groups. Not sure yet
    2333          * whether this is also available via RPC. */
     2058        if (membersid == NULL) {
     2059                return NT_STATUS_NO_MEMORY;
     2060        }
     2061
     2062        /* according to MS-SAMR 3.1.5.8.2 all type of accounts are accepted */
    23342063        ret = ldb_search(d_state->sam_ctx, mem_ctx, &res,
    2335                                 d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
    2336                                  "(&(objectSid=%s)(objectclass=user))",
    2337                                 ldap_encode_ndr_dom_sid(mem_ctx, membersid));
    2338 
    2339         if (ret != 0) {
     2064                        d_state->domain_dn, LDB_SCOPE_SUBTREE, attrs,
     2065                         "(objectSid=%s)",
     2066                        ldap_encode_ndr_dom_sid(mem_ctx, membersid));
     2067
     2068        if (ret != LDB_SUCCESS) {
    23402069                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    23412070        }
     
    23442073                return NT_STATUS_NO_SUCH_USER;
    23452074        }
    2346                
     2075
    23472076        if (res->count > 1) {
    23482077                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     
    23612090        mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
    23622091
    2363         if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
    2364                                  memberdn) != 0) {
     2092        ret = samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
     2093                                                                memberdn);
     2094        if (ret != LDB_SUCCESS) {
    23652095                return NT_STATUS_NO_MEMORY;
    23662096        }
     
    23702100        case LDB_SUCCESS:
    23712101                return NT_STATUS_OK;
    2372         case LDB_ERR_NO_SUCH_ATTRIBUTE:
     2102        case LDB_ERR_UNWILLING_TO_PERFORM:
    23732103                return NT_STATUS_MEMBER_NOT_IN_GROUP;
    23742104        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
     
    23802110
    23812111
    2382 /* 
    2383   samr_QueryGroupMember 
     2112/*
     2113  samr_QueryGroupMember
    23842114*/
    23852115static NTSTATUS dcesrv_samr_QueryGroupMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    23882118        struct dcesrv_handle *h;
    23892119        struct samr_account_state *a_state;
    2390         struct ldb_message **res;
    2391         struct ldb_message_element *el;
    2392         struct samr_RidTypeArray *array;
    2393         const char * const attrs[2] = { "member", NULL };
    2394         int ret;
     2120        struct samr_domain_state *d_state;
     2121        struct samr_RidAttrArray *array;
     2122        unsigned int i, num_members;
     2123        struct dom_sid *members;
     2124        NTSTATUS status;
    23952125
    23962126        DCESRV_PULL_HANDLE(h, r->in.group_handle, SAMR_HANDLE_GROUP);
    23972127
    23982128        a_state = h->data;
    2399 
    2400         /* pull the member attribute */
    2401         ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
    2402                               a_state->account_dn, &res, attrs);
    2403 
    2404         if (ret != 1) {
    2405                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2406         }
    2407 
    2408         array = talloc(mem_ctx, struct samr_RidTypeArray);
    2409 
    2410         if (array == NULL)
    2411                 return NT_STATUS_NO_MEMORY;
    2412 
    2413         ZERO_STRUCTP(array);
    2414 
    2415         el = ldb_msg_find_element(res[0], "member");
    2416 
    2417         if (el != NULL) {
    2418                 int i;
    2419 
    2420                 array->count = el->num_values;
    2421 
    2422                 array->rids = talloc_array(mem_ctx, uint32_t,
    2423                                              el->num_values);
    2424                 if (array->rids == NULL)
    2425                         return NT_STATUS_NO_MEMORY;
    2426 
    2427                 array->types = talloc_array(mem_ctx, uint32_t,
    2428                                             el->num_values);
    2429                 if (array->types == NULL)
    2430                         return NT_STATUS_NO_MEMORY;
    2431 
    2432                 for (i=0; i<el->num_values; i++) {
    2433                         struct ldb_message **res2;
    2434                         const char * const attrs2[2] = { "objectSid", NULL };
    2435                         ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
    2436                                            ldb_dn_from_ldb_val(mem_ctx, a_state->sam_ctx, &el->values[i]),
    2437                                            &res2, attrs2);
    2438                         if (ret != 1)
    2439                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2440 
    2441                         array->rids[i] =
    2442                                 samdb_result_rid_from_sid(mem_ctx, res2[0],
    2443                                                           "objectSid", 0);
    2444 
    2445                         if (array->rids[i] == 0)
    2446                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2447 
    2448                         array->types[i] = 7; /* RID type of some kind, not sure what the value means. */
     2129        d_state = a_state->domain_state;
     2130
     2131        status = dsdb_enum_group_mem(d_state->sam_ctx, mem_ctx,
     2132                                     a_state->account_dn, &members,
     2133                                     &num_members);
     2134        if (!NT_STATUS_IS_OK(status)) {
     2135                return status;
     2136        }
     2137
     2138        array = talloc_zero(mem_ctx, struct samr_RidAttrArray);
     2139        if (array == NULL) {
     2140                return NT_STATUS_NO_MEMORY;
     2141        }
     2142
     2143        if (num_members == 0) {
     2144                *r->out.rids = array;
     2145
     2146                return NT_STATUS_OK;
     2147        }
     2148
     2149        array->rids = talloc_array(array, uint32_t, num_members);
     2150        if (array->rids == NULL) {
     2151                return NT_STATUS_NO_MEMORY;
     2152        }
     2153
     2154        array->attributes = talloc_array(array, uint32_t, num_members);
     2155        if (array->attributes == NULL) {
     2156                return NT_STATUS_NO_MEMORY;
     2157        }
     2158
     2159        array->count = 0;
     2160        for (i=0; i<num_members; i++) {
     2161                if (!dom_sid_in_domain(d_state->domain_sid, &members[i])) {
     2162                        continue;
    24492163                }
     2164
     2165                status = dom_sid_split_rid(NULL, &members[i], NULL,
     2166                                           &array->rids[array->count]);
     2167                if (!NT_STATUS_IS_OK(status)) {
     2168                        return status;
     2169                }
     2170
     2171                array->attributes[array->count] = SE_GROUP_MANDATORY |
     2172                                                  SE_GROUP_ENABLED_BY_DEFAULT |
     2173                                                  SE_GROUP_ENABLED;
     2174                array->count++;
    24502175        }
    24512176
     
    24562181
    24572182
    2458 /* 
    2459   samr_SetMemberAttributesOfGroup 
     2183/*
     2184  samr_SetMemberAttributesOfGroup
    24602185*/
    24612186static NTSTATUS dcesrv_samr_SetMemberAttributesOfGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    24662191
    24672192
    2468 /* 
    2469   samr_OpenAlias 
     2193/*
     2194  samr_OpenAlias
    24702195*/
    24712196static NTSTATUS dcesrv_samr_OpenAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    24942219
    24952220        /* search for the group record */
    2496         ret = gendb_search(d_state->sam_ctx,
    2497                            mem_ctx, d_state->domain_dn, &msgs, attrs,
     2221        ret = gendb_search(d_state->sam_ctx, mem_ctx, NULL, &msgs, attrs,
    24982222                           "(&(objectSid=%s)(objectclass=group)"
    24992223                           "(|(grouptype=%d)(grouptype=%d)))",
     
    25052229        }
    25062230        if (ret != 1) {
    2507                 DEBUG(0,("Found %d records matching sid %s\n", 
     2231                DEBUG(0,("Found %d records matching sid %s\n",
    25082232                         ret, dom_sid_string(mem_ctx, sid)));
    25092233                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    25102234        }
    25112235
    2512         alias_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);
     2236        alias_name = ldb_msg_find_attr_as_string(msgs[0], "sAMAccountName", NULL);
    25132237        if (alias_name == NULL) {
    2514                 DEBUG(0,("sAMAccountName field missing for sid %s\n", 
     2238                DEBUG(0,("sAMAccountName field missing for sid %s\n",
    25152239                         dom_sid_string(mem_ctx, sid)));
    25162240                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    25172241        }
    25182242
    2519         a_state = talloc(d_state, struct samr_account_state);
     2243        a_state = talloc(mem_ctx, struct samr_account_state);
    25202244        if (!a_state) {
    25212245                return NT_STATUS_NO_MEMORY;
     
    25452269
    25462270
    2547 /* 
    2548   samr_QueryAliasInfo 
     2271/*
     2272  samr_QueryAliasInfo
    25492273*/
    25502274static NTSTATUS dcesrv_samr_QueryAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    25672291        /* pull all the alias attributes */
    25682292        ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
    2569                               a_state->account_dn ,&res, attrs);
     2293                              a_state->account_dn, &res, attrs);
     2294        if (ret == 0) {
     2295                return NT_STATUS_NO_SUCH_ALIAS;
     2296        }
    25702297        if (ret != 1) {
    25712298                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     
    26022329
    26032330
    2604 /* 
    2605   samr_SetAliasInfo 
     2331/*
     2332  samr_SetAliasInfo
    26062333*/
    26072334static NTSTATUS dcesrv_samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    26442371        /* modify the samdb record */
    26452372        ret = ldb_modify(a_state->sam_ctx, msg);
    2646         if (ret != 0) {
     2373        if (ret != LDB_SUCCESS) {
    26472374                /* we really need samdb.c to return NTSTATUS */
    26482375                return NT_STATUS_UNSUCCESSFUL;
     
    26532380
    26542381
    2655 /* 
    2656   samr_DeleteDomAlias 
     2382/*
     2383  samr_DeleteDomAlias
    26572384*/
    26582385static NTSTATUS dcesrv_samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    26702397
    26712398        ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
    2672         if (ret != 0) {
     2399        if (ret != LDB_SUCCESS) {
    26732400                return NT_STATUS_UNSUCCESSFUL;
    26742401        }
    26752402
     2403        talloc_free(h);
    26762404        ZERO_STRUCTP(r->out.alias_handle);
    26772405
     
    26802408
    26812409
    2682 /* 
    2683   samr_AddAliasMember 
     2410/*
     2411  samr_AddAliasMember
    26842412*/
    26852413static NTSTATUS dcesrv_samr_AddAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    27022430
    27032431        ret = gendb_search(d_state->sam_ctx, mem_ctx, NULL,
    2704                            &msgs, attrs, "(objectsid=%s)", 
     2432                           &msgs, attrs, "(objectsid=%s)",
    27052433                           ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
    27062434
    27072435        if (ret == 1) {
    27082436                memberdn = msgs[0]->dn;
    2709         } else  if (ret > 1) {
    2710                 DEBUG(0,("Found %d records matching sid %s\n",
    2711                          ret, dom_sid_string(mem_ctx, r->in.sid)));
    2712                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    27132437        } else if (ret == 0) {
    27142438                status = samdb_create_foreign_security_principal(
     
    27182442                }
    27192443        } else {
    2720                 DEBUG(0, ("samdb_search returned %d: %s\n", ret, ldb_errstring(d_state->sam_ctx)));
     2444                DEBUG(0,("Found %d records matching sid %s\n",
     2445                         ret, dom_sid_string(mem_ctx, r->in.sid)));
     2446                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    27212447        }
    27222448
     
    27332459        mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
    27342460
    2735         if (samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
    2736                                  ldb_dn_alloc_linearized(mem_ctx, memberdn)) != 0)
     2461        ret = samdb_msg_add_addval(d_state->sam_ctx, mem_ctx, mod, "member",
     2462                                 ldb_dn_alloc_linearized(mem_ctx, memberdn));
     2463        if (ret != LDB_SUCCESS) {
    27372464                return NT_STATUS_UNSUCCESSFUL;
    2738 
    2739         if (ldb_modify(a_state->sam_ctx, mod) != 0)
     2465        }
     2466
     2467        ret = ldb_modify(a_state->sam_ctx, mod);
     2468        switch (ret) {
     2469        case LDB_SUCCESS:
     2470                return NT_STATUS_OK;
     2471        case LDB_ERR_ENTRY_ALREADY_EXISTS:
     2472                return NT_STATUS_MEMBER_IN_GROUP;
     2473        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
     2474                return NT_STATUS_ACCESS_DENIED;
     2475        default:
    27402476                return NT_STATUS_UNSUCCESSFUL;
    2741 
    2742         return NT_STATUS_OK;
    2743 }
    2744 
    2745 
    2746 /*
    2747   samr_DeleteAliasMember
     2477        }
     2478}
     2479
     2480
     2481/*
     2482  samr_DeleteAliasMember
    27482483*/
    27492484static NTSTATUS dcesrv_samr_DeleteAliasMember(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    27552490        struct ldb_message *mod;
    27562491        const char *memberdn;
     2492        int ret;
    27572493
    27582494        DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
     
    27622498
    27632499        memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
    2764                                        "distinguishedName", "(objectSid=%s)", 
     2500                                       "distinguishedName", "(objectSid=%s)",
    27652501                                       ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
    2766 
    2767         if (memberdn == NULL)
     2502        if (memberdn == NULL) {
    27682503                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     2504        }
    27692505
    27702506        mod = ldb_msg_new(mem_ctx);
     
    27752511        mod->dn = talloc_reference(mem_ctx, a_state->account_dn);
    27762512
    2777         if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
    2778                                  memberdn) != 0)
     2513        ret = samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod, "member",
     2514                                                                 memberdn);
     2515        if (ret != LDB_SUCCESS) {
    27792516                return NT_STATUS_UNSUCCESSFUL;
    2780 
    2781         if (ldb_modify(a_state->sam_ctx, mod) != 0)
     2517        }
     2518
     2519        ret = ldb_modify(a_state->sam_ctx, mod);
     2520        switch (ret) {
     2521        case LDB_SUCCESS:
     2522                return NT_STATUS_OK;
     2523        case LDB_ERR_UNWILLING_TO_PERFORM:
     2524                return NT_STATUS_MEMBER_NOT_IN_GROUP;
     2525        case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
     2526                return NT_STATUS_ACCESS_DENIED;
     2527        default:
    27822528                return NT_STATUS_UNSUCCESSFUL;
    2783 
    2784         return NT_STATUS_OK;
    2785 }
    2786 
    2787 
    2788 /*
    2789   samr_GetMembersInAlias
     2529        }
     2530}
     2531
     2532
     2533/*
     2534  samr_GetMembersInAlias
    27902535*/
    27912536static NTSTATUS dcesrv_samr_GetMembersInAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    27952540        struct samr_account_state *a_state;
    27962541        struct samr_domain_state *d_state;
    2797         struct ldb_message **msgs;
    2798         struct lsa_SidPtr *sids;
    2799         struct ldb_message_element *el;
    2800         const char * const attrs[2] = { "member", NULL};
    2801         int ret;
     2542        struct lsa_SidPtr *array;
     2543        unsigned int i, num_members;
     2544        struct dom_sid *members;
     2545        NTSTATUS status;
    28022546
    28032547        DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
     
    28062550        d_state = a_state->domain_state;
    28072551
    2808         ret = gendb_search_dn(d_state->sam_ctx, mem_ctx,
    2809                               a_state->account_dn, &msgs, attrs);
    2810 
    2811         if (ret == -1) {
    2812                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2813         } else if (ret == 0) {
    2814                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    2815         } else if (ret != 1) {
    2816                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2817         }
    2818 
    2819         r->out.sids->num_sids = 0;
    2820         r->out.sids->sids = NULL;
    2821 
    2822         el = ldb_msg_find_element(msgs[0], "member");
    2823 
    2824         if (el != NULL) {
    2825                 int i;
    2826 
    2827                 sids = talloc_array(mem_ctx, struct lsa_SidPtr,
    2828                                       el->num_values);
    2829 
    2830                 if (sids == NULL)
    2831                         return NT_STATUS_NO_MEMORY;
    2832 
    2833                 for (i=0; i<el->num_values; i++) {
    2834                         struct ldb_message **msgs2;
    2835                         const char * const attrs2[2] = { "objectSid", NULL };
    2836                         ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
    2837                                               ldb_dn_from_ldb_val(mem_ctx, a_state->sam_ctx, &el->values[i]),
    2838                                               &msgs2, attrs2);
    2839                         if (ret != 1)
    2840                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2841 
    2842                         sids[i].sid = samdb_result_dom_sid(mem_ctx, msgs2[0],
    2843                                                            "objectSid");
    2844 
    2845                         if (sids[i].sid == NULL)
    2846                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2847                 }
    2848                 r->out.sids->num_sids = el->num_values;
    2849                 r->out.sids->sids = sids;
    2850         }
    2851 
    2852         return NT_STATUS_OK;
    2853 }
    2854 
    2855 /*
    2856   samr_OpenUser
     2552        status = dsdb_enum_group_mem(d_state->sam_ctx, mem_ctx,
     2553                                     a_state->account_dn, &members,
     2554                                     &num_members);
     2555        if (!NT_STATUS_IS_OK(status)) {
     2556                return status;
     2557        }
     2558
     2559        if (num_members == 0) {
     2560                r->out.sids->sids = NULL;
     2561
     2562                return NT_STATUS_OK;
     2563        }
     2564
     2565        array = talloc_array(mem_ctx, struct lsa_SidPtr, num_members);
     2566        if (array == NULL) {
     2567                return NT_STATUS_NO_MEMORY;
     2568        }
     2569
     2570        for (i=0; i<num_members; i++) {
     2571                array[i].sid = &members[i];
     2572        }
     2573
     2574        r->out.sids->num_sids = num_members;
     2575        r->out.sids->sids = array;
     2576
     2577        return NT_STATUS_OK;
     2578}
     2579
     2580/*
     2581  samr_OpenUser
    28572582*/
    28582583static NTSTATUS dcesrv_samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    28842609        ret = gendb_search(d_state->sam_ctx,
    28852610                           mem_ctx, d_state->domain_dn, &msgs, attrs,
    2886                            "(&(objectSid=%s)(objectclass=user))", 
     2611                           "(&(objectSid=%s)(objectclass=user))",
    28872612                           ldap_encode_ndr_dom_sid(mem_ctx, sid));
    28882613        if (ret == 0) {
     
    28902615        }
    28912616        if (ret != 1) {
    2892                 DEBUG(0,("Found %d records matching sid %s\n", ret, 
     2617                DEBUG(0,("Found %d records matching sid %s\n", ret,
    28932618                         dom_sid_string(mem_ctx, sid)));
    28942619                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    28952620        }
    28962621
    2897         account_name = samdb_result_string(msgs[0], "sAMAccountName", NULL);
     2622        account_name = ldb_msg_find_attr_as_string(msgs[0], "sAMAccountName", NULL);
    28982623        if (account_name == NULL) {
    2899                 DEBUG(0,("sAMAccountName field missing for sid %s\n", 
     2624                DEBUG(0,("sAMAccountName field missing for sid %s\n",
    29002625                         dom_sid_string(mem_ctx, sid)));
    29012626                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     
    29312656
    29322657
    2933 /* 
    2934   samr_DeleteUser 
     2658/*
     2659  samr_DeleteUser
    29352660*/
    29362661static NTSTATUS dcesrv_samr_DeleteUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    29482673
    29492674        ret = ldb_delete(a_state->sam_ctx, a_state->account_dn);
    2950         if (ret != 0) {
    2951                 DEBUG(1, ("Failed to delete user: %s: %s\n", 
    2952                           ldb_dn_get_linearized(a_state->account_dn), 
     2675        if (ret != LDB_SUCCESS) {
     2676                DEBUG(1, ("Failed to delete user: %s: %s\n",
     2677                          ldb_dn_get_linearized(a_state->account_dn),
    29532678                          ldb_errstring(a_state->sam_ctx)));
    29542679                return NT_STATUS_UNSUCCESSFUL;
    29552680        }
    29562681
     2682        talloc_free(h);
    29572683        ZERO_STRUCTP(r->out.user_handle);
    29582684
     
    29612687
    29622688
    2963 /* 
    2964   samr_QueryUserInfo 
     2689/*
     2690  samr_QueryUserInfo
    29652691*/
    29662692static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    30362762        case 5:
    30372763        {
    3038                 static const char * const attrs2[] = {"sAMAccountName", 
     2764                static const char * const attrs2[] = {"sAMAccountName",
    30392765                                                      "displayName",
    30402766                                                      "objectSid",
     
    30422768                                                      "homeDirectory",
    30432769                                                      "homeDrive",
    3044                                                       "scriptPath", 
     2770                                                      "scriptPath",
    30452771                                                      "profilePath",
    30462772                                                      "description",
     
    31372863                attrs = attrs2;
    31382864                break;
     2865        }
     2866        case 18:
     2867        {
     2868                return NT_STATUS_NOT_SUPPORTED;
    31392869        }
    31402870        case 20:
     
    31732903                break;
    31742904        }
     2905        case 23:
     2906        case 24:
     2907        case 25:
     2908        case 26:
     2909        {
     2910                return NT_STATUS_NOT_SUPPORTED;
     2911        }
     2912        default:
     2913        {
     2914                return NT_STATUS_INVALID_INFO_CLASS;
     2915        }
    31752916        }
    31762917
    31772918        /* pull all the user attributes */
    31782919        ret = gendb_search_dn(a_state->sam_ctx, mem_ctx,
    3179                               a_state->account_dn ,&res, attrs);
     2920                              a_state->account_dn, &res, attrs);
     2921        if (ret == 0) {
     2922                return NT_STATUS_NO_SUCH_USER;
     2923        }
    31802924        if (ret != 1) {
    31812925                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     
    33213065                QUERY_UINT  (msg, info21.primary_gid,          "primaryGroupID");
    33223066                QUERY_AFLAGS(msg, info21.acct_flags,           "userAccountControl");
    3323                 info->info21.fields_present = 0x00FFFFFF;
     3067                info->info21.fields_present = 0x08FFFFFF;
    33243068                QUERY_LHOURS(msg, info21.logon_hours,          "logonHours");
    33253069                QUERY_UINT  (msg, info21.bad_password_count,   "badPwdCount");
    33263070                QUERY_UINT  (msg, info21.logon_count,          "logonCount");
     3071                if ((info->info21.acct_flags & ACB_PW_EXPIRED) != 0) {
     3072                        info->info21.password_expired = PASS_MUST_CHANGE_AT_NEXT_LOGON;
     3073                } else {
     3074                        info->info21.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;
     3075                }
    33273076                QUERY_UINT  (msg, info21.country_code,         "countryCode");
    33283077                QUERY_UINT  (msg, info21.code_page,            "codePage");
    33293078                break;
    3330                
     3079
    33313080
    33323081        default:
     
    33413090
    33423091
    3343 /* 
    3344   samr_SetUserInfo 
     3092/*
     3093  samr_SetUserInfo
    33453094*/
    33463095static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    34263175                break;
    34273176
     3177        case 18:
     3178                status = samr_set_password_buffers(dce_call,
     3179                                                   a_state->sam_ctx,
     3180                                                   a_state->account_dn,
     3181                                                   a_state->domain_state->domain_dn,
     3182                                                   mem_ctx,
     3183                                                   r->in.info->info18.lm_pwd_active ? r->in.info->info18.lm_pwd.hash : NULL,
     3184                                                   r->in.info->info18.nt_pwd_active ? r->in.info->info18.nt_pwd.hash : NULL);
     3185                if (!NT_STATUS_IS_OK(status)) {
     3186                        return status;
     3187                }
     3188
     3189                if (r->in.info->info18.password_expired > 0) {
     3190                        struct ldb_message_element *set_el;
     3191                        if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) {
     3192                                return NT_STATUS_NO_MEMORY;
     3193                        }
     3194                        set_el = ldb_msg_find_element(msg, "pwdLastSet");
     3195                        set_el->flags = LDB_FLAG_MOD_REPLACE;
     3196                }
     3197                break;
     3198
    34283199        case 20:
    34293200                SET_PARAMETERS(msg, info20.parameters,      "userParameters");
     
    34313202
    34323203        case 21:
     3204                if (r->in.info->info21.fields_present == 0)
     3205                        return NT_STATUS_INVALID_PARAMETER;
     3206
    34333207#define IFSET(bit) if (bit & r->in.info->info21.fields_present)
     3208                IFSET(SAMR_FIELD_LAST_LOGON)
     3209                        SET_UINT64(msg, info21.last_logon,     "lastLogon");
     3210                IFSET(SAMR_FIELD_LAST_LOGOFF)
     3211                        SET_UINT64(msg, info21.last_logoff,    "lastLogoff");
    34343212                IFSET(SAMR_FIELD_ACCT_EXPIRY)
    34353213                        SET_UINT64(msg, info21.acct_expiry,    "accountExpires");
    3436                 IFSET(SAMR_FIELD_ACCOUNT_NAME)         
     3214                IFSET(SAMR_FIELD_ACCOUNT_NAME)
    34373215                        SET_STRING(msg, info21.account_name,   "samAccountName");
    3438                 IFSET(SAMR_FIELD_FULL_NAME) 
     3216                IFSET(SAMR_FIELD_FULL_NAME)
    34393217                        SET_STRING(msg, info21.full_name,      "displayName");
    34403218                IFSET(SAMR_FIELD_HOME_DIRECTORY)
     
    34523230                IFSET(SAMR_FIELD_COMMENT)
    34533231                        SET_STRING(msg, info21.comment,        "comment");
    3454                 IFSET(SAMR_FIELD_PARAMETERS)   
     3232                IFSET(SAMR_FIELD_PARAMETERS)
    34553233                        SET_PARAMETERS(msg, info21.parameters, "userParameters");
    34563234                IFSET(SAMR_FIELD_PRIMARY_GID)
     
    34603238                IFSET(SAMR_FIELD_LOGON_HOURS)
    34613239                        SET_LHOURS(msg, info21.logon_hours,    "logonHours");
     3240                IFSET(SAMR_FIELD_BAD_PWD_COUNT)
     3241                        SET_UINT  (msg, info21.bad_password_count, "badPwdCount");
     3242                IFSET(SAMR_FIELD_NUM_LOGONS)
     3243                        SET_UINT  (msg, info21.logon_count,    "logonCount");
    34623244                IFSET(SAMR_FIELD_COUNTRY_CODE)
    34633245                        SET_UINT  (msg, info21.country_code,   "countryCode");
    34643246                IFSET(SAMR_FIELD_CODE_PAGE)
    34653247                        SET_UINT  (msg, info21.code_page,      "codePage");
     3248
     3249                /* password change fields */
     3250                IFSET(SAMR_FIELD_LAST_PWD_CHANGE)
     3251                        return NT_STATUS_ACCESS_DENIED;
     3252
     3253                IFSET((SAMR_FIELD_LM_PASSWORD_PRESENT
     3254                                        | SAMR_FIELD_NT_PASSWORD_PRESENT)) {
     3255                        uint8_t *lm_pwd_hash = NULL, *nt_pwd_hash = NULL;
     3256
     3257                        if (r->in.info->info21.lm_password_set) {
     3258                                if ((r->in.info->info21.lm_owf_password.length != 16)
     3259                                 || (r->in.info->info21.lm_owf_password.size != 16)) {
     3260                                        return NT_STATUS_INVALID_PARAMETER;
     3261                                }
     3262
     3263                                lm_pwd_hash = (uint8_t *) r->in.info->info21.lm_owf_password.array;
     3264                        }
     3265                        if (r->in.info->info21.nt_password_set) {
     3266                                if ((r->in.info->info21.nt_owf_password.length != 16)
     3267                                 || (r->in.info->info21.nt_owf_password.size != 16)) {
     3268                                        return NT_STATUS_INVALID_PARAMETER;
     3269                                }
     3270
     3271                                nt_pwd_hash = (uint8_t *) r->in.info->info21.nt_owf_password.array;
     3272                        }
     3273                        status = samr_set_password_buffers(dce_call,
     3274                                                           a_state->sam_ctx,
     3275                                                           a_state->account_dn,
     3276                                                           a_state->domain_state->domain_dn,
     3277                                                           mem_ctx,
     3278                                                           lm_pwd_hash,
     3279                                                           nt_pwd_hash);
     3280                        if (!NT_STATUS_IS_OK(status)) {
     3281                                return status;
     3282                        }
     3283                }
     3284
     3285
     3286                IFSET(SAMR_FIELD_EXPIRED_FLAG) {
     3287                        NTTIME t = 0;
     3288                        struct ldb_message_element *set_el;
     3289                        if (r->in.info->info21.password_expired
     3290                                        == PASS_DONT_CHANGE_AT_NEXT_LOGON) {
     3291                                unix_to_nt_time(&t, time(NULL));
     3292                        }
     3293                        if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg,
     3294                                                 "pwdLastSet", t) != LDB_SUCCESS) {
     3295                                return NT_STATUS_NO_MEMORY;
     3296                        }
     3297                        set_el = ldb_msg_find_element(msg, "pwdLastSet");
     3298                        set_el->flags = LDB_FLAG_MOD_REPLACE;
     3299                }
    34663300#undef IFSET
    34673301                break;
    34683302
    34693303        case 23:
     3304                if (r->in.info->info23.info.fields_present == 0)
     3305                        return NT_STATUS_INVALID_PARAMETER;
     3306
    34703307#define IFSET(bit) if (bit & r->in.info->info23.info.fields_present)
     3308                IFSET(SAMR_FIELD_LAST_LOGON)
     3309                        SET_UINT64(msg, info23.info.last_logon,     "lastLogon");
     3310                IFSET(SAMR_FIELD_LAST_LOGOFF)
     3311                        SET_UINT64(msg, info23.info.last_logoff,    "lastLogoff");
    34713312                IFSET(SAMR_FIELD_ACCT_EXPIRY)
    34723313                        SET_UINT64(msg, info23.info.acct_expiry,    "accountExpires");
    3473                 IFSET(SAMR_FIELD_ACCOUNT_NAME)         
     3314                IFSET(SAMR_FIELD_ACCOUNT_NAME)
    34743315                        SET_STRING(msg, info23.info.account_name,   "samAccountName");
    34753316                IFSET(SAMR_FIELD_FULL_NAME)
     
    34973338                IFSET(SAMR_FIELD_LOGON_HOURS)
    34983339                        SET_LHOURS(msg, info23.info.logon_hours,    "logonHours");
     3340                IFSET(SAMR_FIELD_BAD_PWD_COUNT)
     3341                        SET_UINT  (msg, info23.info.bad_password_count, "badPwdCount");
     3342                IFSET(SAMR_FIELD_NUM_LOGONS)
     3343                        SET_UINT  (msg, info23.info.logon_count,    "logonCount");
     3344
    34993345                IFSET(SAMR_FIELD_COUNTRY_CODE)
    35003346                        SET_UINT  (msg, info23.info.country_code,   "countryCode");
    35013347                IFSET(SAMR_FIELD_CODE_PAGE)
    35023348                        SET_UINT  (msg, info23.info.code_page,      "codePage");
     3349
     3350                /* password change fields */
     3351                IFSET(SAMR_FIELD_LAST_PWD_CHANGE)
     3352                        return NT_STATUS_ACCESS_DENIED;
    35033353
    35043354                IFSET(SAMR_FIELD_NT_PASSWORD_PRESENT) {
     
    35073357                                                   a_state->account_dn,
    35083358                                                   a_state->domain_state->domain_dn,
    3509                                                    mem_ctx, msg,
     3359                                                   mem_ctx,
    35103360                                                   &r->in.info->info23.password);
    35113361                } else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT) {
     
    35143364                                                   a_state->account_dn,
    35153365                                                   a_state->domain_state->domain_dn,
    3516                                                    mem_ctx, msg,
     3366                                                   mem_ctx,
    35173367                                                   &r->in.info->info23.password);
     3368                }
     3369                if (!NT_STATUS_IS_OK(status)) {
     3370                        return status;
     3371                }
     3372
     3373                IFSET(SAMR_FIELD_EXPIRED_FLAG) {
     3374                        NTTIME t = 0;
     3375                        struct ldb_message_element *set_el;
     3376                        if (r->in.info->info23.info.password_expired
     3377                                        == PASS_DONT_CHANGE_AT_NEXT_LOGON) {
     3378                                unix_to_nt_time(&t, time(NULL));
     3379                        }
     3380                        if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg,
     3381                                                 "pwdLastSet", t) != LDB_SUCCESS) {
     3382                                return NT_STATUS_NO_MEMORY;
     3383                        }
     3384                        set_el = ldb_msg_find_element(msg, "pwdLastSet");
     3385                        set_el->flags = LDB_FLAG_MOD_REPLACE;
    35183386                }
    35193387#undef IFSET
     
    35263394                                           a_state->account_dn,
    35273395                                           a_state->domain_state->domain_dn,
    3528                                            mem_ctx, msg,
     3396                                           mem_ctx,
    35293397                                           &r->in.info->info24.password);
     3398                if (!NT_STATUS_IS_OK(status)) {
     3399                        return status;
     3400                }
     3401
     3402                if (r->in.info->info24.password_expired > 0) {
     3403                        struct ldb_message_element *set_el;
     3404                        if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) {
     3405                                return NT_STATUS_NO_MEMORY;
     3406                        }
     3407                        set_el = ldb_msg_find_element(msg, "pwdLastSet");
     3408                        set_el->flags = LDB_FLAG_MOD_REPLACE;
     3409                }
    35303410                break;
    35313411
    35323412        case 25:
     3413                if (r->in.info->info25.info.fields_present == 0)
     3414                        return NT_STATUS_INVALID_PARAMETER;
     3415
    35333416#define IFSET(bit) if (bit & r->in.info->info25.info.fields_present)
     3417                IFSET(SAMR_FIELD_LAST_LOGON)
     3418                        SET_UINT64(msg, info25.info.last_logon,     "lastLogon");
     3419                IFSET(SAMR_FIELD_LAST_LOGOFF)
     3420                        SET_UINT64(msg, info25.info.last_logoff,    "lastLogoff");
    35343421                IFSET(SAMR_FIELD_ACCT_EXPIRY)
    35353422                        SET_UINT64(msg, info25.info.acct_expiry,    "accountExpires");
    3536                 IFSET(SAMR_FIELD_ACCOUNT_NAME)         
     3423                IFSET(SAMR_FIELD_ACCOUNT_NAME)
    35373424                        SET_STRING(msg, info25.info.account_name,   "samAccountName");
    35383425                IFSET(SAMR_FIELD_FULL_NAME)
     
    35603447                IFSET(SAMR_FIELD_LOGON_HOURS)
    35613448                        SET_LHOURS(msg, info25.info.logon_hours,    "logonHours");
     3449                IFSET(SAMR_FIELD_BAD_PWD_COUNT)
     3450                        SET_UINT  (msg, info25.info.bad_password_count, "badPwdCount");
     3451                IFSET(SAMR_FIELD_NUM_LOGONS)
     3452                        SET_UINT  (msg, info25.info.logon_count,    "logonCount");
    35623453                IFSET(SAMR_FIELD_COUNTRY_CODE)
    35633454                        SET_UINT  (msg, info25.info.country_code,   "countryCode");
    35643455                IFSET(SAMR_FIELD_CODE_PAGE)
    35653456                        SET_UINT  (msg, info25.info.code_page,      "codePage");
     3457
     3458                /* password change fields */
     3459                IFSET(SAMR_FIELD_LAST_PWD_CHANGE)
     3460                        return NT_STATUS_ACCESS_DENIED;
    35663461
    35673462                IFSET(SAMR_FIELD_NT_PASSWORD_PRESENT) {
     
    35703465                                                      a_state->account_dn,
    35713466                                                      a_state->domain_state->domain_dn,
    3572                                                       mem_ctx, msg,
     3467                                                      mem_ctx,
    35733468                                                      &r->in.info->info25.password);
    35743469                } else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT) {
     
    35773472                                                      a_state->account_dn,
    35783473                                                      a_state->domain_state->domain_dn,
    3579                                                       mem_ctx, msg,
     3474                                                      mem_ctx,
    35803475                                                      &r->in.info->info25.password);
     3476                }
     3477                if (!NT_STATUS_IS_OK(status)) {
     3478                        return status;
     3479                }
     3480
     3481                IFSET(SAMR_FIELD_EXPIRED_FLAG) {
     3482                        NTTIME t = 0;
     3483                        struct ldb_message_element *set_el;
     3484                        if (r->in.info->info25.info.password_expired
     3485                                        == PASS_DONT_CHANGE_AT_NEXT_LOGON) {
     3486                                unix_to_nt_time(&t, time(NULL));
     3487                        }
     3488                        if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg,
     3489                                                 "pwdLastSet", t) != LDB_SUCCESS) {
     3490                                return NT_STATUS_NO_MEMORY;
     3491                        }
     3492                        set_el = ldb_msg_find_element(msg, "pwdLastSet");
     3493                        set_el->flags = LDB_FLAG_MOD_REPLACE;
    35813494                }
    35823495#undef IFSET
     
    35893502                                              a_state->account_dn,
    35903503                                              a_state->domain_state->domain_dn,
    3591                                               mem_ctx, msg,
     3504                                              mem_ctx,
    35923505                                              &r->in.info->info26.password);
    3593                 break;
    3594                
     3506                if (!NT_STATUS_IS_OK(status)) {
     3507                        return status;
     3508                }
     3509
     3510                if (r->in.info->info26.password_expired > 0) {
     3511                        struct ldb_message_element *set_el;
     3512                        if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) {
     3513                                return NT_STATUS_NO_MEMORY;
     3514                        }
     3515                        set_el = ldb_msg_find_element(msg, "pwdLastSet");
     3516                        set_el->flags = LDB_FLAG_MOD_REPLACE;
     3517                }
     3518                break;
    35953519
    35963520        default:
     
    36043528
    36053529        /* modify the samdb record */
    3606         ret = ldb_modify(a_state->sam_ctx, msg);
    3607         if (ret != 0) {
    3608                 DEBUG(1,("Failed to modify record %s: %s\n",
    3609                          ldb_dn_get_linearized(a_state->account_dn),
    3610                          ldb_errstring(a_state->sam_ctx)));
    3611 
    3612                 /* we really need samdb.c to return NTSTATUS */
    3613                 return NT_STATUS_UNSUCCESSFUL;
    3614         }
    3615 
    3616         return NT_STATUS_OK;
    3617 }
    3618 
    3619 
    3620 /*
    3621   samr_GetGroupsForUser
     3530        if (msg->num_elements > 0) {
     3531                ret = ldb_modify(a_state->sam_ctx, msg);
     3532                if (ret != LDB_SUCCESS) {
     3533                        DEBUG(1,("Failed to modify record %s: %s\n",
     3534                                 ldb_dn_get_linearized(a_state->account_dn),
     3535                                 ldb_errstring(a_state->sam_ctx)));
     3536
     3537                        /* we really need samdb.c to return NTSTATUS */
     3538                        return NT_STATUS_UNSUCCESSFUL;
     3539                }
     3540        }
     3541
     3542        return NT_STATUS_OK;
     3543}
     3544
     3545
     3546/*
     3547  samr_GetGroupsForUser
    36223548*/
    36233549static NTSTATUS dcesrv_samr_GetGroupsForUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    36403566                                    d_state->domain_dn, &res,
    36413567                                    attrs, d_state->domain_sid,
    3642                                     "(&(member=%s)(grouptype=%d)(objectclass=group))",
     3568                                    "(&(member=%s)(|(grouptype=%d)(grouptype=%d))(objectclass=group))",
    36433569                                    ldb_dn_get_linearized(a_state->account_dn),
     3570                                    GTYPE_SECURITY_UNIVERSAL_GROUP,
    36443571                                    GTYPE_SECURITY_GLOBAL_GROUP);
    36453572        if (count < 0)
     
    36723599                group_sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
    36733600                if (group_sid == NULL) {
    3674                         DEBUG(0, ("Couldn't find objectSid attrib\n"));
    3675                         continue;
     3601                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
    36763602                }
    36773603
     
    36893615
    36903616
    3691 /* 
    3692   samr_QueryDisplayInfo 
     3617/*
     3618  samr_QueryDisplayInfo
    36933619*/
    36943620static NTSTATUS dcesrv_samr_QueryDisplayInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    36973623        struct dcesrv_handle *h;
    36983624        struct samr_domain_state *d_state;
    3699         struct ldb_message **res;
    3700         int ldb_cnt, count, i;
     3625        struct ldb_result *res;
     3626        unsigned int i;
     3627        uint32_t count;
    37013628        const char * const attrs[] = { "objectSid", "sAMAccountName",
    37023629                "displayName", "description", "userAccountControl",
     
    37073634        struct samr_DispEntryGeneral *entriesGeneral = NULL;
    37083635        const char *filter;
     3636        int ret;
    37093637
    37103638        DCESRV_PULL_HANDLE(h, r->in.domain_handle, SAMR_HANDLE_DOMAIN);
     
    37163644        case 4:
    37173645                filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)"
    3718                                          "(sAMAccountType=%u))",
     3646                                         "(sAMAccountType=%d))",
    37193647                                         ATYPE_NORMAL_ACCOUNT);
    37203648                break;
    37213649        case 2:
    37223650                filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)"
    3723                                          "(sAMAccountType=%u))",
     3651                                         "(sAMAccountType=%d))",
    37243652                                         ATYPE_WORKSTATION_TRUST);
    37253653                break;
    37263654        case 3:
    37273655        case 5:
    3728                 filter = talloc_asprintf(mem_ctx, "(&(grouptype=%d)"
    3729                                          "(objectclass=group))",
     3656                filter = talloc_asprintf(mem_ctx,
     3657                                         "(&(|(groupType=%d)(groupType=%d))"
     3658                                         "(objectClass=group))",
     3659                                         GTYPE_SECURITY_UNIVERSAL_GROUP,
    37303660                                         GTYPE_SECURITY_GLOBAL_GROUP);
    37313661                break;
     
    37343664        }
    37353665
    3736         /* search for all requested objects in this domain. This could
     3666        /* search for all requested objects in all domains. This could
    37373667           possibly be cached and resumed based on resume_key */
    3738         ldb_cnt = samdb_search_domain(d_state->sam_ctx, mem_ctx,
    3739                                       d_state->domain_dn, &res, attrs,
    3740                                       d_state->domain_sid, "%s", filter);
    3741         if (ldb_cnt == -1) {
     3668        ret = dsdb_search(d_state->sam_ctx, mem_ctx, &res, NULL,
     3669                          LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
     3670        if (ret != LDB_SUCCESS) {
    37423671                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    37433672        }
    3744         if (ldb_cnt == 0 || r->in.max_entries == 0) {
     3673        if ((res->count == 0) || (r->in.max_entries == 0)) {
    37453674                return NT_STATUS_OK;
    37463675        }
     
    37493678        case 1:
    37503679                entriesGeneral = talloc_array(mem_ctx,
    3751                                              struct samr_DispEntryGeneral,
    3752                                              ldb_cnt);
     3680                                              struct samr_DispEntryGeneral,
     3681                                              res->count);
    37533682                break;
    37543683        case 2:
    37553684                entriesFull = talloc_array(mem_ctx,
    3756                                              struct samr_DispEntryFull,
    3757                                              ldb_cnt);
     3685                                           struct samr_DispEntryFull,
     3686                                           res->count);
    37583687                break;
    37593688        case 3:
    37603689                entriesFullGroup = talloc_array(mem_ctx,
    3761                                              struct samr_DispEntryFullGroup,
    3762                                              ldb_cnt);
     3690                                                struct samr_DispEntryFullGroup,
     3691                                                res->count);
    37633692                break;
    37643693        case 4:
    37653694        case 5:
    37663695                entriesAscii = talloc_array(mem_ctx,
    3767                                               struct samr_DispEntryAscii,
    3768                                               ldb_cnt);
     3696                                            struct samr_DispEntryAscii,
     3697                                            res->count);
    37693698                break;
    37703699        }
     
    37763705        count = 0;
    37773706
    3778         for (i=0; i<ldb_cnt; i++) {
     3707        for (i = 0; i < res->count; i++) {
    37793708                struct dom_sid *objectsid;
    37803709
    3781                 objectsid = samdb_result_dom_sid(mem_ctx, res[i],
     3710                objectsid = samdb_result_dom_sid(mem_ctx, res->msgs[i],
    37823711                                                 "objectSid");
    37833712                if (objectsid == NULL)
     
    37873716                case 1:
    37883717                        entriesGeneral[count].idx = count + 1;
    3789                         entriesGeneral[count].rid = 
     3718                        entriesGeneral[count].rid =
    37903719                                objectsid->sub_auths[objectsid->num_auths-1];
    37913720                        entriesGeneral[count].acct_flags =
    3792                                 samdb_result_acct_flags(d_state->sam_ctx, mem_ctx,
    3793                                                         res[i],
     3721                                samdb_result_acct_flags(d_state->sam_ctx,
     3722                                                        mem_ctx,
     3723                                                        res->msgs[i],
    37943724                                                        d_state->domain_dn);
    37953725                        entriesGeneral[count].account_name.string =
    3796                                 samdb_result_string(res[i],
    3797                                                     "sAMAccountName", "");
     3726                                ldb_msg_find_attr_as_string(res->msgs[i],
     3727                                                            "sAMAccountName", "");
    37983728                        entriesGeneral[count].full_name.string =
    3799                                 samdb_result_string(res[i], "displayName", "");
     3729                                ldb_msg_find_attr_as_string(res->msgs[i],
     3730                                                            "displayName", "");
    38003731                        entriesGeneral[count].description.string =
    3801                                 samdb_result_string(res[i], "description", "");
     3732                                ldb_msg_find_attr_as_string(res->msgs[i],
     3733                                                            "description", "");
    38023734                        break;
    38033735                case 2:
     
    38083740                        /* No idea why we need to or in ACB_NORMAL here, but this is what Win2k3 seems to do... */
    38093741                        entriesFull[count].acct_flags =
    3810                                 samdb_result_acct_flags(d_state->sam_ctx, mem_ctx,
    3811                                                         res[i],
     3742                                samdb_result_acct_flags(d_state->sam_ctx,
     3743                                                        mem_ctx,
     3744                                                        res->msgs[i],
    38123745                                                        d_state->domain_dn) | ACB_NORMAL;
    38133746                        entriesFull[count].account_name.string =
    3814                                 samdb_result_string(res[i], "sAMAccountName",
    3815                                                     "");
     3747                                ldb_msg_find_attr_as_string(res->msgs[i],
     3748                                                            "sAMAccountName", "");
    38163749                        entriesFull[count].description.string =
    3817                                 samdb_result_string(res[i], "description", "");
     3750                                ldb_msg_find_attr_as_string(res->msgs[i],
     3751                                                            "description", "");
    38183752                        break;
    38193753                case 3:
     
    38253759                                = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED;
    38263760                        entriesFullGroup[count].account_name.string =
    3827                                 samdb_result_string(res[i], "sAMAccountName",
    3828                                                     "");
     3761                                ldb_msg_find_attr_as_string(res->msgs[i],
     3762                                                            "sAMAccountName", "");
    38293763                        entriesFullGroup[count].description.string =
    3830                                 samdb_result_string(res[i], "description", "");
     3764                                ldb_msg_find_attr_as_string(res->msgs[i],
     3765                                                            "description", "");
    38313766                        break;
    38323767                case 4:
     
    38343769                        entriesAscii[count].idx = count + 1;
    38353770                        entriesAscii[count].account_name.string =
    3836                                 samdb_result_string(res[i], "sAMAccountName",
    3837                                                     "");
     3771                                ldb_msg_find_attr_as_string(res->msgs[i],
     3772                                                            "sAMAccountName", "");
    38383773                        break;
    38393774                }
     
    39053840
    39063841
    3907 /* 
    3908   samr_GetDisplayEnumerationIndex 
     3842/*
     3843  samr_GetDisplayEnumerationIndex
    39093844*/
    39103845static NTSTATUS dcesrv_samr_GetDisplayEnumerationIndex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    39153850
    39163851
    3917 /* 
    3918   samr_TestPrivateFunctionsDomain 
     3852/*
     3853  samr_TestPrivateFunctionsDomain
    39193854*/
    39203855static NTSTATUS dcesrv_samr_TestPrivateFunctionsDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    39253860
    39263861
    3927 /* 
    3928   samr_TestPrivateFunctionsUser 
     3862/*
     3863  samr_TestPrivateFunctionsUser
    39293864*/
    39303865static NTSTATUS dcesrv_samr_TestPrivateFunctionsUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    39353870
    39363871
    3937 /* 
    3938   samr_GetUserPwInfo 
     3872/*
     3873  samr_GetUserPwInfo
    39393874*/
    39403875static NTSTATUS dcesrv_samr_GetUserPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    39603895
    39613896
    3962 /*
    3963   samr_RemoveMemberFromForeignDomain
    3964 */
    3965 static NTSTATUS dcesrv_samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3966                        struct samr_RemoveMemberFromForeignDomain *r)
     3897/*
     3898  samr_RemoveMemberFromForeignDomain
     3899*/
     3900static NTSTATUS dcesrv_samr_RemoveMemberFromForeignDomain(struct dcesrv_call_state *dce_call,
     3901                                                          TALLOC_CTX *mem_ctx,
     3902                                                          struct samr_RemoveMemberFromForeignDomain *r)
    39673903{
    39683904        struct dcesrv_handle *h;
     
    39703906        const char *memberdn;
    39713907        struct ldb_message **res;
    3972         const char * const attrs[3] = { "distinguishedName", "objectSid", NULL };
     3908        const char *no_attrs[] = { NULL };
    39733909        int i, count;
    39743910
     
    39783914
    39793915        memberdn = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
    3980                                        "distinguishedName", "(objectSid=%s)", 
     3916                                       "distinguishedName", "(objectSid=%s)",
    39813917                                       ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid));
    39823918        /* Nothing to do */
     
    39853921        }
    39863922
    3987         /* TODO: Does this call only remove alias members, or does it do this
    3988          * for domain groups as well? */
    3989 
    39903923        count = samdb_search_domain(d_state->sam_ctx, mem_ctx,
    3991                                     d_state->domain_dn, &res, attrs,
     3924                                    d_state->domain_dn, &res, no_attrs,
    39923925                                    d_state->domain_sid,
    39933926                                    "(&(member=%s)(objectClass=group)"
     
    40083941                }
    40093942
    4010                 mod->dn = samdb_result_dn(d_state->sam_ctx, mod, res[i], "distinguishedName", NULL);
    4011                 if (mod->dn == NULL) {
    4012                         talloc_free(mod);
    4013                         continue;
    4014                 }
     3943                mod->dn = res[i]->dn;
    40153944
    40163945                if (samdb_msg_add_delval(d_state->sam_ctx, mem_ctx, mod,
    4017                                          "member", memberdn) != 0)
     3946                                         "member", memberdn) != LDB_SUCCESS)
    40183947                        return NT_STATUS_NO_MEMORY;
    40193948
    4020                 if (ldb_modify(d_state->sam_ctx, mod) != 0)
     3949                if (ldb_modify(d_state->sam_ctx, mod) != LDB_SUCCESS)
    40213950                        return NT_STATUS_UNSUCCESSFUL;
    40223951
     
    40283957
    40293958
    4030 /* 
    4031   samr_QueryDomainInfo2 
     3959/*
     3960  samr_QueryDomainInfo2
    40323961
    40333962  just an alias for samr_QueryDomainInfo
     
    40453974
    40463975        status = dcesrv_samr_QueryDomainInfo(dce_call, mem_ctx, &r1);
    4047        
     3976
    40483977        return status;
    40493978}
    40503979
    40513980
    4052 /* 
    4053   samr_QueryUserInfo2 
     3981/*
     3982  samr_QueryUserInfo2
    40543983
    40553984  just an alias for samr_QueryUserInfo
     
    40643993        r1.in.level  = r->in.level;
    40653994        r1.out.info  = r->out.info;
    4066        
     3995
    40673996        status = dcesrv_samr_QueryUserInfo(dce_call, mem_ctx, &r1);
    40683997
     
    40714000
    40724001
    4073 /* 
    4074   samr_QueryDisplayInfo2 
     4002/*
     4003  samr_QueryDisplayInfo2
    40754004*/
    40764005static NTSTATUS dcesrv_samr_QueryDisplayInfo2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    40954024
    40964025
    4097 /* 
    4098   samr_GetDisplayEnumerationIndex2 
     4026/*
     4027  samr_GetDisplayEnumerationIndex2
    40994028*/
    41004029static NTSTATUS dcesrv_samr_GetDisplayEnumerationIndex2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    41054034
    41064035
    4107 /* 
    4108   samr_QueryDisplayInfo3 
     4036/*
     4037  samr_QueryDisplayInfo3
    41094038*/
    41104039static NTSTATUS dcesrv_samr_QueryDisplayInfo3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    41294058
    41304059
    4131 /* 
    4132   samr_AddMultipleMembersToAlias 
     4060/*
     4061  samr_AddMultipleMembersToAlias
    41334062*/
    41344063static NTSTATUS dcesrv_samr_AddMultipleMembersToAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    41394068
    41404069
    4141 /* 
    4142   samr_RemoveMultipleMembersFromAlias 
     4070/*
     4071  samr_RemoveMultipleMembersFromAlias
    41434072*/
    41444073static NTSTATUS dcesrv_samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    41494078
    41504079
    4151 /* 
    4152   samr_GetDomPwInfo 
     4080/*
     4081  samr_GetDomPwInfo
    41534082
    41544083  this fetches the default password properties for a domain
    41554084
    4156   note that w2k3 completely ignores the domain name in this call, and 
     4085  note that w2k3 completely ignores the domain name in this call, and
    41574086  always returns the information for the servers primary domain
    41584087*/
     
    41674096        ZERO_STRUCTP(r->out.info);
    41684097
    4169         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
     4098        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
     4099                                         dce_call->conn->dce_ctx->lp_ctx,
     4100                                         dce_call->conn->auth_state.session_info, 0);
    41704101        if (sam_ctx == NULL) {
    41714102                return NT_STATUS_INVALID_SYSTEM_SERVICE;
     
    41734104
    41744105        /* The domain name in this call is ignored */
    4175         ret = gendb_search_dn(sam_ctx, 
     4106        ret = gendb_search_dn(sam_ctx,
    41764107                           mem_ctx, NULL, &msgs, attrs);
    41774108        if (ret <= 0) {
     4109                talloc_free(sam_ctx);
     4110
    41784111                return NT_STATUS_NO_SUCH_DOMAIN;
    41794112        }
    41804113        if (ret > 1) {
    41814114                talloc_free(msgs);
     4115                talloc_free(sam_ctx);
     4116
    41824117                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    41834118        }
    41844119
    4185         r->out.info->min_password_length = samdb_result_uint(msgs[0],
     4120        r->out.info->min_password_length = ldb_msg_find_attr_as_uint(msgs[0],
    41864121                "minPwdLength", 0);
    4187         r->out.info->password_properties = samdb_result_uint(msgs[0],
     4122        r->out.info->password_properties = ldb_msg_find_attr_as_uint(msgs[0],
    41884123                "pwdProperties", 1);
    41894124
    41904125        talloc_free(msgs);
    4191 
    4192         talloc_free(sam_ctx);
    4193         return NT_STATUS_OK;
    4194 }
    4195 
    4196 
    4197 /* 
    4198   samr_Connect2 
     4126        talloc_unlink(mem_ctx, sam_ctx);
     4127
     4128        return NT_STATUS_OK;
     4129}
     4130
     4131
     4132/*
     4133  samr_Connect2
    41994134*/
    42004135static NTSTATUS dcesrv_samr_Connect2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    42114146
    42124147
    4213 /* 
    4214   samr_SetUserInfo2 
     4148/*
     4149  samr_SetUserInfo2
    42154150
    42164151  just an alias for samr_SetUserInfo
     
    42294164
    42304165
    4231 /* 
    4232   samr_SetBootKeyInformation 
     4166/*
     4167  samr_SetBootKeyInformation
    42334168*/
    42344169static NTSTATUS dcesrv_samr_SetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    42394174
    42404175
    4241 /* 
    4242   samr_GetBootKeyInformation 
     4176/*
     4177  samr_GetBootKeyInformation
    42434178*/
    42444179static NTSTATUS dcesrv_samr_GetBootKeyInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    42454180                       struct samr_GetBootKeyInformation *r)
    42464181{
    4247         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4248 }
    4249 
    4250 
    4251 /*
    4252   samr_Connect3
     4182        /* Windows Server 2008 returns this */
     4183        return NT_STATUS_NOT_SUPPORTED;
     4184}
     4185
     4186
     4187/*
     4188  samr_Connect3
    42534189*/
    42544190static NTSTATUS dcesrv_samr_Connect3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    42654201
    42664202
    4267 /* 
    4268   samr_Connect4 
     4203/*
     4204  samr_Connect4
    42694205*/
    42704206static NTSTATUS dcesrv_samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    42814217
    42824218
    4283 /* 
    4284   samr_Connect5 
     4219/*
     4220  samr_Connect5
    42854221*/
    42864222static NTSTATUS dcesrv_samr_Connect5(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    43044240
    43054241
    4306 /* 
    4307   samr_RidToSid 
     4242/*
     4243  samr_RidToSid
    43084244*/
    43094245static NTSTATUS dcesrv_samr_RidToSid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    43274263
    43284264
    4329 /* 
    4330   samr_SetDsrmPassword 
     4265/*
     4266  samr_SetDsrmPassword
    43314267*/
    43324268static NTSTATUS dcesrv_samr_SetDsrmPassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    43374273
    43384274
    4339 /*
    4340   samr_ValidatePassword
    4341 */
    4342 static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4343                                       struct samr_ValidatePassword *r)
    4344 {
    4345         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     4275/*
     4276  samr_ValidatePassword
     4277
     4278  For now the call checks the password complexity (if active) and the minimum
     4279  password length on level 2 and 3. Level 1 is ignored for now.
     4280*/
     4281static NTSTATUS dcesrv_samr_ValidatePassword(struct dcesrv_call_state *dce_call,
     4282                                             TALLOC_CTX *mem_ctx,
     4283                                             struct samr_ValidatePassword *r)
     4284{
     4285        struct samr_GetDomPwInfo r2;
     4286        struct samr_PwInfo pwInfo;
     4287        DATA_BLOB password;
     4288        enum samr_ValidationStatus res;
     4289        NTSTATUS status;
     4290
     4291        (*r->out.rep) = talloc_zero(mem_ctx, union samr_ValidatePasswordRep);
     4292
     4293        r2.in.domain_name = NULL;
     4294        r2.out.info = &pwInfo;
     4295        status = dcesrv_samr_GetDomPwInfo(dce_call, mem_ctx, &r2);
     4296        if (!NT_STATUS_IS_OK(status)) {
     4297                return status;
     4298        }
     4299
     4300        switch (r->in.level) {
     4301        case NetValidateAuthentication:
     4302                /* we don't support this yet */
     4303                return NT_STATUS_NOT_SUPPORTED;
     4304        break;
     4305        case NetValidatePasswordChange:
     4306                password = data_blob_const(r->in.req->req2.password.string,
     4307                                           r->in.req->req2.password.length);
     4308                res = samdb_check_password(&password,
     4309                                           pwInfo.password_properties,
     4310                                           pwInfo.min_password_length);
     4311                (*r->out.rep)->ctr2.status = res;
     4312        break;
     4313        case NetValidatePasswordReset:
     4314                password = data_blob_const(r->in.req->req3.password.string,
     4315                                           r->in.req->req3.password.length);
     4316                res = samdb_check_password(&password,
     4317                                           pwInfo.password_properties,
     4318                                           pwInfo.min_password_length);
     4319                (*r->out.rep)->ctr3.status = res;
     4320        break;
     4321        default:
     4322                return NT_STATUS_INVALID_INFO_CLASS;
     4323        break;
     4324        }
     4325
     4326        return NT_STATUS_OK;
    43464327}
    43474328
  • trunk/server/source4/rpc_server/samr/dcesrv_samr.h

    r414 r745  
    1 /* 
     1/*
    22   Unix SMB/CIFS implementation.
    33
     
    55
    66   Copyright (C) Andrew Tridgell 2004
    7    
     7
    88   This program is free software; you can redistribute it and/or modify
    99   it under the terms of the GNU General Public License as published by
    1010   the Free Software Foundation; either version 3 of the License, or
    1111   (at your option) any later version.
    12    
     12
    1313   This program is distributed in the hope that it will be useful,
    1414   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1515   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1616   GNU General Public License for more details.
    17    
     17
    1818   You should have received a copy of the GNU General Public License
    1919   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  • trunk/server/source4/rpc_server/samr/samr_password.c

    r414 r745  
    1 /* 
     1/*
    22   Unix SMB/CIFS implementation.
    33
     
    66   Copyright (C) Andrew Tridgell 2004
    77   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
    8    
     8
    99   This program is free software; you can redistribute it and/or modify
    1010   it under the terms of the GNU General Public License as published by
    1111   the Free Software Foundation; either version 3 of the License, or
    1212   (at your option) any later version.
    13    
     13
    1414   This program is distributed in the hope that it will be useful,
    1515   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1616   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1717   GNU General Public License for more details.
    18    
     18
    1919   You should have received a copy of the GNU General Public License
    2020   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    3131#include "../lib/util/util_ldb.h"
    3232
    33 /* 
    34   samr_ChangePasswordUser 
    35 */
    36 NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, 
     33/*
     34  samr_ChangePasswordUser
     35*/
     36NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call,
    3737                                        TALLOC_CTX *mem_ctx,
    3838                                        struct samr_ChangePasswordUser *r)
     
    4141        struct samr_account_state *a_state;
    4242        struct ldb_context *sam_ctx;
    43         struct ldb_message **res, *msg;
     43        struct ldb_message **res;
    4444        int ret;
    4545        struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
     
    6161        }
    6262
    63         /* To change a password we need to open as system */
    64         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
     63        /* Connect to a SAMDB with system privileges for fetching the old pw
     64         * hashes. */
     65        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
     66                                dce_call->conn->dce_ctx->lp_ctx,
     67                                system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
    6568        if (sam_ctx == NULL) {
    6669                return NT_STATUS_INVALID_SYSTEM_SERVICE;
    67         }
    68 
    69         ret = ldb_transaction_start(sam_ctx);
    70         if (ret) {
    71                 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
    72                 return NT_STATUS_TRANSACTION_ABORTED;
    7370        }
    7471
     
    7774                              a_state->account_dn, &res, attrs);
    7875        if (ret != 1) {
    79                 ldb_transaction_cancel(sam_ctx);
    80                 return NT_STATUS_WRONG_PASSWORD;
    81         }
    82         msg = res[0];
    83 
    84         status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
    85                                         msg, &lm_pwd, &nt_pwd);
     76                return NT_STATUS_WRONG_PASSWORD;
     77        }
     78
     79        status = samdb_result_passwords(mem_ctx,
     80                                        dce_call->conn->dce_ctx->lp_ctx,
     81                                        res[0], &lm_pwd, &nt_pwd);
    8682        if (!NT_STATUS_IS_OK(status) || !nt_pwd) {
    87                 ldb_transaction_cancel(sam_ctx);
    8883                return NT_STATUS_WRONG_PASSWORD;
    8984        }
     
    9489                D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
    9590                if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
    96                         ldb_transaction_cancel(sam_ctx);
    9791                        return NT_STATUS_WRONG_PASSWORD;
    9892                }
     
    10397        D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
    10498        if (memcmp(checkHash.hash, nt_pwd, 16) != 0) {
    105                 ldb_transaction_cancel(sam_ctx);
    106                 return NT_STATUS_WRONG_PASSWORD;
    107         }
    108        
     99                return NT_STATUS_WRONG_PASSWORD;
     100        }
     101
    109102        /* The NT Cross is not required by Win2k3 R2, but if present
    110103           check the nt cross hash */
     
    112105                D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
    113106                if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
    114                         ldb_transaction_cancel(sam_ctx);
    115107                        return NT_STATUS_WRONG_PASSWORD;
    116108                }
     
    122114                D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
    123115                if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
    124                         ldb_transaction_cancel(sam_ctx);
    125116                        return NT_STATUS_WRONG_PASSWORD;
    126117                }
    127118        }
    128119
    129         msg = ldb_msg_new(mem_ctx);
    130         if (msg == NULL) {
    131                 ldb_transaction_cancel(sam_ctx);
    132                 return NT_STATUS_NO_MEMORY;
    133         }
    134 
    135         msg->dn = ldb_dn_copy(msg, a_state->account_dn);
    136         if (!msg->dn) {
    137                 ldb_transaction_cancel(sam_ctx);
    138                 return NT_STATUS_NO_MEMORY;
    139         }
    140 
    141         /* setup password modify mods on the user DN specified.  This may fail
    142          * due to password policies.  */
     120        /* Start a SAM with user privileges for the password change */
     121        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
     122                                dce_call->conn->dce_ctx->lp_ctx,
     123                                dce_call->conn->auth_state.session_info, 0);
     124        if (sam_ctx == NULL) {
     125                return NT_STATUS_INVALID_SYSTEM_SERVICE;
     126        }
     127
     128        /* Start transaction */
     129        ret = ldb_transaction_start(sam_ctx);
     130        if (ret != LDB_SUCCESS) {
     131                DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
     132                return NT_STATUS_TRANSACTION_ABORTED;
     133        }
     134
     135        /* Performs the password modification. We pass the old hashes read out
     136         * from the database since they were already checked against the user-
     137         * provided ones. */
    143138        status = samdb_set_password(sam_ctx, mem_ctx,
    144                                     a_state->account_dn, a_state->domain_state->domain_dn,
    145                                     msg, NULL, &new_lmPwdHash, &new_ntPwdHash,
    146                                     true, /* this is a user password change */
     139                                    a_state->account_dn,
     140                                    a_state->domain_state->domain_dn,
     141                                    NULL, &new_lmPwdHash, &new_ntPwdHash,
     142                                    lm_pwd, nt_pwd, /* this is a user password change */
    147143                                    NULL,
    148144                                    NULL);
     
    152148        }
    153149
    154         /* The above call only setup the modifications, this actually
    155          * makes the write to the database. */
    156         ret = samdb_replace(sam_ctx, mem_ctx, msg);
    157         if (ret != 0) {
    158                 DEBUG(2,("Failed to modify record to change password on %s: %s\n",
    159                          ldb_dn_get_linearized(a_state->account_dn),
    160                          ldb_errstring(sam_ctx)));
    161                 ldb_transaction_cancel(sam_ctx);
    162                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    163         }
    164 
    165150        /* And this confirms it in a transaction commit */
    166151        ret = ldb_transaction_commit(sam_ctx);
    167         if (ret != 0) {
     152        if (ret != LDB_SUCCESS) {
    168153                DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
    169154                         ldb_dn_get_linearized(a_state->account_dn),
     
    175160}
    176161
    177 /*
    178   samr_OemChangePasswordUser2
    179 */
    180 NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    181                                      struct samr_OemChangePasswordUser2 *r)
     162/*
     163  samr_OemChangePasswordUser2
     164*/
     165NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
     166                                            TALLOC_CTX *mem_ctx,
     167                                            struct samr_OemChangePasswordUser2 *r)
    182168{
    183169        NTSTATUS status;
     
    188174        struct ldb_dn *user_dn;
    189175        int ret;
    190         struct ldb_message **res, *mod;
     176        struct ldb_message **res;
    191177        const char * const attrs[] = { "objectSid", "dBCSPwd", NULL };
    192178        struct samr_Password *lm_pwd;
     
    205191
    206192        /* this call can only work with lanman auth */
    207         if (!lp_lanman_auth(dce_call->conn->dce_ctx->lp_ctx)) {
    208                 return NT_STATUS_NOT_SUPPORTED;
    209         }
    210 
    211         /* To change a password we need to open as system */
    212         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
     193        if (!lpcfg_lanman_auth(dce_call->conn->dce_ctx->lp_ctx)) {
     194                return NT_STATUS_WRONG_PASSWORD;
     195        }
     196
     197        /* Connect to a SAMDB with system privileges for fetching the old pw
     198         * hashes. */
     199        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
     200                                dce_call->conn->dce_ctx->lp_ctx,
     201                                system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
    213202        if (sam_ctx == NULL) {
    214203                return NT_STATUS_INVALID_SYSTEM_SERVICE;
    215         }
    216 
    217         ret = ldb_transaction_start(sam_ctx);
    218         if (ret) {
    219                 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
    220                 return NT_STATUS_TRANSACTION_ABORTED;
    221204        }
    222205
     
    224207           user SID). We also need the current lm password hash in
    225208           order to decrypt the incoming password */
    226         ret = gendb_search(sam_ctx, 
     209        ret = gendb_search(sam_ctx,
    227210                           mem_ctx, NULL, &res, attrs,
    228211                           "(&(sAMAccountName=%s)(objectclass=user))",
    229212                           r->in.account->string);
    230213        if (ret != 1) {
    231                 ldb_transaction_cancel(sam_ctx);
    232214                /* Don't give the game away:  (don't allow anonymous users to prove the existance of usernames) */
    233215                return NT_STATUS_WRONG_PASSWORD;
     
    239221                                        res[0], &lm_pwd, NULL);
    240222        if (!NT_STATUS_IS_OK(status) || !lm_pwd) {
    241                 ldb_transaction_cancel(sam_ctx);
    242223                return NT_STATUS_WRONG_PASSWORD;
    243224        }
    244225
    245226        /* decrypt the password we have been given */
    246         lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash)); 
     227        lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash));
    247228        arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);
    248229        data_blob_free(&lm_pwd_blob);
    249        
     230
    250231        if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
    251                 ldb_transaction_cancel(sam_ctx);
    252232                DEBUG(3,("samr: failed to decode password buffer\n"));
    253233                return NT_STATUS_WRONG_PASSWORD;
    254234        }
    255                
    256         if (!convert_string_talloc_convenience(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
    257                                   CH_DOS, CH_UNIX, 
    258                                   (const char *)new_password.data, 
     235
     236        if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
     237                                  CH_DOS, CH_UNIX,
     238                                  (const char *)new_password.data,
    259239                                  new_password.length,
    260240                                  (void **)&new_pass, NULL, false)) {
    261241                DEBUG(3,("samr: failed to convert incoming password buffer to unix charset\n"));
    262                 ldb_transaction_cancel(sam_ctx);
    263                 return NT_STATUS_WRONG_PASSWORD;
    264         }
    265 
    266         if (!convert_string_talloc_convenience(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
    267                                                CH_DOS, CH_UTF16,
    268                                                (const char *)new_password.data,
     242                return NT_STATUS_WRONG_PASSWORD;
     243        }
     244
     245        if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
     246                                               CH_DOS, CH_UTF16,
     247                                               (const char *)new_password.data,
    269248                                               new_password.length,
    270249                                               (void **)&new_unicode_password.data, &unicode_pw_len, false)) {
    271250                DEBUG(3,("samr: failed to convert incoming password buffer to UTF16 charset\n"));
    272                 ldb_transaction_cancel(sam_ctx);
    273251                return NT_STATUS_WRONG_PASSWORD;
    274252        }
     
    278256        E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);
    279257        if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {
    280                 ldb_transaction_cancel(sam_ctx);
    281                 return NT_STATUS_WRONG_PASSWORD;
    282         }
    283 
    284         mod = ldb_msg_new(mem_ctx);
    285         if (mod == NULL) {
    286                 ldb_transaction_cancel(sam_ctx);
    287                 return NT_STATUS_NO_MEMORY;
    288         }
    289 
    290         mod->dn = ldb_dn_copy(mod, user_dn);
    291         if (!mod->dn) {
    292                 ldb_transaction_cancel(sam_ctx);
    293                 return NT_STATUS_NO_MEMORY;
    294         }
    295 
    296         /* set the password on the user DN specified.  This may fail
    297          * due to password policies */
     258                return NT_STATUS_WRONG_PASSWORD;
     259        }
     260
     261        /* Connect to a SAMDB with user privileges for the password change */
     262        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
     263                                dce_call->conn->dce_ctx->lp_ctx,
     264                                dce_call->conn->auth_state.session_info, 0);
     265        if (sam_ctx == NULL) {
     266                return NT_STATUS_INVALID_SYSTEM_SERVICE;
     267        }
     268
     269        /* Start transaction */
     270        ret = ldb_transaction_start(sam_ctx);
     271        if (ret != LDB_SUCCESS) {
     272                DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
     273                return NT_STATUS_TRANSACTION_ABORTED;
     274        }
     275
     276        /* Performs the password modification. We pass the old hashes read out
     277         * from the database since they were already checked against the user-
     278         * provided ones. */
    298279        status = samdb_set_password(sam_ctx, mem_ctx,
    299                                     user_dn, NULL, 
    300                                     mod, &new_unicode_password,
     280                                    user_dn, NULL,
     281                                    &new_unicode_password,
    301282                                    NULL, NULL,
    302                                     true, /* this is a user password change */
    303                                     NULL, 
     283                                    lm_pwd, NULL, /* this is a user password change */
     284                                    NULL,
    304285                                    NULL);
    305286        if (!NT_STATUS_IS_OK(status)) {
     
    308289        }
    309290
    310         /* The above call only setup the modifications, this actually
    311          * makes the write to the database. */
    312         ret = samdb_replace(sam_ctx, mem_ctx, mod);
    313         if (ret != 0) {
    314                 DEBUG(2,("Failed to modify record to change password on %s: %s\n",
    315                          ldb_dn_get_linearized(user_dn),
    316                          ldb_errstring(sam_ctx)));
    317                 ldb_transaction_cancel(sam_ctx);
    318                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    319         }
    320 
    321291        /* And this confirms it in a transaction commit */
    322292        ret = ldb_transaction_commit(sam_ctx);
    323         if (ret != 0) {
     293        if (ret != LDB_SUCCESS) {
    324294                DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
    325295                         ldb_dn_get_linearized(user_dn),
     
    332302
    333303
    334 /* 
    335   samr_ChangePasswordUser3 
    336 */
    337 NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, 
    338                                   TALLOC_CTX *mem_ctx,
    339                                   struct samr_ChangePasswordUser3 *r)
    340 {       
     304/*
     305  samr_ChangePasswordUser3
     306*/
     307NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
     308                                        TALLOC_CTX *mem_ctx,
     309                                        struct samr_ChangePasswordUser3 *r)
     310{
    341311        NTSTATUS status;
    342312        DATA_BLOB new_password;
     
    344314        struct ldb_dn *user_dn;
    345315        int ret;
    346         struct ldb_message **res, *mod;
     316        struct ldb_message **res;
    347317        const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL };
    348318        struct samr_Password *nt_pwd, *lm_pwd;
    349319        DATA_BLOB nt_pwd_blob;
    350320        struct samr_DomInfo1 *dominfo = NULL;
    351         struct samr_ChangeReject *reject = NULL;
    352         enum samr_RejectReason reason = SAMR_REJECT_OTHER;
     321        struct userPwdChangeFailureInformation *reject = NULL;
     322        enum samPwdChangeReason reason = SAM_PWD_CHANGE_NO_ERROR;
    353323        uint8_t new_nt_hash[16], new_lm_hash[16];
    354324        struct samr_Password nt_verifier, lm_verifier;
     
    362332        }
    363333
    364         /* To change a password we need to open as system */
    365         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
     334        /* Connect to a SAMDB with system privileges for fetching the old pw
     335         * hashes. */
     336        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
     337                                dce_call->conn->dce_ctx->lp_ctx,
     338                                system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
    366339        if (sam_ctx == NULL) {
    367340                return NT_STATUS_INVALID_SYSTEM_SERVICE;
    368         }
    369 
    370         ret = ldb_transaction_start(sam_ctx);
    371         if (ret) {
    372                 talloc_free(sam_ctx);
    373                 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
    374                 return NT_STATUS_TRANSACTION_ABORTED;
    375341        }
    376342
     
    378344           user SID). We also need the current lm and nt password hashes
    379345           in order to decrypt the incoming passwords */
    380         ret = gendb_search(sam_ctx, 
     346        ret = gendb_search(sam_ctx,
    381347                           mem_ctx, NULL, &res, attrs,
    382348                           "(&(sAMAccountName=%s)(objectclass=user))",
     
    390356        user_dn = res[0]->dn;
    391357
    392         status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx, 
     358        status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
    393359                                        res[0], &lm_pwd, &nt_pwd);
    394360        if (!NT_STATUS_IS_OK(status) ) {
     
    407373
    408374        if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) {
    409                 ldb_transaction_cancel(sam_ctx);
    410375                DEBUG(3,("samr: failed to decode password buffer\n"));
    411                 return NT_STATUS_WRONG_PASSWORD;
    412         }
    413                
     376                status =  NT_STATUS_WRONG_PASSWORD;
     377                goto failed;
     378        }
     379
    414380        if (r->in.nt_verifier == NULL) {
    415381                status = NT_STATUS_WRONG_PASSWORD;
     
    431397        if (lm_pwd && r->in.lm_verifier != NULL) {
    432398                char *new_pass;
    433                 if (!convert_string_talloc_convenience(mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
    434                                           CH_UTF16, CH_UNIX, 
    435                                           (const char *)new_password.data, 
     399                if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
     400                                          CH_UTF16, CH_UNIX,
     401                                          (const char *)new_password.data,
    436402                                          new_password.length,
    437403                                          (void **)&new_pass, NULL, false)) {
     
    445411        }
    446412
    447         mod = ldb_msg_new(mem_ctx);
    448         if (mod == NULL) {
    449                 status = NT_STATUS_NO_MEMORY;
    450                 goto failed;
    451         }
    452 
    453         mod->dn = ldb_dn_copy(mod, user_dn);
    454         if (!mod->dn) {
    455                 status = NT_STATUS_NO_MEMORY;
    456                 goto failed;
    457         }
    458 
    459         /* set the password on the user DN specified.  This may fail
    460          * due to password policies */
     413        /* Connect to a SAMDB with user privileges for the password change */
     414        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
     415                                dce_call->conn->dce_ctx->lp_ctx,
     416                                dce_call->conn->auth_state.session_info, 0);
     417        if (sam_ctx == NULL) {
     418                return NT_STATUS_INVALID_SYSTEM_SERVICE;
     419        }
     420
     421        ret = ldb_transaction_start(sam_ctx);
     422        if (ret != LDB_SUCCESS) {
     423                DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
     424                return NT_STATUS_TRANSACTION_ABORTED;
     425        }
     426
     427        /* Performs the password modification. We pass the old hashes read out
     428         * from the database since they were already checked against the user-
     429         * provided ones. */
    461430        status = samdb_set_password(sam_ctx, mem_ctx,
    462                                     user_dn, NULL, 
    463                                     mod, &new_password,
     431                                    user_dn, NULL,
     432                                    &new_password,
    464433                                    NULL, NULL,
    465                                     true, /* this is a user password change */
    466                                     &reason, 
     434                                    lm_pwd, nt_pwd, /* this is a user password change */
     435                                    &reason,
    467436                                    &dominfo);
     437
    468438        if (!NT_STATUS_IS_OK(status)) {
    469                 goto failed;
    470         }
    471 
    472         /* The above call only setup the modifications, this actually
    473          * makes the write to the database. */
    474         ret = samdb_replace(sam_ctx, mem_ctx, mod);
    475         if (ret != 0) {
    476                 DEBUG(2,("samdb_replace failed to change password for %s: %s\n",
    477                          ldb_dn_get_linearized(user_dn),
    478                          ldb_errstring(sam_ctx)));
    479                 status = NT_STATUS_UNSUCCESSFUL;
     439                ldb_transaction_cancel(sam_ctx);
    480440                goto failed;
    481441        }
     
    483443        /* And this confirms it in a transaction commit */
    484444        ret = ldb_transaction_commit(sam_ctx);
    485         if (ret != 0) {
     445        if (ret != LDB_SUCCESS) {
    486446                DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
    487447                         ldb_dn_get_linearized(user_dn),
     
    494454
    495455failed:
    496         ldb_transaction_cancel(sam_ctx);
    497         talloc_free(sam_ctx);
    498 
    499         reject = talloc(mem_ctx, struct samr_ChangeReject);
     456        reject = talloc_zero(mem_ctx, struct userPwdChangeFailureInformation);
     457        if (reject != NULL) {
     458                reject->extendedFailureReason = reason;
     459
     460                *r->out.reject = reject;
     461        }
     462
    500463        *r->out.dominfo = dominfo;
    501         *r->out.reject = reject;
    502 
    503         if (reject == NULL) {
    504                 return status;
    505         }
    506         ZERO_STRUCTP(reject);
    507 
    508         reject->reason = reason;
    509464
    510465        return status;
     
    512467
    513468
    514 /* 
    515   samr_ChangePasswordUser2 
     469/*
     470  samr_ChangePasswordUser2
    516471
    517472  easy - just a subset of samr_ChangePasswordUser3
    518473*/
    519 NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    520                                   struct samr_ChangePasswordUser2 *r)
     474NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call,
     475                                         TALLOC_CTX *mem_ctx,
     476                                         struct samr_ChangePasswordUser2 *r)
    521477{
    522478        struct samr_ChangePasswordUser3 r2;
    523479        struct samr_DomInfo1 *dominfo = NULL;
    524         struct samr_ChangeReject *reject = NULL;
     480        struct userPwdChangeFailureInformation *reject = NULL;
    525481
    526482        r2.in.server = r->in.server;
     
    541497/*
    542498  set password via a samr_CryptPassword buffer
    543   this will in the 'msg' with modify operations that will update the user
    544   password when applied
    545499*/
    546500NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
    547                            void *sam_ctx,
     501                           struct ldb_context *sam_ctx,
    548502                           struct ldb_dn *account_dn, struct ldb_dn *domain_dn,
    549503                           TALLOC_CTX *mem_ctx,
    550                            struct ldb_message *msg,
    551504                           struct samr_CryptPassword *pwbuf)
    552505{
     
    566519                return NT_STATUS_WRONG_PASSWORD;
    567520        }
    568                
     521
    569522        /* set the password - samdb needs to know both the domain and user DNs,
    570523           so the domain password policy can be used */
    571524        return samdb_set_password(sam_ctx, mem_ctx,
    572                                   account_dn, domain_dn, 
    573                                   msg, &new_password,
     525                                  account_dn, domain_dn,
     526                                  &new_password,
    574527                                  NULL, NULL,
    575                                   false, /* This is a password set, not change */
     528                                  NULL, NULL, /* This is a password set, not change */
    576529                                  NULL, NULL);
    577530}
     
    580533/*
    581534  set password via a samr_CryptPasswordEx buffer
    582   this will in the 'msg' with modify operations that will update the user
    583   password when applied
    584535*/
    585536NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
    586537                              struct ldb_context *sam_ctx,
    587                               struct ldb_dn *account_dn, struct ldb_dn *domain_dn,
     538                              struct ldb_dn *account_dn,
     539                              struct ldb_dn *domain_dn,
    588540                              TALLOC_CTX *mem_ctx,
    589                               struct ldb_message *msg,
    590541                              struct samr_CryptPasswordEx *pwbuf)
    591542{
     
    610561        MD5Update(&ctx, session_key.data, session_key.length);
    611562        MD5Final(co_session_key.data, &ctx);
    612        
     563
    613564        arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);
    614565
     
    617568                return NT_STATUS_WRONG_PASSWORD;
    618569        }
    619                
     570
    620571        /* set the password - samdb needs to know both the domain and user DNs,
    621572           so the domain password policy can be used */
    622573        return samdb_set_password(sam_ctx, mem_ctx,
    623                                   account_dn, domain_dn, 
    624                                   msg, &new_password,
     574                                  account_dn, domain_dn,
     575                                  &new_password,
    625576                                  NULL, NULL,
    626                                   false, /* This is a password set, not change */
     577                                  NULL, NULL, /* This is a password set, not change */
    627578                                  NULL, NULL);
    628579}
    629580
    630 
     581/*
     582  set password via encrypted NT and LM hash buffers
     583*/
     584NTSTATUS samr_set_password_buffers(struct dcesrv_call_state *dce_call,
     585                                   struct ldb_context *sam_ctx,
     586                                   struct ldb_dn *account_dn,
     587                                   struct ldb_dn *domain_dn,
     588                                   TALLOC_CTX *mem_ctx,
     589                                   const uint8_t *lm_pwd_hash,
     590                                   const uint8_t *nt_pwd_hash)
     591{
     592        struct samr_Password *d_lm_pwd_hash = NULL, *d_nt_pwd_hash = NULL;
     593        DATA_BLOB session_key = data_blob(NULL, 0);
     594        DATA_BLOB in, out;
     595        NTSTATUS nt_status = NT_STATUS_OK;
     596
     597        nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
     598        if (!NT_STATUS_IS_OK(nt_status)) {
     599                return nt_status;
     600        }
     601
     602        if (lm_pwd_hash != NULL) {
     603                in = data_blob_const(lm_pwd_hash, 16);
     604                out = data_blob_talloc_zero(mem_ctx, 16);
     605
     606                sess_crypt_blob(&out, &in, &session_key, false);
     607
     608                d_lm_pwd_hash = (struct samr_Password *) out.data;
     609        }
     610        if (nt_pwd_hash != NULL) {
     611                in = data_blob_const(nt_pwd_hash, 16);
     612                out = data_blob_talloc_zero(mem_ctx, 16);
     613
     614                sess_crypt_blob(&out, &in, &session_key, false);
     615
     616                d_nt_pwd_hash = (struct samr_Password *) out.data;
     617        }
     618
     619        if ((d_lm_pwd_hash != NULL) || (d_nt_pwd_hash != NULL)) {
     620                nt_status = samdb_set_password(sam_ctx, mem_ctx, account_dn,
     621                                               domain_dn, NULL,
     622                                               d_lm_pwd_hash, d_nt_pwd_hash,
     623                                               NULL, NULL, /* this is a password set */
     624                                               NULL, NULL);
     625        }
     626
     627        return nt_status;
     628}
Note: See TracChangeset for help on using the changeset viewer.