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:
1 deleted
33 edited
8 copied

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source4/rpc_server/browser/dcesrv_browser.c

    r414 r745  
    7373                return WERR_UNKNOWN_LEVEL;
    7474        }
    75 
    76         return WERR_INVALID_PARAM;
    7775}
    7876
  • trunk/server/source4/rpc_server/common/common.h

    r414 r745  
    2525
    2626struct share_config;
     27struct dcesrv_connection;
    2728struct dcesrv_context;
    2829struct dcesrv_context;
     30struct dcesrv_call_state;
     31struct ndr_interface_table;
     32struct ncacn_packet;
    2933
    3034struct dcerpc_server_info {
     
    3539};
    3640
    37 struct ndr_interface_table;
    38 struct dcesrv_call_state;
    3941#include "rpc_server/common/proto.h"
    4042
  • trunk/server/source4/rpc_server/common/forward.c

    r414 r745  
    2121
    2222#include "includes.h"
     23#include <tevent.h>
    2324#include "rpc_server/dcerpc_server.h"
     25#include "librpc/gen_ndr/dcerpc.h"
     26#include "rpc_server/common/common.h"
    2427#include "messaging/irpc.h"
     28#include "auth/auth.h"
     29
    2530
    2631struct dcesrv_forward_state {
     
    3237  called when the forwarded rpc request is finished
    3338 */
    34 static void dcesrv_irpc_forward_callback(struct irpc_request *ireq)
     39static void dcesrv_irpc_forward_callback(struct tevent_req *subreq)
    3540{
    36         struct dcesrv_forward_state *st = talloc_get_type(ireq->async.private_data,
    37                                                           struct dcesrv_forward_state);
     41        struct dcesrv_forward_state *st =
     42                tevent_req_callback_data(subreq,
     43                struct dcesrv_forward_state);
    3844        const char *opname = st->opname;
    3945        NTSTATUS status;
    40         if (!NT_STATUS_IS_OK(ireq->status)) {
     46
     47        status = dcerpc_binding_handle_call_recv(subreq);
     48        TALLOC_FREE(subreq);
     49        if (!NT_STATUS_IS_OK(status)) {
    4150                DEBUG(0,("IRPC callback failed for %s - %s\n",
    42                          opname, nt_errstr(ireq->status)));
     51                         opname, nt_errstr(status)));
    4352                st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
    4453        }
    45         talloc_free(ireq);
    4654        status = dcesrv_reply(st->dce_call);
    4755        if (!NT_STATUS_IS_OK(status)) {
     
    5361
    5462
    55 /*
    56   forward a RPC call using IRPC to another task
     63/**
     64 * Forward a RPC call using IRPC to another task
    5765 */
    5866void dcesrv_irpc_forward_rpc_call(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    5967                                  void *r, uint32_t callid,
    6068                                  const struct ndr_interface_table *ndr_table,
    61                                   const char *dest_task, const char *opname)
     69                                  const char *dest_task, const char *opname,
     70                                  uint32_t timeout)
    6271{
    63         struct server_id *sid;
    64         struct irpc_request *ireq;
    6572        struct dcesrv_forward_state *st;
     73        struct dcerpc_binding_handle *binding_handle;
     74        struct tevent_req *subreq;
     75        struct security_token *token;
    6676
    6777        st = talloc(mem_ctx, struct dcesrv_forward_state);
     
    8393        }
    8494
    85         /* find the server task */
    86         sid = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, dest_task);
    87         if (sid == NULL || sid[0].id == 0) {
    88                 DEBUG(0,("%s: Unable to find %s task\n", dest_task, opname));
     95        binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
     96                                                     dest_task, ndr_table);
     97        if (binding_handle == NULL) {
     98                DEBUG(0,("%s: Failed to forward request to %s task\n",
     99                         opname, dest_task));
    89100                dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
    90101                return;
    91102        }
    92103
     104        /* reset timeout for the handle */
     105        dcerpc_binding_handle_set_timeout(binding_handle, timeout);
     106
     107        /* add security token to the handle*/
     108        token = dce_call->conn->auth_state.session_info->security_token;
     109        irpc_binding_handle_add_security_token(binding_handle, token);
     110
    93111        /* forward the call */
    94         ireq = irpc_call_send(dce_call->msg_ctx, sid[0], ndr_table, callid, r, mem_ctx);
    95         if (ireq == NULL) {
     112        subreq = dcerpc_binding_handle_call_send(st, dce_call->event_ctx,
     113                                                 binding_handle,
     114                                                 NULL, ndr_table,
     115                                                 callid,
     116                                                 dce_call, r);
     117        if (subreq == NULL) {
    96118                DEBUG(0,("%s: Failed to forward request to %s task\n",
    97119                         opname, dest_task));
     
    104126
    105127        /* setup the callback */
    106         ireq->async.fn = dcesrv_irpc_forward_callback;
    107         ireq->async.private_data = st;
     128        tevent_req_set_callback(subreq, dcesrv_irpc_forward_callback, st);
    108129}
  • trunk/server/source4/rpc_server/common/server_info.c

    r414 r745  
    2121
    2222#include "includes.h"
    23 #include "librpc/gen_ndr/ndr_srvsvc.h"
     23#include "librpc/gen_ndr/srvsvc.h"
    2424#include "rpc_server/dcerpc_server.h"
    2525#include "dsdb/samdb/samdb.h"
    2626#include "auth/auth.h"
    2727#include "param/param.h"
    28 #include "rpc_server/common/common.h"
    2928
    3029/*
     
    3736        enum srvsvc_PlatformId id;
    3837
    39         id = lp_parm_int(dce_ctx->lp_ctx, NULL, "server_info", "platform_id", PLATFORM_ID_NT);
     38        id = lpcfg_parm_int(dce_ctx->lp_ctx, NULL, "server_info", "platform_id", PLATFORM_ID_NT);
    4039
    4140        return id;
     
    4847        /* if there's no string return our NETBIOS name */
    4948        if (!p) {
    50                 return talloc_strdup(mem_ctx, lp_netbios_name(dce_ctx->lp_ctx));
     49                return talloc_strdup(mem_ctx, lpcfg_netbios_name(dce_ctx->lp_ctx));
    5150        }
    5251
     
    6867        default_server_announce |= SV_TYPE_SERVER_UNIX;
    6968
    70         switch (lp_announce_as(dce_ctx->lp_ctx)) {
     69        switch (lpcfg_announce_as(dce_ctx->lp_ctx)) {
    7170                case ANNOUNCE_AS_NT_SERVER:
    7271                        default_server_announce |= SV_TYPE_SERVER_NT;
     
    8584        }
    8685
    87         switch (lp_server_role(dce_ctx->lp_ctx)) {
     86        switch (lpcfg_server_role(dce_ctx->lp_ctx)) {
    8887                case ROLE_DOMAIN_MEMBER:
    8988                        default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
     
    9796                        }
    9897                        /* open main ldb */
    99                         samctx = samdb_connect(tmp_ctx, event_ctx, dce_ctx->lp_ctx, anonymous_session(tmp_ctx, event_ctx, dce_ctx->lp_ctx));
     98                        samctx = samdb_connect(tmp_ctx, event_ctx, dce_ctx->lp_ctx, anonymous_session(tmp_ctx, dce_ctx->lp_ctx), 0);
    10099                        if (samctx == NULL) {
    101100                                DEBUG(2,("Unable to open samdb in determining server announce flags\n"));
     
    117116                        break;
    118117        }
    119         if (lp_time_server(dce_ctx->lp_ctx))
     118        if (lpcfg_time_server(dce_ctx->lp_ctx))
    120119                default_server_announce |= SV_TYPE_TIME_SOURCE;
    121120
    122         if (lp_host_msdfs(dce_ctx->lp_ctx))
     121        if (lpcfg_host_msdfs(dce_ctx->lp_ctx))
    123122                default_server_announce |= SV_TYPE_DFS_SERVER;
    124123
  • trunk/server/source4/rpc_server/dcerpc_server.c

    r414 r745  
    2222
    2323#include "includes.h"
    24 #include "librpc/gen_ndr/ndr_dcerpc.h"
    2524#include "auth/auth.h"
    2625#include "auth/gensec/gensec.h"
     
    2827#include "rpc_server/dcerpc_server.h"
    2928#include "rpc_server/dcerpc_server_proto.h"
     29#include "rpc_server/common/proto.h"
    3030#include "librpc/rpc/dcerpc_proto.h"
    31 #include "lib/events/events.h"
    32 #include "smbd/service_task.h"
    33 #include "smbd/service_stream.h"
    34 #include "smbd/service.h"
    3531#include "system/filesys.h"
    3632#include "libcli/security/security.h"
    3733#include "param/param.h"
     34#include "../lib/tsocket/tsocket.h"
     35#include "../libcli/named_pipe_auth/npa_tstream.h"
     36#include "smbd/service_stream.h"
     37#include "../lib/tsocket/tsocket.h"
     38#include "lib/socket/socket.h"
     39#include "smbd/process_model.h"
     40#include "lib/messaging/irpc.h"
     41#include "librpc/rpc/rpc_common.h"
    3842
    3943/* this is only used when the client asks for an unknown interface */
     
    337341}
    338342
    339 NTSTATUS dcesrv_generic_session_key(struct dcesrv_connection *p,
    340                                     DATA_BLOB *session_key)
    341 {
    342         /* this took quite a few CPU cycles to find ... */
    343         session_key->data = discard_const_p(uint8_t, "SystemLibraryDTC");
    344         session_key->length = 16;
    345         return NT_STATUS_OK;
    346 }
    347 
    348343/*
    349344  fetch the user session key - may be default (above) or the SMB session key
     
    395390        p->contexts = NULL;
    396391        p->call_list = NULL;
    397         p->packet_log_dir = lp_lockdir(dce_ctx->lp_ctx);
     392        p->packet_log_dir = lpcfg_lockdir(dce_ctx->lp_ctx);
    398393        p->incoming_fragmented_call_list = NULL;
    399394        p->pending_call_list = NULL;
     
    415410}
    416411
    417 static void dcesrv_init_hdr(struct ncacn_packet *pkt, bool bigendian)
    418 {
    419         pkt->rpc_vers = 5;
    420         pkt->rpc_vers_minor = 0;
    421         if (bigendian) {
    422                 pkt->drep[0] = 0;
    423         } else {
    424                 pkt->drep[0] = DCERPC_DREP_LE;
    425         }
    426         pkt->drep[1] = 0;
    427         pkt->drep[2] = 0;
    428         pkt->drep[3] = 0;
    429 }
    430 
    431412/*
    432413  move a call from an existing linked list to the specified list. This
     
    466447}
    467448
    468 /*
    469   return a dcerpc fault
    470 */
    471 static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code)
    472 {
    473         struct ncacn_packet pkt;
    474         struct data_blob_list_item *rep;
    475         uint8_t zeros[4];
    476         NTSTATUS status;
    477 
    478         /* setup a bind_ack */
    479         dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
    480         pkt.auth_length = 0;
    481         pkt.call_id = call->pkt.call_id;
    482         pkt.ptype = DCERPC_PKT_FAULT;
    483         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
    484         pkt.u.fault.alloc_hint = 0;
    485         pkt.u.fault.context_id = 0;
    486         pkt.u.fault.cancel_count = 0;
    487         pkt.u.fault.status = fault_code;
    488 
    489         ZERO_STRUCT(zeros);
    490         pkt.u.fault._pad = data_blob_const(zeros, sizeof(zeros));
    491 
    492         rep = talloc(call, struct data_blob_list_item);
    493         if (!rep) {
    494                 return NT_STATUS_NO_MEMORY;
    495         }
    496 
    497         status = ncacn_push_auth(&rep->blob, call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx), &pkt, NULL);
    498         if (!NT_STATUS_IS_OK(status)) {
    499                 return status;
    500         }
    501 
    502         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
    503 
    504         DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
    505         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
    506 
    507         if (call->conn->call_list && call->conn->call_list->replies) {
    508                 if (call->conn->transport.report_output_data) {
    509                         call->conn->transport.report_output_data(call->conn);
    510                 }
    511         }
    512 
    513         return NT_STATUS_OK;   
    514 }
    515 
    516449
    517450/*
     
    525458
    526459        /* setup a bind_nak */
    527         dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
     460        dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
    528461        pkt.auth_length = 0;
    529462        pkt.call_id = call->pkt.call_id;
     
    540473        }
    541474
    542         status = ncacn_push_auth(&rep->blob, call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx), &pkt, NULL);
     475        status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
    543476        if (!NT_STATUS_IS_OK(status)) {
    544477                return status;
     
    563496        DLIST_REMOVE(c->conn->contexts, c);
    564497
    565         if (c->iface) {
     498        if (c->iface && c->iface->unbind) {
    566499                c->iface->unbind(c, c->iface);
    567500        }
     
    589522         */
    590523        if (call->pkt.u.bind.assoc_group_id != 0 &&
    591             lp_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
     524            lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
    592525            dcesrv_assoc_group_find(call->conn->dce_ctx, call->pkt.u.bind.assoc_group_id) == NULL) {
    593526                return dcesrv_bind_nak(call, 0);       
     
    657590                talloc_set_destructor(context, dcesrv_connection_context_destructor);
    658591
    659                 status = iface->bind(call, iface);
     592                status = iface->bind(call, iface, if_version);
    660593                if (!NT_STATUS_IS_OK(status)) {
    661594                        char *uuid_str = GUID_string(call, &uuid);
     
    676609
    677610        if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) &&
    678             lp_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","header signing", false)) {
     611            lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","header signing", false)) {
    679612                call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_HEADER_SIGNING;
    680613                extra_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
     
    689622
    690623        /* setup a bind_ack */
    691         dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
     624        dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
    692625        pkt.auth_length = 0;
    693626        pkt.call_id = call->pkt.call_id;
     
    741674        }
    742675
    743         status = ncacn_push_auth(&rep->blob, call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx), &pkt, call->conn->auth_state.auth_info);
     676        status = ncacn_push_auth(&rep->blob, call, &pkt,
     677                                                         call->conn->auth_state.auth_info);
    744678        if (!NT_STATUS_IS_OK(status)) {
    745679                talloc_free(call->context);
     
    836770        talloc_set_destructor(context, dcesrv_connection_context_destructor);
    837771
    838         status = iface->bind(call, iface);
     772        status = iface->bind(call, iface, if_version);
    839773        if (!NT_STATUS_IS_OK(status)) {
    840774                /* we don't want to trigger the iface->unbind() hook */
     
    883817        if (result == 0 &&
    884818            call->pkt.u.alter.assoc_group_id != 0 &&
    885             lp_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
     819            lpcfg_parm_bool(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv","assoc group checking", true) &&
    886820            call->pkt.u.alter.assoc_group_id != call->context->assoc_group->id) {
    887821                DEBUG(0,(__location__ ": Failed attempt to use new assoc_group in alter context (0x%08x 0x%08x)\n",
     
    893827
    894828        /* setup a alter_resp */
    895         dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
     829        dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
    896830        pkt.auth_length = 0;
    897831        pkt.call_id = call->pkt.call_id;
     
    932866        }
    933867
    934         status = ncacn_push_auth(&rep->blob, call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx), &pkt, call->conn->auth_state.auth_info);
     868        status = ncacn_push_auth(&rep->blob, call, &pkt, call->conn->auth_state.auth_info);
    935869        if (!NT_STATUS_IS_OK(status)) {
    936870                return status;
     
    949883
    950884        return NT_STATUS_OK;
     885}
     886
     887/*
     888  possibly save the call for inspection with ndrdump
     889 */
     890static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
     891{
     892#ifdef DEVELOPER
     893        char *fname;
     894        const char *dump_dir;
     895        dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx, NULL, "dcesrv", "stubs directory");
     896        if (!dump_dir) {
     897                return;
     898        }
     899        fname = talloc_asprintf(call, "%s/RPC-%s-%u-%s.dat",
     900                                dump_dir,
     901                                call->context->iface->name,
     902                                call->pkt.u.request.opnum,
     903                                why);
     904        if (file_save(fname, call->pkt.u.request.stub_and_verifier.data, call->pkt.u.request.stub_and_verifier.length)) {
     905                DEBUG(0,("RPC SAVED %s\n", fname));
     906        }
     907        talloc_free(fname);
     908#endif
    951909}
    952910
     
    971929        }
    972930
    973         pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call,
    974                                   lp_iconv_convenience(call->conn->dce_ctx->lp_ctx));
     931        pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
    975932        NT_STATUS_HAVE_NO_MEMORY(pull);
    976933
     
    987944        status = context->iface->ndr_pull(call, call, pull, &call->r);
    988945        if (!NT_STATUS_IS_OK(status)) {
     946                if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
     947                        /* we got an unknown call */
     948                        DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
     949                                 call->pkt.u.request.opnum, context->iface->name));
     950                        dcesrv_save_call(call, "unknown");
     951                } else {
     952                        dcesrv_save_call(call, "pullfail");
     953                }
    989954                return dcesrv_fault(call, call->fault_code);
    990955        }
    991956
    992957        if (pull->offset != pull->data_size) {
     958                dcesrv_save_call(call, "extrabytes");
    993959                DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
    994960                         pull->data_size - pull->offset));
    995                 dump_data(10, pull->data+pull->offset, pull->data_size - pull->offset);
    996961        }
    997962
     
    1016981}
    1017982
    1018 _PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
    1019 {
    1020         struct ndr_push *push;
    1021         NTSTATUS status;
    1022         DATA_BLOB stub;
    1023         uint32_t total_length, chunk_size;
    1024         struct dcesrv_connection_context *context = call->context;
    1025         size_t sig_size = 0;
    1026 
    1027         /* call the reply function */
    1028         status = context->iface->reply(call, call, call->r);
    1029         if (!NT_STATUS_IS_OK(status)) {
    1030                 return dcesrv_fault(call, call->fault_code);
    1031         }
    1032 
    1033         /* form the reply NDR */
    1034         push = ndr_push_init_ctx(call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx));
    1035         NT_STATUS_HAVE_NO_MEMORY(push);
    1036 
    1037         /* carry over the pointer count to the reply in case we are
    1038            using full pointer. See NDR specification for full
    1039            pointers */
    1040         push->ptr_count = call->ndr_pull->ptr_count;
    1041 
    1042         if (lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx)) {
    1043                 push->flags |= LIBNDR_FLAG_BIGENDIAN;
    1044         }
    1045 
    1046         status = context->iface->ndr_push(call, call, push, call->r);
    1047         if (!NT_STATUS_IS_OK(status)) {
    1048                 return dcesrv_fault(call, call->fault_code);
    1049         }
    1050 
    1051         stub = ndr_push_blob(push);
    1052 
    1053         total_length = stub.length;
    1054 
    1055         /* we can write a full max_recv_frag size, minus the dcerpc
    1056            request header size */
    1057         chunk_size = call->conn->cli_max_recv_frag;
    1058         chunk_size -= DCERPC_REQUEST_LENGTH;
    1059         if (call->conn->auth_state.auth_info &&
    1060             call->conn->auth_state.gensec_security) {
    1061                 sig_size = gensec_sig_size(call->conn->auth_state.gensec_security,
    1062                                            call->conn->cli_max_recv_frag);
    1063                 if (sig_size) {
    1064                         chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
    1065                         chunk_size -= sig_size;
    1066                 }
    1067         }
    1068         chunk_size -= (chunk_size % 16);
    1069 
    1070         do {
    1071                 uint32_t length;
    1072                 struct data_blob_list_item *rep;
    1073                 struct ncacn_packet pkt;
    1074 
    1075                 rep = talloc(call, struct data_blob_list_item);
    1076                 NT_STATUS_HAVE_NO_MEMORY(rep);
    1077 
    1078                 length = MIN(chunk_size, stub.length);
    1079 
    1080                 /* form the dcerpc response packet */
    1081                 dcesrv_init_hdr(&pkt, lp_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
    1082                 pkt.auth_length = 0;
    1083                 pkt.call_id = call->pkt.call_id;
    1084                 pkt.ptype = DCERPC_PKT_RESPONSE;
    1085                 pkt.pfc_flags = 0;
    1086                 if (stub.length == total_length) {
    1087                         pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
    1088                 }
    1089                 if (length == stub.length) {
    1090                         pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
    1091                 }
    1092                 pkt.u.response.alloc_hint = stub.length;
    1093                 pkt.u.response.context_id = call->pkt.u.request.context_id;
    1094                 pkt.u.response.cancel_count = 0;
    1095                 pkt.u.response.stub_and_verifier.data = stub.data;
    1096                 pkt.u.response.stub_and_verifier.length = length;
    1097 
    1098                 if (!dcesrv_auth_response(call, &rep->blob, sig_size, &pkt)) {
    1099                         return dcesrv_fault(call, DCERPC_FAULT_OTHER);         
    1100                 }
    1101 
    1102                 dcerpc_set_frag_length(&rep->blob, rep->blob.length);
    1103 
    1104                 DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
    1105                
    1106                 stub.data += length;
    1107                 stub.length -= length;
    1108         } while (stub.length != 0);
    1109 
    1110         /* move the call from the pending to the finished calls list */
    1111         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
    1112 
    1113         if (call->conn->call_list && call->conn->call_list->replies) {
    1114                 if (call->conn->transport.report_output_data) {
    1115                         call->conn->transport.report_output_data(call->conn);
    1116                 }
    1117         }
    1118 
    1119         return NT_STATUS_OK;
    1120 }
    1121 
    1122 _PUBLIC_ struct socket_address *dcesrv_connection_get_my_addr(struct dcesrv_connection *conn, TALLOC_CTX *mem_ctx)
    1123 {
    1124         if (!conn->transport.get_my_addr) {
    1125                 return NULL;
    1126         }
    1127 
    1128         return conn->transport.get_my_addr(conn, mem_ctx);
    1129 }
    1130 
    1131 _PUBLIC_ struct socket_address *dcesrv_connection_get_peer_addr(struct dcesrv_connection *conn, TALLOC_CTX *mem_ctx)
    1132 {
    1133         if (!conn->transport.get_peer_addr) {
    1134                 return NULL;
    1135         }
    1136 
    1137         return conn->transport.get_peer_addr(conn, mem_ctx);
    1138 }
    1139 
    1140983
    1141984/*
     
    1146989        dcesrv_call_set_list(call, DCESRV_LIST_NONE);
    1147990        return 0;
     991}
     992
     993_PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
     994{
     995        return conn->local_address;
     996}
     997
     998_PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
     999{
     1000        return conn->remote_address;
    11481001}
    11491002
     
    11951048                }
    11961049
    1197                 /* this is a continuation of an existing call - find the call then
    1198                    tack it on the end */
     1050                /* this is a continuation of an existing call - find the call
     1051                   then tack it on the end */
    11991052                call = dcesrv_find_fragmented_call(dce_conn, call2->pkt.call_id);
    12001053                if (!call) {
     
    13731226{
    13741227        static bool initialized;
    1375         extern NTSTATUS dcerpc_server_wkssvc_init(void);
    1376         extern NTSTATUS dcerpc_server_drsuapi_init(void);
    1377         extern NTSTATUS dcerpc_server_winreg_init(void);
    1378         extern NTSTATUS dcerpc_server_spoolss_init(void);
    1379         extern NTSTATUS dcerpc_server_epmapper_init(void);
    1380         extern NTSTATUS dcerpc_server_srvsvc_init(void);
    1381         extern NTSTATUS dcerpc_server_netlogon_init(void);
    1382         extern NTSTATUS dcerpc_server_rpcecho_init(void);
    1383         extern NTSTATUS dcerpc_server_unixinfo_init(void);
    1384         extern NTSTATUS dcerpc_server_samr_init(void);
    1385         extern NTSTATUS dcerpc_server_remote_init(void);
    1386         extern NTSTATUS dcerpc_server_lsa_init(void);
    1387         extern NTSTATUS dcerpc_server_browser_init(void);
     1228#define _MODULE_PROTO(init) extern NTSTATUS init(void);
     1229        STATIC_dcerpc_server_MODULES_PROTO;
    13881230        init_module_fn static_init[] = { STATIC_dcerpc_server_MODULES };
    13891231        init_module_fn *shared_init;
     
    14251267}
    14261268
     1269static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
     1270{
     1271        struct stream_connection *srv_conn;
     1272        srv_conn = talloc_get_type(dce_conn->transport.private_data,
     1273                                   struct stream_connection);
     1274
     1275        stream_terminate_connection(srv_conn, reason);
     1276}
     1277/* We need this include to be able to compile on some plateforms
     1278 * (ie. freebsd 7.2) as it seems that <sys/uio.h> is not included
     1279 * correctly.
     1280 * It has to be that deep because otherwise we have a conflict on
     1281 * const struct dcesrv_interface declaration.
     1282 * This is mostly due to socket_wrapper defining #define bind swrap_bind
     1283 * which conflict with the bind used before.
     1284 */
     1285#include "system/network.h"
     1286
     1287struct dcesrv_sock_reply_state {
     1288        struct dcesrv_connection *dce_conn;
     1289        struct dcesrv_call_state *call;
     1290        struct iovec iov;
     1291};
     1292
     1293static void dcesrv_sock_reply_done(struct tevent_req *subreq);
     1294
     1295static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
     1296{
     1297        struct dcesrv_call_state *call;
     1298
     1299        call = dce_conn->call_list;
     1300        if (!call || !call->replies) {
     1301                return;
     1302        }
     1303
     1304        while (call->replies) {
     1305                struct data_blob_list_item *rep = call->replies;
     1306                struct dcesrv_sock_reply_state *substate;
     1307                struct tevent_req *subreq;
     1308
     1309                substate = talloc(call, struct dcesrv_sock_reply_state);
     1310                if (!substate) {
     1311                        dcesrv_terminate_connection(dce_conn, "no memory");
     1312                        return;
     1313                }
     1314
     1315                substate->dce_conn = dce_conn;
     1316                substate->call = NULL;
     1317
     1318                DLIST_REMOVE(call->replies, rep);
     1319
     1320                if (call->replies == NULL) {
     1321                        substate->call = call;
     1322                }
     1323
     1324                substate->iov.iov_base = (void *) rep->blob.data;
     1325                substate->iov.iov_len = rep->blob.length;
     1326
     1327                subreq = tstream_writev_queue_send(substate,
     1328                                                   dce_conn->event_ctx,
     1329                                                   dce_conn->stream,
     1330                                                   dce_conn->send_queue,
     1331                                                   &substate->iov, 1);
     1332                if (!subreq) {
     1333                        dcesrv_terminate_connection(dce_conn, "no memory");
     1334                        return;
     1335                }
     1336                tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
     1337                                        substate);
     1338        }
     1339
     1340        DLIST_REMOVE(call->conn->call_list, call);
     1341        call->list = DCESRV_LIST_NONE;
     1342}
     1343
     1344static void dcesrv_sock_reply_done(struct tevent_req *subreq)
     1345{
     1346        struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
     1347                                                struct dcesrv_sock_reply_state);
     1348        int ret;
     1349        int sys_errno;
     1350        NTSTATUS status;
     1351        struct dcesrv_call_state *call = substate->call;
     1352
     1353        ret = tstream_writev_queue_recv(subreq, &sys_errno);
     1354        TALLOC_FREE(subreq);
     1355        if (ret == -1) {
     1356                status = map_nt_error_from_unix(sys_errno);
     1357                dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
     1358                return;
     1359        }
     1360
     1361        talloc_free(substate);
     1362        if (call) {
     1363                talloc_free(call);
     1364        }
     1365}
     1366
     1367
     1368
     1369
     1370struct dcesrv_socket_context {
     1371        const struct dcesrv_endpoint *endpoint;
     1372        struct dcesrv_context *dcesrv_ctx;
     1373};
     1374
     1375
     1376static void dcesrv_read_fragment_done(struct tevent_req *subreq);
     1377
     1378static void dcesrv_sock_accept(struct stream_connection *srv_conn)
     1379{
     1380        NTSTATUS status;
     1381        struct dcesrv_socket_context *dcesrv_sock =
     1382                talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
     1383        struct dcesrv_connection *dcesrv_conn = NULL;
     1384        int ret;
     1385        struct tevent_req *subreq;
     1386        struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
     1387
     1388        if (!srv_conn->session_info) {
     1389                status = auth_anonymous_session_info(srv_conn,
     1390                                                     lp_ctx,
     1391                                                     &srv_conn->session_info);
     1392                if (!NT_STATUS_IS_OK(status)) {
     1393                        DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
     1394                                nt_errstr(status)));
     1395                        stream_terminate_connection(srv_conn, nt_errstr(status));
     1396                        return;
     1397                }
     1398        }
     1399
     1400        status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
     1401                                         srv_conn,
     1402                                         dcesrv_sock->endpoint,
     1403                                         srv_conn->session_info,
     1404                                         srv_conn->event.ctx,
     1405                                         srv_conn->msg_ctx,
     1406                                         srv_conn->server_id,
     1407                                         DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
     1408                                         &dcesrv_conn);
     1409        if (!NT_STATUS_IS_OK(status)) {
     1410                DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
     1411                        nt_errstr(status)));
     1412                stream_terminate_connection(srv_conn, nt_errstr(status));
     1413                return;
     1414        }
     1415
     1416        dcesrv_conn->transport.private_data             = srv_conn;
     1417        dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
     1418
     1419        TALLOC_FREE(srv_conn->event.fde);
     1420
     1421        dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
     1422        if (!dcesrv_conn->send_queue) {
     1423                status = NT_STATUS_NO_MEMORY;
     1424                DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
     1425                        nt_errstr(status)));
     1426                stream_terminate_connection(srv_conn, nt_errstr(status));
     1427                return;
     1428        }
     1429
     1430        if (dcesrv_sock->endpoint->ep_description->transport == NCACN_NP) {
     1431                dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
     1432                dcesrv_conn->stream = talloc_move(dcesrv_conn,
     1433                                                  &srv_conn->tstream);
     1434        } else {
     1435                ret = tstream_bsd_existing_socket(dcesrv_conn,
     1436                                                  socket_get_fd(srv_conn->socket),
     1437                                                  &dcesrv_conn->stream);
     1438                if (ret == -1) {
     1439                        status = map_nt_error_from_unix(errno);
     1440                        DEBUG(0, ("dcesrv_sock_accept: "
     1441                                  "failed to setup tstream: %s\n",
     1442                                  nt_errstr(status)));
     1443                        stream_terminate_connection(srv_conn, nt_errstr(status));
     1444                        return;
     1445                }
     1446                socket_set_flags(srv_conn->socket, SOCKET_FLAG_NOCLOSE);
     1447        }
     1448
     1449        dcesrv_conn->local_address = srv_conn->local_address;
     1450        dcesrv_conn->remote_address = srv_conn->remote_address;
     1451
     1452        srv_conn->private_data = dcesrv_conn;
     1453
     1454        irpc_add_name(srv_conn->msg_ctx, "rpc_server");
     1455
     1456        subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
     1457                                               dcesrv_conn->event_ctx,
     1458                                               dcesrv_conn->stream);
     1459        if (!subreq) {
     1460                status = NT_STATUS_NO_MEMORY;
     1461                DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
     1462                        nt_errstr(status)));
     1463                stream_terminate_connection(srv_conn, nt_errstr(status));
     1464                return;
     1465        }
     1466        tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
     1467
     1468        return;
     1469}
     1470
     1471static void dcesrv_read_fragment_done(struct tevent_req *subreq)
     1472{
     1473        struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
     1474                                             struct dcesrv_connection);
     1475        struct ncacn_packet *pkt;
     1476        DATA_BLOB buffer;
     1477        NTSTATUS status;
     1478
     1479        status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
     1480                                               &pkt, &buffer);
     1481        TALLOC_FREE(subreq);
     1482        if (!NT_STATUS_IS_OK(status)) {
     1483                dcesrv_terminate_connection(dce_conn, nt_errstr(status));
     1484                return;
     1485        }
     1486
     1487        status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
     1488        if (!NT_STATUS_IS_OK(status)) {
     1489                dcesrv_terminate_connection(dce_conn, nt_errstr(status));
     1490                return;
     1491        }
     1492
     1493        subreq = dcerpc_read_ncacn_packet_send(dce_conn,
     1494                                               dce_conn->event_ctx,
     1495                                               dce_conn->stream);
     1496        if (!subreq) {
     1497                status = NT_STATUS_NO_MEMORY;
     1498                dcesrv_terminate_connection(dce_conn, nt_errstr(status));
     1499                return;
     1500        }
     1501        tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
     1502}
     1503
     1504static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
     1505{
     1506        struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
     1507                                             struct dcesrv_connection);
     1508        dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
     1509}
     1510
     1511static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
     1512{
     1513        struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
     1514                                             struct dcesrv_connection);
     1515        dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
     1516}
     1517
     1518
     1519static const struct stream_server_ops dcesrv_stream_ops = {
     1520        .name                   = "rpc",
     1521        .accept_connection      = dcesrv_sock_accept,
     1522        .recv_handler           = dcesrv_sock_recv,
     1523        .send_handler           = dcesrv_sock_send,
     1524};
     1525
     1526static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
     1527                                   struct loadparm_context *lp_ctx,
     1528                                   struct dcesrv_endpoint *e,
     1529                            struct tevent_context *event_ctx, const struct model_ops *model_ops)
     1530{
     1531        struct dcesrv_socket_context *dcesrv_sock;
     1532        uint16_t port = 1;
     1533        NTSTATUS status;
     1534
     1535        dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
     1536        NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
     1537
     1538        /* remember the endpoint of this socket */
     1539        dcesrv_sock->endpoint           = e;
     1540        dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
     1541
     1542        status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
     1543                                     model_ops, &dcesrv_stream_ops,
     1544                                     "unix", e->ep_description->endpoint, &port,
     1545                                     lpcfg_socket_options(lp_ctx),
     1546                                     dcesrv_sock);
     1547        if (!NT_STATUS_IS_OK(status)) {
     1548                DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
     1549                         e->ep_description->endpoint, nt_errstr(status)));
     1550        }
     1551
     1552        return status;
     1553}
     1554
     1555static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
     1556                                      struct loadparm_context *lp_ctx,
     1557                                      struct dcesrv_endpoint *e,
     1558                                      struct tevent_context *event_ctx, const struct model_ops *model_ops)
     1559{
     1560        struct dcesrv_socket_context *dcesrv_sock;
     1561        uint16_t port = 1;
     1562        char *full_path;
     1563        NTSTATUS status;
     1564
     1565        if (!e->ep_description->endpoint) {
     1566                /* No identifier specified: use DEFAULT.
     1567                 * DO NOT hardcode this value anywhere else. Rather, specify
     1568                 * no endpoint and let the epmapper worry about it. */
     1569                e->ep_description->endpoint = talloc_strdup(dce_ctx, "DEFAULT");
     1570        }
     1571
     1572        full_path = talloc_asprintf(dce_ctx, "%s/%s", lpcfg_ncalrpc_dir(lp_ctx),
     1573                                    e->ep_description->endpoint);
     1574
     1575        dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
     1576        NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
     1577
     1578        /* remember the endpoint of this socket */
     1579        dcesrv_sock->endpoint           = e;
     1580        dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
     1581
     1582        status = stream_setup_socket(dcesrv_sock, event_ctx, lp_ctx,
     1583                                     model_ops, &dcesrv_stream_ops,
     1584                                     "unix", full_path, &port,
     1585                                     lpcfg_socket_options(lp_ctx),
     1586                                     dcesrv_sock);
     1587        if (!NT_STATUS_IS_OK(status)) {
     1588                DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
     1589                         e->ep_description->endpoint, full_path, nt_errstr(status)));
     1590        }
     1591        return status;
     1592}
     1593
     1594static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
     1595                                 struct loadparm_context *lp_ctx,
     1596                                 struct dcesrv_endpoint *e,
     1597                                 struct tevent_context *event_ctx, const struct model_ops *model_ops)
     1598{
     1599        struct dcesrv_socket_context *dcesrv_sock;
     1600        NTSTATUS status;
     1601                       
     1602        if (e->ep_description->endpoint == NULL) {
     1603                DEBUG(0, ("Endpoint mandatory for named pipes\n"));
     1604                return NT_STATUS_INVALID_PARAMETER;
     1605        }
     1606
     1607        dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
     1608        NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
     1609
     1610        /* remember the endpoint of this socket */
     1611        dcesrv_sock->endpoint           = e;
     1612        dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
     1613
     1614        status = tstream_setup_named_pipe(dce_ctx, event_ctx, lp_ctx,
     1615                                          model_ops, &dcesrv_stream_ops,
     1616                                          e->ep_description->endpoint,
     1617                                          dcesrv_sock);
     1618        if (!NT_STATUS_IS_OK(status)) {
     1619                DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
     1620                         e->ep_description->endpoint, nt_errstr(status)));
     1621                return status;
     1622        }
     1623
     1624        return NT_STATUS_OK;
     1625}
     1626
     1627/*
     1628  add a socket address to the list of events, one event per dcerpc endpoint
     1629*/
     1630static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
     1631                                         struct tevent_context *event_ctx, const struct model_ops *model_ops,
     1632                                         const char *address)
     1633{
     1634        struct dcesrv_socket_context *dcesrv_sock;
     1635        uint16_t port = 0;
     1636        NTSTATUS status;
     1637                       
     1638        if (e->ep_description->endpoint) {
     1639                port = atoi(e->ep_description->endpoint);
     1640        }
     1641
     1642        dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
     1643        NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
     1644
     1645        /* remember the endpoint of this socket */
     1646        dcesrv_sock->endpoint           = e;
     1647        dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
     1648
     1649        status = stream_setup_socket(dcesrv_sock, event_ctx, dce_ctx->lp_ctx,
     1650                                     model_ops, &dcesrv_stream_ops,
     1651                                     "ipv4", address, &port,
     1652                                     lpcfg_socket_options(dce_ctx->lp_ctx),
     1653                                     dcesrv_sock);
     1654        if (!NT_STATUS_IS_OK(status)) {
     1655                DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
     1656                         address, port, nt_errstr(status)));
     1657        }
     1658
     1659        if (e->ep_description->endpoint == NULL) {
     1660                e->ep_description->endpoint = talloc_asprintf(dce_ctx, "%d", port);
     1661        }
     1662
     1663        return status;
     1664}
     1665
     1666#include "lib/socket/netif.h" /* Included here to work around the fact that socket_wrapper redefines bind() */
     1667
     1668static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
     1669                                  struct loadparm_context *lp_ctx,
     1670                                  struct dcesrv_endpoint *e,
     1671                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
     1672{
     1673        NTSTATUS status;
     1674
     1675        /* Add TCP/IP sockets */
     1676        if (lpcfg_interfaces(lp_ctx) && lpcfg_bind_interfaces_only(lp_ctx)) {
     1677                int num_interfaces;
     1678                int i;
     1679                struct interface *ifaces;
     1680
     1681                load_interfaces(dce_ctx, lpcfg_interfaces(lp_ctx), &ifaces);
     1682
     1683                num_interfaces = iface_count(ifaces);
     1684                for(i = 0; i < num_interfaces; i++) {
     1685                        const char *address = iface_n_ip(ifaces, i);
     1686                        status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
     1687                        NT_STATUS_NOT_OK_RETURN(status);
     1688                }
     1689        } else {
     1690                status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops,
     1691                                                  lpcfg_socket_address(lp_ctx));
     1692                NT_STATUS_NOT_OK_RETURN(status);
     1693        }
     1694
     1695        return NT_STATUS_OK;
     1696}
     1697
     1698NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
     1699                       struct loadparm_context *lp_ctx,
     1700                       struct dcesrv_endpoint *e,
     1701                       struct tevent_context *event_ctx,
     1702                       const struct model_ops *model_ops)
     1703{
     1704        switch (e->ep_description->transport) {
     1705        case NCACN_UNIX_STREAM:
     1706                return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
     1707
     1708        case NCALRPC:
     1709                return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
     1710
     1711        case NCACN_IP_TCP:
     1712                return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
     1713
     1714        case NCACN_NP:
     1715                return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
     1716
     1717        default:
     1718                return NT_STATUS_NOT_SUPPORTED;
     1719        }
     1720}
     1721
     1722
     1723/**
     1724 * retrieve credentials from a dce_call
     1725 */
     1726_PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
     1727{
     1728        return dce_call->conn->auth_state.session_info->credentials;
     1729}
     1730
     1731/**
     1732 * returns true if this is an authenticated call
     1733 */
     1734_PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
     1735{
     1736        enum security_user_level level;
     1737        level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
     1738        return level >= SECURITY_USER;
     1739}
     1740
     1741/**
     1742 * retrieve account_name for a dce_call
     1743 */
     1744_PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
     1745{
     1746        return dce_call->context->conn->auth_state.session_info->info->account_name;
     1747}
  • trunk/server/source4/rpc_server/dcerpc_server.h

    r414 r745  
    2424#define SAMBA_DCERPC_SERVER_H
    2525
    26 #include "librpc/gen_ndr/server_id.h"
     26#include "librpc/gen_ndr/server_id4.h"
    2727#include "librpc/rpc/dcerpc.h"
    2828#include "librpc/ndr/libndr.h"
     
    4545
    4646        /* this function is called when the client binds to this interface  */
    47         NTSTATUS (*bind)(struct dcesrv_call_state *, const struct dcesrv_interface *);
     47        NTSTATUS (*bind)(struct dcesrv_call_state *, const struct dcesrv_interface *, uint32_t if_version);
    4848
    4949        /* this function is called when the client disconnects the endpoint */
     
    219219                void *private_data;
    220220                void (*report_output_data)(struct dcesrv_connection *);
    221                 struct socket_address *(*get_my_addr)(struct dcesrv_connection *, TALLOC_CTX *mem_ctx);
    222                 struct socket_address *(*get_peer_addr)(struct dcesrv_connection *, TALLOC_CTX *mem_ctx);
    223221        } transport;
    224222
    225223        struct tstream_context *stream;
    226224        struct tevent_queue *send_queue;
     225
     226        const struct tsocket_address *local_address;
     227        const struct tsocket_address *remote_address;
    227228};
    228229
     
    261262        /* parent context */
    262263        struct dcesrv_context *dce_ctx;
     264
     265        /* Remote association group ID (if proxied) */
     266        uint32_t proxied_id;
    263267};
    264268
     
    332336
    333337struct socket_address *dcesrv_connection_get_peer_addr(struct dcesrv_connection *conn, TALLOC_CTX *mem_ctx);
     338const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn);
     339const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn);
    334340
    335341NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p, DATA_BLOB *session_key);
     
    372378#define DCESRV_PULL_HANDLE_WERR(h, inhandle, t) DCESRV_PULL_HANDLE_RETVAL(h, inhandle, t, WERR_BADFID)
    373379
     380NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
     381                       struct loadparm_context *lp_ctx,
     382                       struct dcesrv_endpoint *e,
     383                       struct tevent_context *event_ctx,
     384                       const struct model_ops *model_ops);
     385
     386/**
     387 * retrieve credentials from a dce_call
     388 */
     389_PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call);
     390
     391/**
     392 * returns true if this is an authenticated call
     393 */
     394_PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call);
     395
     396/**
     397 * retrieve account_name for a dce_call
     398 */
     399_PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call);
    374400
    375401
  • trunk/server/source4/rpc_server/dcesrv_auth.c

    r414 r745  
    2424#include "rpc_server/dcerpc_server.h"
    2525#include "rpc_server/dcerpc_server_proto.h"
     26#include "rpc_server/common/proto.h"
    2627#include "librpc/rpc/dcerpc_proto.h"
    2728#include "librpc/gen_ndr/ndr_dcerpc.h"
     
    3031#include "auth/auth.h"
    3132#include "param/param.h"
     33#include "librpc/rpc/rpc_common.h"
    3234
    3335/*
     
    4345        struct dcesrv_auth *auth = &dce_conn->auth_state;
    4446        NTSTATUS status;
    45         enum ndr_err_code ndr_err;
     47        uint32_t auth_length;
    4648
    4749        if (pkt->u.bind.auth_info.length == 0) {
     
    5557        }
    5658
    57         ndr_err = ndr_pull_struct_blob(&pkt->u.bind.auth_info,
    58                                        call, NULL,
    59                                        dce_conn->auth_state.auth_info,
    60                                        (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
    61         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    62                 return false;
    63         }
    64 
     59        status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.bind.auth_info,
     60                                          dce_conn->auth_state.auth_info,
     61                                          &auth_length, false);
    6562        server_credentials
    6663                = cli_credentials_init(call);
     
    8077        status = samba_server_gensec_start(dce_conn, call->event_ctx,
    8178                                           call->msg_ctx,
    82                                            call->conn->dce_ctx->lp_ctx, 
     79                                           call->conn->dce_ctx->lp_ctx,
    8380                                           server_credentials,
    8481                                           NULL,
     
    8986
    9087        if (!NT_STATUS_IS_OK(status)) {
    91                 DEBUG(1, ("Failed to start GENSEC mechanism for DCERPC server: auth_type=%d, auth_level=%d: %s\n",
     88                DEBUG(3, ("Failed to start GENSEC mechanism for DCERPC server: auth_type=%d, auth_level=%d: %s\n",
    9289                          (int)auth->auth_info->auth_type,
    9390                          (int)auth->auth_info->auth_level,
     
    142139                return NT_STATUS_OK;
    143140        } else {
    144                 DEBUG(2, ("Failed to start dcesrv auth negotiate: %s\n", nt_errstr(status)));
     141                DEBUG(4, ("GENSEC mech rejected the incoming authentication at bind_ack: %s\n",
     142                          nt_errstr(status)));
    145143                return status;
    146144        }
     
    156154        struct dcesrv_connection *dce_conn = call->conn;
    157155        NTSTATUS status;
    158         enum ndr_err_code ndr_err;
     156        uint32_t auth_length;
    159157
    160158        /* We can't work without an existing gensec state, and an new blob to feed it */
     
    165163        }
    166164
    167         ndr_err = ndr_pull_struct_blob(&pkt->u.auth3.auth_info,
    168                                        call, NULL,
    169                                        dce_conn->auth_state.auth_info,
    170                                        (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
    171         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     165        status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.auth3.auth_info,
     166                                          dce_conn->auth_state.auth_info, &auth_length, true);
     167        if (!NT_STATUS_IS_OK(status)) {
    172168                return false;
    173169        }
     
    189185                return true;
    190186        } else {
    191                 DEBUG(4, ("dcesrv_auth_auth3: failed to authenticate: %s\n",
     187                DEBUG(4, ("GENSEC mech rejected the incoming authentication at bind_auth3: %s\n",
    192188                          nt_errstr(status)));
    193189                return false;
    194190        }
    195 
    196         return true;
    197191}
    198192
     
    206200        struct ncacn_packet *pkt = &call->pkt;
    207201        struct dcesrv_connection *dce_conn = call->conn;
    208         enum ndr_err_code ndr_err;
     202        NTSTATUS status;
     203        uint32_t auth_length;
    209204
    210205        /* on a pure interface change there is no auth blob */
     
    223218        }
    224219
    225         ndr_err = ndr_pull_struct_blob(&pkt->u.alter.auth_info,
    226                                        call, NULL,
    227                                        dce_conn->auth_state.auth_info,
    228                                        (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
    229         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     220        status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.alter.auth_info,
     221                                          dce_conn->auth_state.auth_info,
     222                                          &auth_length, true);
     223        if (!NT_STATUS_IS_OK(status)) {
    230224                return false;
    231225        }
     
    276270        }
    277271
    278         DEBUG(2, ("Failed to finish dcesrv auth alter_ack: %s\n", nt_errstr(status)));
     272        DEBUG(4, ("GENSEC mech rejected the incoming authentication at auth alter_ack: %s\n",
     273                  nt_errstr(status)));
    279274        return status;
    280275}
     
    287282        struct ncacn_packet *pkt = &call->pkt;
    288283        struct dcesrv_connection *dce_conn = call->conn;
    289         DATA_BLOB auth_blob;
    290284        struct dcerpc_auth auth;
    291         struct ndr_pull *ndr;
    292         NTSTATUS status;
    293         enum ndr_err_code ndr_err;
     285        NTSTATUS status;
     286        uint32_t auth_length;
    294287        size_t hdr_size = DCERPC_REQUEST_LENGTH;
    295288
     
    297290            !dce_conn->auth_state.gensec_security) {
    298291                return true;
     292        }
     293
     294        if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
     295                hdr_size += 16;
    299296        }
    300297
     
    319316        }
    320317
    321         auth_blob.length = 8 + pkt->auth_length;
    322 
    323         /* check for a valid length */
    324         if (pkt->u.request.stub_and_verifier.length < auth_blob.length) {
    325                 return false;
    326         }
    327 
    328         auth_blob.data =
    329                 pkt->u.request.stub_and_verifier.data +
    330                 pkt->u.request.stub_and_verifier.length - auth_blob.length;
    331         pkt->u.request.stub_and_verifier.length -= auth_blob.length;
    332 
    333         /* pull the auth structure */
    334         ndr = ndr_pull_init_blob(&auth_blob, call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx));
    335         if (!ndr) {
    336                 return false;
    337         }
    338 
    339         if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
    340                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
    341         }
    342 
    343         if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
    344                 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
    345                 hdr_size += 16;
    346         }
    347 
    348         ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth);
    349         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    350                 talloc_free(ndr);
    351                 return false;
    352         }
     318        status = dcerpc_pull_auth_trailer(pkt, call,
     319                                          &pkt->u.request.stub_and_verifier,
     320                                          &auth, &auth_length, false);
     321        if (!NT_STATUS_IS_OK(status)) {
     322                return false;
     323        }
     324
     325        pkt->u.request.stub_and_verifier.length -= auth_length;
    353326
    354327        /* check signature or unseal the packet */
     
    389362        /* remove the indicated amount of padding */
    390363        if (pkt->u.request.stub_and_verifier.length < auth.auth_pad_length) {
    391                 talloc_free(ndr);
    392364                return false;
    393365        }
    394366        pkt->u.request.stub_and_verifier.length -= auth.auth_pad_length;
    395         talloc_free(ndr);
    396367
    397368        return NT_STATUS_IS_OK(status);
     
    415386        /* non-signed packets are simple */
    416387        if (sig_size == 0) {
    417                 status = ncacn_push_auth(blob, call, lp_iconv_convenience(dce_conn->dce_ctx->lp_ctx), pkt, NULL);
     388                status = ncacn_push_auth(blob, call, pkt, NULL);
    418389                return NT_STATUS_IS_OK(status);
    419390        }
     
    426397        case DCERPC_AUTH_LEVEL_CONNECT:
    427398                /*
    428                  * TODO: let the gensec mech decide if it wants to generate a signature
    429                  *       that might be needed for schannel...
     399                 * TODO: let the gensec mech decide if it wants to generate a
     400                 *       signature that might be needed for schannel...
    430401                 */
    431                 status = ncacn_push_auth(blob, call, lp_iconv_convenience(dce_conn->dce_ctx->lp_ctx), pkt, NULL);
     402                status = ncacn_push_auth(blob, call, pkt, NULL);
    432403                return NT_STATUS_IS_OK(status);
    433404
    434405        case DCERPC_AUTH_LEVEL_NONE:
    435                 status = ncacn_push_auth(blob, call, lp_iconv_convenience(dce_conn->dce_ctx->lp_ctx), pkt, NULL);
     406                status = ncacn_push_auth(blob, call, pkt, NULL);
    436407                return NT_STATUS_IS_OK(status);
    437408
     
    440411        }
    441412
    442         ndr = ndr_push_init_ctx(call, lp_iconv_convenience(dce_conn->dce_ctx->lp_ctx));
     413        ndr = ndr_push_init_ctx(call);
    443414        if (!ndr) {
    444415                return false;
     
    454425        }
    455426
    456         /* pad to 16 byte multiple, match win2k3 */
     427        /* pad to 16 byte multiple in the payload portion of the
     428           packet. This matches what w2k3 does. Note that we can't use
     429           ndr_push_align() as that is relative to the start of the
     430           whole packet, whereas w2k8 wants it relative to the start
     431           of the stub */
    457432        dce_conn->auth_state.auth_info->auth_pad_length =
    458433                (16 - (pkt->u.response.stub_and_verifier.length & 15)) & 15;
    459         ndr_err = ndr_push_zero(ndr, dce_conn->auth_state.auth_info->auth_pad_length);
     434        ndr_err = ndr_push_zero(ndr,
     435                                dce_conn->auth_state.auth_info->auth_pad_length);
    460436        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    461437                return false;
     
    470446        /* add the auth verifier */
    471447        ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS,
    472                                       dce_conn->auth_state.auth_info);
     448                                       dce_conn->auth_state.auth_info);
    473449        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    474450                return false;
     
    514490        }
    515491
    516         if (NT_STATUS_IS_OK(status)) {
    517                 if (creds2.length != sig_size) {
    518                         DEBUG(0,("dcesrv_auth_response: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
    519                                  (unsigned)creds2.length, (uint32_t)sig_size,
    520                                  (unsigned)dce_conn->auth_state.auth_info->auth_pad_length,
    521                                  (unsigned)pkt->u.response.stub_and_verifier.length));
    522                         data_blob_free(&creds2);
    523                         status = NT_STATUS_INTERNAL_ERROR;
    524                 }
    525         }
    526 
    527         if (NT_STATUS_IS_OK(status)) {
    528                 if (!data_blob_append(call, blob, creds2.data, creds2.length)) {
    529                         status = NT_STATUS_NO_MEMORY;
    530                 }
    531                 data_blob_free(&creds2);
    532         }
    533 
    534492        if (!NT_STATUS_IS_OK(status)) {
    535493                return false;
    536494        }       
    537495
     496        if (creds2.length != sig_size) {
     497                DEBUG(3,("dcesrv_auth_response: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n",
     498                         (unsigned)creds2.length, (uint32_t)sig_size,
     499                         (unsigned)dce_conn->auth_state.auth_info->auth_pad_length,
     500                         (unsigned)pkt->u.response.stub_and_verifier.length));
     501                dcerpc_set_frag_length(blob, blob->length + creds2.length);
     502                dcerpc_set_auth_length(blob, creds2.length);
     503        }
     504
     505        if (!data_blob_append(call, blob, creds2.data, creds2.length)) {
     506                status = NT_STATUS_NO_MEMORY;
     507                return false;
     508        }
     509        data_blob_free(&creds2);
     510
    538511        return true;
    539512}
  • trunk/server/source4/rpc_server/drsuapi/addentry.c

    r414 r745  
    2323#include "includes.h"
    2424#include "rpc_server/dcerpc_server.h"
    25 #include "rpc_server/common/common.h"
    2625#include "dsdb/samdb/samdb.h"
    27 #include "lib/ldb/include/ldb_errors.h"
     26#include "dsdb/common/util.h"
    2827#include "param/param.h"
    29 #include "librpc/gen_ndr/ndr_drsblobs.h"
    30 #include "auth/auth.h"
     28#include "libcli/security/security.h"
     29#include "libcli/security/session.h"
    3130#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
    32 #include "libcli/security/security.h"
    33 #include "librpc/gen_ndr/ndr_drsblobs.h"
    3431#include "librpc/gen_ndr/ndr_drsuapi.h"
    35 
    3632
    3733/*
     
    5046                const char *dn_string = obj->object.identifier->dn;
    5147                struct ldb_dn *dn = ldb_dn_new(mem_ctx, b_state->sam_ctx, dn_string);
    52                 struct ldb_result *res;
     48                struct ldb_result *res, *res2;
    5349                struct ldb_dn *ref_dn;
    5450                struct GUID ntds_guid;
     
    5753                const char *ntds_guid_str;
    5854                const char *dom_string;
     55                const char *attrs2[] = { "dNSHostName", "cn", NULL };
     56                const char *dNSHostName, *cn;
    5957
    6058                DEBUG(6,(__location__ ": Adding SPNs for %s\n",
     
    8381                ntds_guid_str = GUID_string(res, &ntds_guid);
    8482
    85                 dom_string = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
     83                dom_string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
     84
     85                /* get the dNSHostName and cn */
     86                ret = ldb_search(b_state->sam_ctx, mem_ctx, &res2,
     87                                 ref_dn, LDB_SCOPE_BASE, attrs2, NULL);
     88                if (ret != LDB_SUCCESS) {
     89                        DEBUG(0,(__location__ ": Failed to find ref_dn '%s'\n",
     90                                 ldb_dn_get_linearized(ref_dn)));
     91                        return WERR_DS_DRA_INTERNAL_ERROR;
     92                }
     93
     94                dNSHostName = ldb_msg_find_attr_as_string(res2->msgs[0], "dNSHostName", NULL);
     95                cn = ldb_msg_find_attr_as_string(res2->msgs[0], "cn", NULL);
    8696
    8797                /*
     
    101111                }
    102112
    103                 el->num_values = 2;
    104                 el->values = talloc_array(msg->elements, struct ldb_val, 2);
    105                 if (el->values == NULL) {
     113
     114                ldb_msg_add_steal_string(msg, "servicePrincipalName",
     115                                         talloc_asprintf(el->values,
     116                                                         "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s",
     117                                                         ntds_guid_str, dom_string));
     118                ldb_msg_add_steal_string(msg, "servicePrincipalName",
     119                                         talloc_asprintf(el->values, "ldap/%s._msdcs.%s",
     120                                                         ntds_guid_str, dom_string));
     121                if (cn) {
     122                        ldb_msg_add_steal_string(msg, "servicePrincipalName",
     123                                                 talloc_asprintf(el->values, "ldap/%s", cn));
     124                }
     125                if (dNSHostName) {
     126                        ldb_msg_add_steal_string(msg, "servicePrincipalName",
     127                                                 talloc_asprintf(el->values, "ldap/%s", dNSHostName));
     128                }
     129                if (el->num_values < 2) {
    106130                        return WERR_NOMEM;
    107131                }
    108                 /* the magic constant is the GUID of the DRSUAPI RPC
    109                    interface */
    110                 el->values[0].data = (uint8_t *)talloc_asprintf(el->values,
    111                                                                 "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s",
    112                                                                 ntds_guid_str, dom_string);
    113                 el->values[0].length = strlen((char *)el->values[0].data);
    114                 el->values[1].data = (uint8_t *)talloc_asprintf(el->values, "ldap/%s._msdcs.%s",
    115                                                                 ntds_guid_str, dom_string);
    116                 el->values[1].length = strlen((char *)el->values[1].data);
    117 
    118                 ret = ldb_modify(b_state->sam_ctx, msg);
     132
     133                ret = dsdb_modify(b_state->sam_ctx, msg, DSDB_MODIFY_PERMISSIVE);
    119134                if (ret != LDB_SUCCESS) {
    120135                        DEBUG(0,(__location__ ": Failed to add SPNs - %s\n",
     
    152167        ZERO_STRUCTP(r->out.ctr);
    153168        *r->out.level_out = 3;
    154         r->out.ctr->ctr3.level = 1;
    155         r->out.ctr->ctr3.error = talloc_zero(mem_ctx, union drsuapi_DsAddEntryError);
     169        r->out.ctr->ctr3.err_ver = 1;
     170        r->out.ctr->ctr3.err_data = talloc_zero(mem_ctx, union drsuapi_DsAddEntry_ErrData);
    156171
    157172        DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
    158173        b_state = h->data;
    159174
    160         status = drs_security_level_check(dce_call, "DsAddEntry");
     175        status = drs_security_level_check(dce_call, "DsAddEntry", SECURITY_DOMAIN_CONTROLLER, NULL);
    161176        if (!W_ERROR_IS_OK(status)) {
    162177                return status;
     
    179194                                                    &ids);
    180195                if (!W_ERROR_IS_OK(status)) {
    181                         r->out.ctr->ctr3.error->info1.status = status;
     196                        r->out.ctr->ctr3.err_data->v1.status = status;
    182197                        ldb_transaction_cancel(b_state->sam_ctx);
     198                        DEBUG(0,(__location__ ": DsAddEntry failed - %s\n", win_errstr(status)));
    183199                        return status;
    184200                }
     
    197213        status = drsuapi_add_SPNs(b_state, dce_call, mem_ctx, first_object);
    198214        if (!W_ERROR_IS_OK(status)) {
    199                 r->out.ctr->ctr3.error->info1.status = status;
     215                r->out.ctr->ctr3.err_data->v1.status = status;
    200216                ldb_transaction_cancel(b_state->sam_ctx);
     217                DEBUG(0,(__location__ ": DsAddEntry add SPNs failed - %s\n", win_errstr(status)));
    201218                return status;
    202219        }
     
    204221        ret = ldb_transaction_commit(b_state->sam_ctx);
    205222        if (ret != LDB_SUCCESS) {
     223                DEBUG(0,(__location__ ": DsAddEntry commit failed: %s\n",
     224                         ldb_errstring(b_state->sam_ctx)));
    206225                return WERR_DS_DRA_INTERNAL_ERROR;
    207226        }
  • trunk/server/source4/rpc_server/drsuapi/dcesrv_drsuapi.c

    r414 r745  
    2626#include "rpc_server/common/common.h"
    2727#include "dsdb/samdb/samdb.h"
     28#include "libcli/security/security.h"
     29#include "libcli/security/session.h"
    2830#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
    29 #include "libcli/security/security.h"
     31#include "auth/auth.h"
     32#include "param/param.h"
     33#include "lib/messaging/irpc.h"
     34
     35#define DRSUAPI_UNSUPPORTED(fname) do { \
     36        DEBUG(1,(__location__ ": Unsupported DRS call %s\n", #fname)); \
     37        if (DEBUGLVL(2)) NDR_PRINT_IN_DEBUG(fname, r); \
     38        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); \
     39} while (0)
    3040
    3141/*
     
    4858        uint32_t repl_epoch;
    4959        int ret;
     60        struct auth_session_info *auth_info;
     61        WERROR werr;
     62        bool connected_as_system = false;
    5063
    5164        r->out.bind_info = NULL;
     
    5568        W_ERROR_HAVE_NO_MEMORY(b_state);
    5669
     70        /* if this is a DC connecting, give them system level access */
     71        werr = drs_security_level_check(dce_call, NULL, SECURITY_DOMAIN_CONTROLLER, NULL);
     72        if (W_ERROR_IS_OK(werr)) {
     73                DEBUG(3,(__location__ ": doing DsBind with system_session\n"));
     74                auth_info = system_session(dce_call->conn->dce_ctx->lp_ctx);
     75                connected_as_system = true;
     76        } else {
     77                auth_info = dce_call->conn->auth_state.session_info;
     78        }
     79
    5780        /*
    5881         * connect to the samdb
    5982         */
    60         b_state->sam_ctx = samdb_connect(b_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
     83        b_state->sam_ctx = samdb_connect(b_state, dce_call->event_ctx,
     84                                         dce_call->conn->dce_ctx->lp_ctx, auth_info, 0);
    6185        if (!b_state->sam_ctx) {
    6286                return WERR_FOOBAR;
     87        }
     88
     89        if (connected_as_system) {
     90                b_state->sam_ctx_system = b_state->sam_ctx;
     91        } else {
     92                /* an RODC also needs system samdb access for secret
     93                   attribute replication */
     94                werr = drs_security_level_check(dce_call, NULL, SECURITY_RO_DOMAIN_CONTROLLER,
     95                                                samdb_domain_sid(b_state->sam_ctx));
     96                if (W_ERROR_IS_OK(werr)) {
     97                        b_state->sam_ctx_system = samdb_connect(b_state, dce_call->event_ctx,
     98                                                                dce_call->conn->dce_ctx->lp_ctx,
     99                                                                system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
     100                        if (!b_state->sam_ctx_system) {
     101                                return WERR_FOOBAR;
     102                        }
     103                }
    63104        }
    64105
     
    95136                return WERR_DS_DRA_INTERNAL_ERROR;
    96137        }
    97         repl_epoch = samdb_result_uint(ntds_res->msgs[0], "ms-DS-ReplicationEpoch", 0);
     138        repl_epoch = ldb_msg_find_attr_as_uint(ntds_res->msgs[0],
     139                                               "ms-DS-ReplicationEpoch", 0);
    98140
    99141        /*
     
    147189        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
    148190        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
    149         if (0 /*domain.behavior_version == 2*/) {
    150                 /* TODO: find out how this is really triggered! */
    151                 b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
    152         }
     191        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
    153192        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
    154193        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
     
    160199        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
    161200        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
    162         b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_00100000;
     201        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V5;
    163202        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
    164203        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
     
    173212        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
    174213#endif
     214        b_state->local_info28.supported_extensions      |= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10;
    175215        b_state->local_info28.site_guid                 = site_guid;
    176216        b_state->local_info28.pid                       = pid;
     
    230270{
    231271        WERROR status;
    232 
    233         status = drs_security_level_check(dce_call, "DsReplicaSync");
     272        uint32_t timeout;
     273
     274        status = drs_security_level_check(dce_call, "DsReplicaSync", SECURITY_DOMAIN_CONTROLLER, NULL);
    234275        if (!W_ERROR_IS_OK(status)) {
    235276                return status;
    236277        }
    237278
    238         dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSREPLICASYNC,
     279        if (r->in.level != 1) {
     280                DEBUG(0,("DsReplicaSync called with unsupported level %d\n", r->in.level));
     281                return WERR_DS_DRA_INVALID_PARAMETER;
     282        }
     283
     284        if (r->in.req->req1.options & DRSUAPI_DRS_ASYNC_OP) {
     285                timeout = IRPC_CALL_TIMEOUT;
     286        } else {
     287                /*
     288                 * use Infinite time for timeout in case
     289                 * the caller made a sync call
     290                 */
     291                timeout = IRPC_CALL_TIMEOUT_INF;
     292        }
     293
     294        dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
     295                                     r, NDR_DRSUAPI_DSREPLICASYNC,
    239296                                     &ndr_table_drsuapi,
    240                                      "dreplsrv", "DsReplicaSync");
     297                                     "dreplsrv", "DsReplicaSync",
     298                                     timeout);
    241299
    242300        return WERR_OK;
     
    250308                                          struct drsuapi_DsReplicaAdd *r)
    251309{
    252         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     310        WERROR status;
     311
     312        status = drs_security_level_check(dce_call, "DsReplicaAdd", SECURITY_DOMAIN_CONTROLLER, NULL);
     313        if (!W_ERROR_IS_OK(status)) {
     314                return status;
     315        }
     316
     317        dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
     318                                     r, NDR_DRSUAPI_DSREPLICAADD,
     319                                     &ndr_table_drsuapi,
     320                                     "dreplsrv", "DsReplicaAdd",
     321                                     IRPC_CALL_TIMEOUT);
     322
     323        return WERR_OK;
    253324}
    254325
     
    260331                                          struct drsuapi_DsReplicaDel *r)
    261332{
    262         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     333        WERROR status;
     334
     335        status = drs_security_level_check(dce_call, "DsReplicaDel", SECURITY_DOMAIN_CONTROLLER, NULL);
     336        if (!W_ERROR_IS_OK(status)) {
     337                return status;
     338        }
     339
     340        dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
     341                                     r, NDR_DRSUAPI_DSREPLICADEL,
     342                                     &ndr_table_drsuapi,
     343                                     "dreplsrv", "DsReplicaDel",
     344                                     IRPC_CALL_TIMEOUT);
     345
     346        return WERR_OK;
    263347}
    264348
     
    270354                                          struct drsuapi_DsReplicaMod *r)
    271355{
    272         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     356        WERROR status;
     357
     358        status = drs_security_level_check(dce_call, "DsReplicaMod", SECURITY_DOMAIN_CONTROLLER, NULL);
     359        if (!W_ERROR_IS_OK(status)) {
     360                return status;
     361        }
     362
     363        dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx,
     364                                     r, NDR_DRSUAPI_DSREPLICAMOD,
     365                                     &ndr_table_drsuapi,
     366                                     "dreplsrv", "DsReplicaMod",
     367                                     IRPC_CALL_TIMEOUT);
     368
     369        return WERR_OK;
    273370}
    274371
     
    280377                       struct DRSUAPI_VERIFY_NAMES *r)
    281378{
    282         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     379        DRSUAPI_UNSUPPORTED(DRSUAPI_VERIFY_NAMES);
    283380}
    284381
     
    290387                       struct drsuapi_DsGetMemberships *r)
    291388{
    292         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     389        DRSUAPI_UNSUPPORTED(drsuapi_DsGetMemberships);
    293390}
    294391
     
    300397                       struct DRSUAPI_INTER_DOMAIN_MOVE *r)
    301398{
    302         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     399        DRSUAPI_UNSUPPORTED(DRSUAPI_INTER_DOMAIN_MOVE);
    303400}
    304401
     
    310407                       struct drsuapi_DsGetNT4ChangeLog *r)
    311408{
    312         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    313 }
    314 
     409        DRSUAPI_UNSUPPORTED(drsuapi_DsGetNT4ChangeLog);
     410}
    315411
    316412/*
     
    320416                            struct drsuapi_DsCrackNames *r)
    321417{
    322         WERROR status;
    323418        struct drsuapi_bind_state *b_state;
    324419        struct dcesrv_handle *h;
     
    334429        switch (r->in.level) {
    335430                case 1: {
    336                         struct drsuapi_DsNameCtr1 *ctr1;
    337                         struct drsuapi_DsNameInfo1 *names;
    338                         int count;
    339                         int i;
    340 
    341                         ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
    342                         W_ERROR_HAVE_NO_MEMORY(ctr1);
    343 
    344                         count = r->in.req->req1.count;
    345                         names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
    346                         W_ERROR_HAVE_NO_MEMORY(names);
    347 
    348                         for (i=0; i < count; i++) {
    349                                 status = DsCrackNameOneName(b_state->sam_ctx, mem_ctx,
    350                                                             r->in.req->req1.format_flags,
    351                                                             r->in.req->req1.format_offered,
    352                                                             r->in.req->req1.format_desired,
    353                                                             r->in.req->req1.names[i].str,
    354                                                             &names[i]);
    355                                 if (!W_ERROR_IS_OK(status)) {
    356                                         return status;
    357                                 }
    358                         }
    359 
    360                         ctr1->count = count;
    361                         ctr1->array = names;
    362                         r->out.ctr->ctr1 = ctr1;
    363 
    364                         return WERR_OK;
    365                 }
    366         }
    367        
    368         return WERR_UNKNOWN_LEVEL;
    369 }
    370 
    371 /*
    372   drsuapi_DsWriteAccountSpn
    373 */
    374 static WERROR dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    375                        struct drsuapi_DsWriteAccountSpn *r)
    376 {
    377         struct drsuapi_bind_state *b_state;
    378         struct dcesrv_handle *h;
    379 
    380         *r->out.level_out = r->in.level;
    381 
    382         DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
    383         b_state = h->data;
    384 
    385         r->out.res = talloc(mem_ctx, union drsuapi_DsWriteAccountSpnResult);
    386         W_ERROR_HAVE_NO_MEMORY(r->out.res);
    387 
    388         switch (r->in.level) {
    389                 case 1: {
    390                         struct drsuapi_DsWriteAccountSpnRequest1 *req;
    391                         struct ldb_message *msg;
    392                         int count, i, ret;
    393                         req = &r->in.req->req1;
    394                         count = req->count;
    395 
    396                         msg = ldb_msg_new(mem_ctx);
    397                         if (msg == NULL) {
    398                                 return WERR_NOMEM;
    399                         }
    400 
    401                         msg->dn = ldb_dn_new(msg, b_state->sam_ctx, req->object_dn);
    402                         if ( ! ldb_dn_validate(msg->dn)) {
    403                                 r->out.res->res1.status = WERR_OK;
     431                        switch(r->in.req->req1.format_offered){
     432                        case DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID:
     433                        case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX:
     434                        case DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS:
     435                        case DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON:
     436                        case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE:
     437                        case DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME:
     438                        case DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME:
     439                        case DRSUAPI_DS_NAME_FORMAT_LIST_NCS:
     440                        case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS:
     441                        case DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID:
     442                        case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN:
     443                        case DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER:
     444                        case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE:
     445                        case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE:
     446                        case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE:
     447                        case DRSUAPI_DS_NAME_FORMAT_LIST_SITES:
     448                                DEBUG(0, ("DsCrackNames: Unsupported operation requested: %X",
     449                                          r->in.req->req1.format_offered));
    404450                                return WERR_OK;
    405                         }
    406                        
    407                         /* construct mods */
    408                         for (i = 0; i < count; i++) {
    409                                 samdb_msg_add_string(b_state->sam_ctx,
    410                                                      msg, msg, "servicePrincipalName",
    411                                                      req->spn_names[i].str);
    412                         }
    413                         for (i=0;i<msg->num_elements;i++) {
    414                                 switch (req->operation) {
    415                                 case DRSUAPI_DS_SPN_OPERATION_ADD:
    416                                         msg->elements[i].flags = LDB_FLAG_MOD_ADD;
    417                                         break;
    418                                 case DRSUAPI_DS_SPN_OPERATION_REPLACE:
    419                                         msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
    420                                         break;
    421                                 case DRSUAPI_DS_SPN_OPERATION_DELETE:
    422                                         msg->elements[i].flags = LDB_FLAG_MOD_DELETE;
    423                                         break;
    424                                 }
    425                         }
    426    
    427                         /* Apply to database */
    428 
    429                         ret = ldb_modify(b_state->sam_ctx, msg);
    430                         if (ret != 0) {
    431                                 DEBUG(0,("Failed to modify SPNs on %s: %s\n",
    432                                          ldb_dn_get_linearized(msg->dn),
    433                                          ldb_errstring(b_state->sam_ctx)));
    434                                 r->out.res->res1.status = WERR_ACCESS_DENIED;
    435                         } else {
    436                                 r->out.res->res1.status = WERR_OK;
    437                         }
    438 
    439                         return WERR_OK;
    440                 }
    441         }
    442        
     451                        case DRSUAPI_DS_NAME_FORMAT_LIST_ROLES:
     452                                return dcesrv_drsuapi_ListRoles(b_state->sam_ctx, mem_ctx,
     453                                                                &r->in.req->req1, &r->out.ctr->ctr1);
     454                        default:/* format_offered is in the enum drsuapi_DsNameFormat*/
     455                                return dcesrv_drsuapi_CrackNamesByNameFormat(b_state->sam_ctx, mem_ctx,
     456                                                                             &r->in.req->req1, &r->out.ctr->ctr1);
     457                        }
     458                }
     459        }
    443460        return WERR_UNKNOWN_LEVEL;
    444461}
     
    458475        WERROR status;
    459476
    460         ZERO_STRUCT(r->out.res);
    461477        *r->out.level_out = 1;
    462478
    463         status = drs_security_level_check(dce_call, "DsRemoveDSServer");
     479        status = drs_security_level_check(dce_call, "DsRemoveDSServer", SECURITY_DOMAIN_CONTROLLER, NULL);
    464480        if (!W_ERROR_IS_OK(status)) {
    465481                return status;
     
    508524                       struct DRSUAPI_REMOVE_DS_DOMAIN *r)
    509525{
    510         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     526        DRSUAPI_UNSUPPORTED(DRSUAPI_REMOVE_DS_DOMAIN);
    511527}
    512528
    513529/* Obtain the site name from a server DN */
    514 static const char *result_site_name(struct ldb_dn *site_dn)
     530static const char *result_site_name(struct ldb_dn *server_dn)
    515531{
    516532        /* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
    517         const struct ldb_val *val = ldb_dn_get_component_val(site_dn, 2);
    518         const char *name = ldb_dn_get_component_name(site_dn, 2);
     533        const struct ldb_val *val = ldb_dn_get_component_val(server_dn, 2);
     534        const char *name = ldb_dn_get_component_name(server_dn, 2);
    519535
    520536        if (!name || (ldb_attr_cmp(name, "cn") != 0)) {
     
    556572        struct drsuapi_DsGetDCInfoCtr2 *ctr2;
    557573
    558         int ret, i;
     574        int ret;
     575        unsigned int i;
    559576
    560577        *r->out.level_out = r->in.req->req1.level;
     
    686703                        if (ret == LDB_SUCCESS && res_ntds->count == 1) {
    687704                                ctr2->array[i].is_gc
    688                                         = (ldb_msg_find_attr_as_int(res_ntds->msgs[0], "options", 0) == 1);
     705                                        = (ldb_msg_find_attr_as_uint(res_ntds->msgs[0], "options", 0) & DS_NTDSDSA_OPT_IS_GC);
    689706                                ctr2->array[i].ntds_guid
    690707                                        = samdb_result_guid(res_ntds->msgs[0], "objectGUID");
     
    784801                                  struct drsuapi_DsExecuteKCC *r)
    785802{
    786         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     803        WERROR status;
     804        status = drs_security_level_check(dce_call, "DsExecuteKCC", SECURITY_DOMAIN_CONTROLLER, NULL);
     805
     806        if (!W_ERROR_IS_OK(status)) {
     807                return status;
     808        }
     809
     810        dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSEXECUTEKCC,
     811                                     &ndr_table_drsuapi, "kccsrv", "DsExecuteKCC",
     812                                     IRPC_CALL_TIMEOUT);
     813        return WERR_OK;
    787814}
    788815
     
    794821                       struct drsuapi_DsReplicaGetInfo *r)
    795822{
    796         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     823        enum security_user_level level;
     824
     825        if (!lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL,
     826                         "drs", "disable_sec_check", false)) {
     827                level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
     828                if (level < SECURITY_DOMAIN_CONTROLLER) {
     829                        DEBUG(1,(__location__ ": Administrator access required for DsReplicaGetInfo\n"));
     830                        security_token_debug(0, 2, dce_call->conn->auth_state.session_info->security_token);
     831                        return WERR_DS_DRA_ACCESS_DENIED;
     832                }
     833        }
     834
     835        dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSREPLICAGETINFO,
     836                                     &ndr_table_drsuapi, "kccsrv", "DsReplicaGetInfo",
     837                                     IRPC_CALL_TIMEOUT);
     838
     839        return WERR_OK;
    797840}
    798841
     
    804847                       struct DRSUAPI_ADD_SID_HISTORY *r)
    805848{
    806         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     849        DRSUAPI_UNSUPPORTED(DRSUAPI_ADD_SID_HISTORY);
    807850}
    808851
     
    813856                       struct drsuapi_DsGetMemberships2 *r)
    814857{
    815         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     858        DRSUAPI_UNSUPPORTED(drsuapi_DsGetMemberships2);
    816859}
    817860
     
    822865                       struct DRSUAPI_REPLICA_VERIFY_OBJECTS *r)
    823866{
    824         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     867        DRSUAPI_UNSUPPORTED(DRSUAPI_REPLICA_VERIFY_OBJECTS);
    825868}
    826869
     
    832875                       struct DRSUAPI_GET_OBJECT_EXISTENCE *r)
    833876{
    834         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     877        DRSUAPI_UNSUPPORTED(DRSUAPI_GET_OBJECT_EXISTENCE);
    835878}
    836879
     
    842885                       struct drsuapi_QuerySitesByCost *r)
    843886{
    844         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     887        DRSUAPI_UNSUPPORTED(drsuapi_QuerySitesByCost);
    845888}
    846889
  • trunk/server/source4/rpc_server/drsuapi/dcesrv_drsuapi.h

    r414 r745  
    3232struct drsuapi_bind_state {
    3333        struct ldb_context *sam_ctx;
     34        struct ldb_context *sam_ctx_system;
    3435        struct GUID remote_bind_guid;
    3536        struct drsuapi_DsBindInfo28 remote_info28;
     
    4041
    4142/* prototypes of internal functions */
     43WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
     44                          struct drsuapi_DsReplicaUpdateRefsRequest1 *req);
    4245WERROR dcesrv_drsuapi_DsReplicaUpdateRefs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4346                                          struct drsuapi_DsReplicaUpdateRefs *r);
     
    4649WERROR dcesrv_drsuapi_DsAddEntry(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4750                                 struct drsuapi_DsAddEntry *r);
     51WERROR dcesrv_drsuapi_DsWriteAccountSpn(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     52                                        struct drsuapi_DsWriteAccountSpn *r);
    4853
    4954char *drs_ObjectIdentifier_to_string(TALLOC_CTX *mem_ctx,
     
    5661                                    enum ldb_scope scope,
    5762                                    const char * const *attrs,
    58                                     const char *sort_attrib,
    5963                                    const char *filter);
    6064
    6165WERROR drs_security_level_check(struct dcesrv_call_state *dce_call,
    62                                 const char* call);
     66                                const char* call, enum security_user_level minimum_level,
     67                                const struct dom_sid *domain_sid);
    6368
    6469void drsuapi_process_secret_attribute(struct drsuapi_DsReplicaAttribute *attr,
    6570                                      struct drsuapi_DsReplicaMetaData *meta_data);
     71
     72WERROR drs_security_access_check(struct ldb_context *sam_ctx,
     73                                 TALLOC_CTX *mem_ctx,
     74                                 struct security_token *token,
     75                                 struct drsuapi_DsReplicaObjectIdentifier *nc,
     76                                 const char *ext_right);
     77
     78WERROR drs_security_access_check_nc_root(struct ldb_context *sam_ctx,
     79                                         TALLOC_CTX *mem_ctx,
     80                                         struct security_token *token,
     81                                         struct drsuapi_DsReplicaObjectIdentifier *nc,
     82                                         const char *ext_right);
  • trunk/server/source4/rpc_server/drsuapi/drsutil.c

    r414 r745  
    2323#include "rpc_server/dcerpc_server.h"
    2424#include "dsdb/samdb/samdb.h"
    25 #include "libcli/security/dom_sid.h"
    26 #include "rpc_server/drsuapi/dcesrv_drsuapi.h"
    2725#include "libcli/security/security.h"
     26#include "libcli/security/session.h"
    2827#include "param/param.h"
    29 
    30 /*
    31   format a drsuapi_DsReplicaObjectIdentifier naming context as a string
    32  */
    33 char *drs_ObjectIdentifier_to_string(TALLOC_CTX *mem_ctx,
    34                                      struct drsuapi_DsReplicaObjectIdentifier *nc)
    35 {
    36         char *guid, *sid, *ret;
    37         guid = GUID_string(mem_ctx, &nc->guid);
    38         sid  = dom_sid_string(mem_ctx, &nc->sid);
    39         ret = talloc_asprintf(mem_ctx, "<GUID=%s>;<SID=%s>;%s",
    40                               guid, sid, nc->dn);
    41         talloc_free(guid);
    42         talloc_free(sid);
    43         return ret;
    44 }
     28#include "auth/session.h"
    4529
    4630int drsuapi_search_with_extended_dn(struct ldb_context *ldb,
     
    5034                                    enum ldb_scope scope,
    5135                                    const char * const *attrs,
    52                                     const char *sort_attrib,
    5336                                    const char *filter)
    5437{
     
    8467        }
    8568
    86         ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
    87         if (ret != LDB_SUCCESS) {
    88                 return ret;
    89         }
    90 
    91         if (sort_attrib) {
    92                 struct ldb_server_sort_control **sort_control;
    93                 sort_control = talloc_array(req, struct ldb_server_sort_control *, 2);
    94                 if (sort_control == NULL) {
    95                         talloc_free(tmp_ctx);
    96                         return LDB_ERR_OPERATIONS_ERROR;
    97                 }
    98                 sort_control[0] = talloc(req, struct ldb_server_sort_control);
    99                 sort_control[0]->attributeName = sort_attrib;
    100                 sort_control[0]->orderingRule = NULL;
    101                 sort_control[0]->reverse = 1;
    102                 sort_control[1] = NULL;
    103 
    104                 ret = ldb_request_add_control(req, LDB_CONTROL_SERVER_SORT_OID, true, sort_control);
    105                 if (ret != LDB_SUCCESS) {
    106                         return ret;
    107                 }
    108         }
    109 
     69        ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_RECYCLED_OID, true, NULL);
     70        if (ret != LDB_SUCCESS) {
     71                return ret;
     72        }
     73
     74        ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
     75        if (ret != LDB_SUCCESS) {
     76                return ret;
     77        }
    11078
    11179        ret = ldb_request(ldb, req);
     
    11987}
    12088
    121 WERROR drs_security_level_check(struct dcesrv_call_state *dce_call, const char* call)
    122 {
    123         if (lp_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL,
     89WERROR drs_security_level_check(struct dcesrv_call_state *dce_call,
     90                                const char* call,
     91                                enum security_user_level minimum_level,
     92                                const struct dom_sid *domain_sid)
     93{
     94        enum security_user_level level;
     95
     96        if (lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL,
    12497                         "drs", "disable_sec_check", false)) {
    12598                return WERR_OK;
    12699        }
    127100
    128         if (security_session_user_level(dce_call->conn->auth_state.session_info) <
    129                 SECURITY_DOMAIN_CONTROLLER) {
    130                 DEBUG(0,("DsReplicaGetInfo refused for security token\n"));
     101        level = security_session_user_level(dce_call->conn->auth_state.session_info, domain_sid);
     102        if (level < minimum_level) {
     103                if (call) {
     104                        DEBUG(0,("%s refused for security token (level=%u)\n",
     105                                 call, (unsigned)level));
     106                        security_token_debug(0, 2, dce_call->conn->auth_state.session_info->security_token);
     107                }
    131108                return WERR_DS_DRA_ACCESS_DENIED;
    132109        }
     
    143120
    144121        switch (attr->attid) {
    145         case DRSUAPI_ATTRIBUTE_dBCSPwd:
    146         case DRSUAPI_ATTRIBUTE_unicodePwd:
    147         case DRSUAPI_ATTRIBUTE_ntPwdHistory:
    148         case DRSUAPI_ATTRIBUTE_lmPwdHistory:
    149         case DRSUAPI_ATTRIBUTE_supplementalCredentials:
    150         case DRSUAPI_ATTRIBUTE_priorValue:
    151         case DRSUAPI_ATTRIBUTE_currentValue:
    152         case DRSUAPI_ATTRIBUTE_trustAuthOutgoing:
    153         case DRSUAPI_ATTRIBUTE_trustAuthIncoming:
    154         case DRSUAPI_ATTRIBUTE_initialAuthOutgoing:
    155         case DRSUAPI_ATTRIBUTE_initialAuthIncoming:
     122        case DRSUAPI_ATTID_dBCSPwd:
     123        case DRSUAPI_ATTID_unicodePwd:
     124        case DRSUAPI_ATTID_ntPwdHistory:
     125        case DRSUAPI_ATTID_lmPwdHistory:
     126        case DRSUAPI_ATTID_supplementalCredentials:
     127        case DRSUAPI_ATTID_priorValue:
     128        case DRSUAPI_ATTID_currentValue:
     129        case DRSUAPI_ATTID_trustAuthOutgoing:
     130        case DRSUAPI_ATTID_trustAuthIncoming:
     131        case DRSUAPI_ATTID_initialAuthOutgoing:
     132        case DRSUAPI_ATTID_initialAuthIncoming:
    156133                /*set value to null*/
    157134                attr->value_ctr.num_values = 0;
     
    163140                return;
    164141        }
    165         return;
    166 }
     142}
     143
     144
     145/*
     146  check security on a DN, with logging of errors
     147 */
     148static WERROR drs_security_access_check_log(struct ldb_context *sam_ctx,
     149                                            TALLOC_CTX *mem_ctx,
     150                                            struct security_token *token,
     151                                            struct ldb_dn *dn,
     152                                            const char *ext_right)
     153{
     154        int ret;
     155        if (!dn) {
     156                DEBUG(3,("drs_security_access_check: Null dn provided, access is denied for %s\n",
     157                              ext_right));
     158                return WERR_DS_DRA_ACCESS_DENIED;
     159        }
     160        ret = dsdb_check_access_on_dn(sam_ctx,
     161                                      mem_ctx,
     162                                      dn,
     163                                      token,
     164                                      SEC_ADS_CONTROL_ACCESS,
     165                                      ext_right);
     166        if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
     167                DEBUG(3,("%s refused for security token on %s\n",
     168                         ext_right, ldb_dn_get_linearized(dn)));
     169                security_token_debug(2, 0, token);
     170                return WERR_DS_DRA_ACCESS_DENIED;
     171        } else if (ret != LDB_SUCCESS) {
     172                DEBUG(1,("Failed to perform access check on %s\n", ldb_dn_get_linearized(dn)));
     173                return WERR_DS_DRA_INTERNAL_ERROR;
     174        }
     175        return WERR_OK;
     176}
     177
     178
     179/*
     180  check security on a object identifier
     181 */
     182WERROR drs_security_access_check(struct ldb_context *sam_ctx,
     183                                 TALLOC_CTX *mem_ctx,
     184                                 struct security_token *token,
     185                                 struct drsuapi_DsReplicaObjectIdentifier *nc,
     186                                 const char *ext_right)
     187{
     188        struct ldb_dn *dn = drs_ObjectIdentifier_to_dn(mem_ctx, sam_ctx, nc);
     189        WERROR werr;
     190        werr = drs_security_access_check_log(sam_ctx, mem_ctx, token, dn, ext_right);
     191        talloc_free(dn);
     192        return werr;
     193}
     194
     195/*
     196  check security on the NC root of a object identifier
     197 */
     198WERROR drs_security_access_check_nc_root(struct ldb_context *sam_ctx,
     199                                         TALLOC_CTX *mem_ctx,
     200                                         struct security_token *token,
     201                                         struct drsuapi_DsReplicaObjectIdentifier *nc,
     202                                         const char *ext_right)
     203{
     204        struct ldb_dn *dn, *nc_root;
     205        WERROR werr;
     206        int ret;
     207
     208        dn = drs_ObjectIdentifier_to_dn(mem_ctx, sam_ctx, nc);
     209        W_ERROR_HAVE_NO_MEMORY(dn);
     210        ret = dsdb_find_nc_root(sam_ctx, dn, dn, &nc_root);
     211        if (ret != LDB_SUCCESS) {
     212                return WERR_DS_CANT_FIND_EXPECTED_NC;
     213        }
     214        werr = drs_security_access_check_log(sam_ctx, mem_ctx, token, nc_root, ext_right);
     215        talloc_free(dn);
     216        return werr;
     217}
  • trunk/server/source4/rpc_server/drsuapi/getncchanges.c

    r414 r745  
    22   Unix SMB/CIFS implementation.
    33
    4    implement the DRSUpdateRefs call
     4   implement the DSGetNCChanges call
    55
    66   Copyright (C) Anatoliy Atanasov 2009
     
    2222
    2323#include "includes.h"
    24 #include "librpc/gen_ndr/ndr_drsuapi.h"
    2524#include "rpc_server/dcerpc_server.h"
    2625#include "dsdb/samdb/samdb.h"
    2726#include "param/param.h"
    2827#include "librpc/gen_ndr/ndr_drsblobs.h"
    29 #include "auth/auth.h"
     28#include "librpc/gen_ndr/ndr_drsuapi.h"
     29#include "librpc/gen_ndr/ndr_security.h"
     30#include "libcli/security/security.h"
     31#include "libcli/security/session.h"
    3032#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
    3133#include "rpc_server/dcerpc_server_proto.h"
    3234#include "../libcli/drsuapi/drsuapi.h"
    33 #include "libcli/security/security.h"
     35#include "lib/util/binsearch.h"
     36#include "lib/util/tsort.h"
     37#include "auth/session.h"
     38#include "dsdb/common/util.h"
     39
     40/*
     41  build a DsReplicaObjectIdentifier from a ldb msg
     42 */
     43static struct drsuapi_DsReplicaObjectIdentifier *get_object_identifier(TALLOC_CTX *mem_ctx,
     44                                                                       struct ldb_message *msg)
     45{
     46        struct drsuapi_DsReplicaObjectIdentifier *identifier;
     47        struct dom_sid *sid;
     48
     49        identifier = talloc(mem_ctx, struct drsuapi_DsReplicaObjectIdentifier);
     50        if (identifier == NULL) {
     51                return NULL;
     52        }
     53
     54        identifier->dn = ldb_dn_alloc_linearized(identifier, msg->dn);
     55        identifier->guid = samdb_result_guid(msg, "objectGUID");
     56
     57        sid = samdb_result_dom_sid(identifier, msg, "objectSid");
     58        if (sid) {
     59                identifier->sid = *sid;
     60        } else {
     61                ZERO_STRUCT(identifier->sid);
     62        }
     63        return identifier;
     64}
     65
     66static int udv_compare(const struct GUID *guid1, struct GUID guid2)
     67{
     68        return GUID_compare(guid1, &guid2);
     69}
     70
     71/*
     72  see if we can filter an attribute using the uptodateness_vector
     73 */
     74static bool udv_filter(const struct drsuapi_DsReplicaCursorCtrEx *udv,
     75                       const struct GUID *originating_invocation_id,
     76                       uint64_t originating_usn)
     77{
     78        const struct drsuapi_DsReplicaCursor *c;
     79        if (udv == NULL) return false;
     80        BINARY_ARRAY_SEARCH(udv->cursors, udv->count, source_dsa_invocation_id,
     81                            originating_invocation_id, udv_compare, c);
     82        if (c && originating_usn <= c->highest_usn) {
     83                return true;
     84        }
     85        return false;
     86       
     87}
     88
     89static int attid_cmp(enum drsuapi_DsAttributeId a1, enum drsuapi_DsAttributeId a2)
     90{
     91        if (a1 == a2) return 0;
     92        return ((uint32_t)a1) > ((uint32_t)a2) ? 1 : -1;
     93}
     94
     95/*
     96  check if an attribute is in a partial_attribute_set
     97 */
     98static bool check_partial_attribute_set(const struct dsdb_attribute *sa,
     99                                        struct drsuapi_DsPartialAttributeSet *pas)
     100{
     101        enum drsuapi_DsAttributeId *result;
     102        BINARY_ARRAY_SEARCH_V(pas->attids, pas->num_attids, (enum drsuapi_DsAttributeId)sa->attributeID_id,
     103                              attid_cmp, result);
     104        return result != NULL;
     105}
     106
    34107
    35108/*
     
    40113                                          struct ldb_context *sam_ctx,
    41114                                          struct ldb_dn *ncRoot_dn,
     115                                          bool   is_schema_nc,
    42116                                          struct dsdb_schema *schema,
    43117                                          DATA_BLOB *session_key,
    44118                                          uint64_t highest_usn,
    45                                           uint32_t replica_flags)
     119                                          uint32_t replica_flags,
     120                                          struct drsuapi_DsPartialAttributeSet *partial_attribute_set,
     121                                          struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector,
     122                                          enum drsuapi_DsExtendedOperation extended_op)
    46123{
    47124        const struct ldb_val *md_value;
    48         int i, n;
    49         struct ldb_dn *obj_dn;
     125        uint32_t i, n;
    50126        struct replPropertyMetaDataBlob md;
    51         struct dom_sid *sid;
    52127        uint32_t rid = 0;
    53128        enum ndr_err_code ndr_err;
     
    55130        const char *rdn;
    56131        const struct dsdb_attribute *rdn_sa;
    57 
    58         if (ldb_dn_compare(ncRoot_dn, msg->dn) == 0) {
     132        unsigned int instanceType;
     133        struct dsdb_syntax_ctx syntax_ctx;
     134
     135        /* make dsdb sytanx context for conversions */
     136        dsdb_syntax_ctx_init(&syntax_ctx, sam_ctx, schema);
     137        syntax_ctx.is_schema_nc = is_schema_nc;
     138
     139        instanceType = ldb_msg_find_attr_as_uint(msg, "instanceType", 0);
     140        if (instanceType & INSTANCE_TYPE_IS_NC_HEAD) {
    59141                obj->is_nc_prefix = true;
    60142                obj->parent_object_guid = NULL;
    61143        } else {
    62                 struct ldb_dn *parent_dn;
    63                 uint32_t instance_type;
    64 
    65                 instance_type = ldb_msg_find_attr_as_uint(msg, "instanceType", 0);
    66                 if (instance_type & INSTANCE_TYPE_IS_NC_HEAD) {
    67                         struct ldb_result *res;
    68                         int ret;
    69                         char *dnstr = ldb_dn_get_linearized(msg->dn);
    70                         msg->dn = ldb_dn_new(msg, sam_ctx, dnstr);
    71                         /* we need to re-search the msg, to avoid the
    72                          * broken dual message problems with our
    73                          * partitions implementation */
    74                         DEBUG(6,(__location__ ": Re-fetching subref %s\n",
    75                                  ldb_dn_get_linearized(msg->dn)));
    76                         ret = drsuapi_search_with_extended_dn(sam_ctx, msg, &res,
    77                                                               msg->dn, LDB_SCOPE_BASE, NULL,
    78                                                               NULL, NULL);
    79                         if (ret != LDB_SUCCESS || res->count < 1) {
    80                                 DEBUG(0,(__location__ ": Failed to reload subref head %s in %s\n",
    81                                          ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(ncRoot_dn)));
    82                                 return WERR_DS_DRA_INTERNAL_ERROR;
    83                         }
    84                         msg = res->msgs[0];
    85                 }
    86 
    87                 parent_dn = ldb_dn_copy(msg, msg->dn);
    88144                obj->is_nc_prefix = false;
    89145                obj->parent_object_guid = talloc(obj, struct GUID);
    90                 if (parent_dn == NULL) {
     146                if (obj->parent_object_guid == NULL) {
    91147                        return WERR_DS_DRA_INTERNAL_ERROR;
    92148                }
    93                 if (ldb_dn_remove_child_components(parent_dn, 1) != true) {
    94                         DEBUG(0,(__location__ ": Unable to remove DN component\n"));
     149                *obj->parent_object_guid = samdb_result_guid(msg, "parentGUID");
     150                if (GUID_all_zero(obj->parent_object_guid)) {
     151                        DEBUG(0,(__location__ ": missing parentGUID for %s\n",
     152                                 ldb_dn_get_linearized(msg->dn)));
    95153                        return WERR_DS_DRA_INTERNAL_ERROR;
    96154                }
    97                 if (dsdb_find_guid_by_dn(sam_ctx, parent_dn, obj->parent_object_guid) != LDB_SUCCESS) {
    98                         DEBUG(0,(__location__ ": Unable to find parent DN %s %s\n",
    99                                  ldb_dn_get_linearized(msg->dn), ldb_dn_get_linearized(parent_dn)));
    100                 }
    101                 talloc_free(parent_dn);
    102155        }
    103156        obj->next_object = NULL;
     
    109162        }
    110163
    111         ndr_err = ndr_pull_struct_blob(md_value, obj,
    112                                        lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")), &md,
     164        if (instanceType & INSTANCE_TYPE_UNINSTANT) {
     165                /* don't send uninstantiated objects */
     166                return WERR_OK;
     167        }
     168
     169        ndr_err = ndr_pull_struct_blob(md_value, obj, &md,
    113170                                       (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
    114171        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    135192        obj->meta_data_ctr = talloc(obj, struct drsuapi_DsReplicaMetaDataCtr);
    136193        attids = talloc_array(obj, uint32_t, md.ctr.ctr1.count);
     194
     195        obj->object.identifier = get_object_identifier(obj, msg);
     196        if (obj->object.identifier == NULL) {
     197                return WERR_NOMEM;
     198        }
     199        dom_sid_split_rid(NULL, &obj->object.identifier->sid, NULL, &rid);
    137200       
    138201        obj->meta_data_ctr->meta_data = talloc_array(obj, struct drsuapi_DsReplicaMetaData, md.ctr.ctr1.count);
    139202        for (n=i=0; i<md.ctr.ctr1.count; i++) {
     203                const struct dsdb_attribute *sa;
     204                bool force_attribute = false;
     205
    140206                /* if the attribute has not changed, and it is not the
    141207                   instanceType then don't include it */
    142208                if (md.ctr.ctr1.array[i].local_usn < highest_usn &&
    143                     md.ctr.ctr1.array[i].attid != DRSUAPI_ATTRIBUTE_instanceType) continue;
     209                    extended_op != DRSUAPI_EXOP_REPL_SECRET &&
     210                    md.ctr.ctr1.array[i].attid != DRSUAPI_ATTID_instanceType) continue;
     211
    144212                /* don't include the rDN */
    145213                if (md.ctr.ctr1.array[i].attid == rdn_sa->attributeID_id) continue;
     214
     215                sa = dsdb_attribute_by_attributeID_id(schema, md.ctr.ctr1.array[i].attid);
     216                if (!sa) {
     217                        DEBUG(0,(__location__ ": Failed to find attribute in schema for attrid %u mentioned in replPropertyMetaData of %s\n",
     218                                 (unsigned int)md.ctr.ctr1.array[i].attid,
     219                                 ldb_dn_get_linearized(msg->dn)));
     220                        return WERR_DS_DRA_INTERNAL_ERROR;             
     221                }
     222
     223                if (sa->linkID) {
     224                        struct ldb_message_element *el;
     225                        el = ldb_msg_find_element(msg, sa->lDAPDisplayName);
     226                        if (el && el->num_values && dsdb_dn_is_upgraded_link_val(&el->values[0])) {
     227                                /* don't send upgraded links inline */
     228                                continue;
     229                        }
     230                }
     231
     232                if (extended_op == DRSUAPI_EXOP_REPL_SECRET &&
     233                    !dsdb_attr_in_rodc_fas(sa)) {
     234                        force_attribute = true;
     235                        DEBUG(4,("Forcing attribute %s in %s\n",
     236                                 sa->lDAPDisplayName, ldb_dn_get_linearized(msg->dn)));
     237                }
     238
     239                /* filter by uptodateness_vector */
     240                if (md.ctr.ctr1.array[i].attid != DRSUAPI_ATTID_instanceType &&
     241                    !force_attribute &&
     242                    udv_filter(uptodateness_vector,
     243                               &md.ctr.ctr1.array[i].originating_invocation_id,
     244                               md.ctr.ctr1.array[i].originating_usn)) {
     245                        continue;
     246                }
     247
     248                /* filter by partial_attribute_set */
     249                if (partial_attribute_set && !check_partial_attribute_set(sa, partial_attribute_set)) {
     250                        continue;
     251                }
     252
    146253                obj->meta_data_ctr->meta_data[n].originating_change_time = md.ctr.ctr1.array[i].originating_change_time;
    147254                obj->meta_data_ctr->meta_data[n].version = md.ctr.ctr1.array[i].version;
     
    152259        }
    153260
    154         /*
    155           note that if n==0 we still need to send the change, as it
    156           could be a rename, which changes the uSNChanged, but not any
    157           of the replicated attributes
    158          */
     261        /* ignore it if its an empty change. Note that renames always
     262         * change the 'name' attribute, so they won't be ignored by
     263         * this */
     264        if (n == 0 ||
     265            (n == 1 && attids[0] == DRSUAPI_ATTID_instanceType)) {
     266                talloc_free(obj->meta_data_ctr);
     267                obj->meta_data_ctr = NULL;
     268                return WERR_OK;
     269        }
    159270
    160271        obj->meta_data_ctr->count = n;
    161 
    162         obj->object.identifier = talloc(obj, struct drsuapi_DsReplicaObjectIdentifier);
    163         obj_dn = ldb_msg_find_attr_as_dn(sam_ctx, obj, msg, "distinguishedName");
    164         obj->object.identifier->dn = ldb_dn_get_linearized(obj_dn);
    165         obj->object.identifier->guid = samdb_result_guid(msg, "objectGUID");
    166         sid = samdb_result_dom_sid(obj, msg, "objectSid");
    167         if (sid) {
    168                 dom_sid_split_rid(NULL, sid, NULL, &rid);
    169                 obj->object.identifier->sid = *sid;
    170         } else {
    171                 ZERO_STRUCT(obj->object.identifier->sid);
    172         }
    173272
    174273        obj->object.flags = DRSUAPI_DS_REPLICA_OBJECT_FROM_MASTER;
     
    194293                el = ldb_msg_find_element(msg, sa->lDAPDisplayName);
    195294                if (el == NULL) {
    196                         DEBUG(0,("No element '%s' for attributeID %u in message\n",
     295                        /* this happens for attributes that have been removed */
     296                        DEBUG(5,("No element '%s' for attributeID %u in message\n",
    197297                                 sa->lDAPDisplayName, attids[i]));
    198298                        ZERO_STRUCT(obj->object.attribute_ctr.attributes[i]);
    199                         obj->object.attribute_ctr.attributes[i].attid = attids[i];
     299                        obj->object.attribute_ctr.attributes[i].attid =
     300                                        dsdb_attribute_get_attid(sa, syntax_ctx.is_schema_nc);
    200301                } else {
    201                         werr = dsdb_attribute_ldb_to_drsuapi(sam_ctx, schema, el, obj,
    202                                                              &obj->object.attribute_ctr.attributes[i]);
     302                        werr = sa->syntax->ldb_to_drsuapi(&syntax_ctx, sa, el, obj,
     303                                                          &obj->object.attribute_ctr.attributes[i]);
    203304                        if (!W_ERROR_IS_OK(werr)) {
    204305                                DEBUG(0,("Unable to convert %s to DRS object - %s\n",
     
    206307                                return werr;
    207308                        }
    208                         /* if DRSUAPI_DS_REPLICA_NEIGHBOUR_SPECIAL_SECRET_PROCESSING is set
     309                        /* if DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING is set
    209310                         * check if attribute is secret and send a null value
    210                          * TODO: check if we can make this in the database layer
    211311                         */
    212                         if ((replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_SPECIAL_SECRET_PROCESSING)
    213                             == DRSUAPI_DS_REPLICA_NEIGHBOUR_SPECIAL_SECRET_PROCESSING) {
     312                        if (replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) {
    214313                                drsuapi_process_secret_attribute(&obj->object.attribute_ctr.attributes[i],
    215314                                                                 &obj->meta_data_ctr->meta_data[i]);
     
    230329}
    231330
     331
    232332/*
    233   load replUpToDateVector from a DN
     333  add one linked attribute from an object to the list of linked
     334  attributes in a getncchanges request
    234335 */
    235 static WERROR load_udv(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
    236                        struct ldb_dn *dn, struct replUpToDateVectorBlob *ouv)
    237 {
    238         const char *attrs[] = { "replUpToDateVector", NULL };
    239         struct ldb_result *res = NULL;
     336static WERROR get_nc_changes_add_la(TALLOC_CTX *mem_ctx,
     337                                    struct ldb_context *sam_ctx,
     338                                    const struct dsdb_schema *schema,
     339                                    const struct dsdb_attribute *sa,
     340                                    struct ldb_message *msg,
     341                                    struct dsdb_dn *dsdb_dn,
     342                                    struct drsuapi_DsReplicaLinkedAttribute **la_list,
     343                                    uint32_t *la_count)
     344{
     345        struct drsuapi_DsReplicaLinkedAttribute *la;
     346        bool active;
     347        NTSTATUS status;
     348        WERROR werr;
     349
     350        (*la_list) = talloc_realloc(mem_ctx, *la_list, struct drsuapi_DsReplicaLinkedAttribute, (*la_count)+1);
     351        W_ERROR_HAVE_NO_MEMORY(*la_list);
     352
     353        la = &(*la_list)[*la_count];
     354
     355        la->identifier = get_object_identifier(*la_list, msg);
     356        W_ERROR_HAVE_NO_MEMORY(la->identifier);
     357
     358        active = (dsdb_dn_rmd_flags(dsdb_dn->dn) & DSDB_RMD_FLAG_DELETED) == 0;
     359
     360        la->attid = sa->attributeID_id;
     361        la->flags = active?DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE:0;
     362
     363        status = dsdb_get_extended_dn_nttime(dsdb_dn->dn, &la->originating_add_time, "RMD_ADDTIME");
     364        if (!NT_STATUS_IS_OK(status)) {
     365                return ntstatus_to_werror(status);
     366        }
     367        status = dsdb_get_extended_dn_uint32(dsdb_dn->dn, &la->meta_data.version, "RMD_VERSION");
     368        if (!NT_STATUS_IS_OK(status)) {
     369                return ntstatus_to_werror(status);
     370        }
     371        status = dsdb_get_extended_dn_nttime(dsdb_dn->dn, &la->meta_data.originating_change_time, "RMD_CHANGETIME");
     372        if (!NT_STATUS_IS_OK(status)) {
     373                return ntstatus_to_werror(status);
     374        }
     375        status = dsdb_get_extended_dn_guid(dsdb_dn->dn, &la->meta_data.originating_invocation_id, "RMD_INVOCID");
     376        if (!NT_STATUS_IS_OK(status)) {
     377                return ntstatus_to_werror(status);
     378        }
     379        status = dsdb_get_extended_dn_uint64(dsdb_dn->dn, &la->meta_data.originating_usn, "RMD_ORIGINATING_USN");
     380        if (!NT_STATUS_IS_OK(status)) {
     381                return ntstatus_to_werror(status);
     382        }
     383
     384        werr = dsdb_dn_la_to_blob(sam_ctx, sa, schema, *la_list, dsdb_dn, &la->value.blob);
     385        W_ERROR_NOT_OK_RETURN(werr);
     386
     387        (*la_count)++;
     388        return WERR_OK;
     389}
     390
     391
     392/*
     393  add linked attributes from an object to the list of linked
     394  attributes in a getncchanges request
     395 */
     396static WERROR get_nc_changes_add_links(struct ldb_context *sam_ctx,
     397                                       TALLOC_CTX *mem_ctx,
     398                                       struct ldb_dn *ncRoot_dn,
     399                                       struct dsdb_schema *schema,
     400                                       uint64_t highest_usn,
     401                                       uint32_t replica_flags,
     402                                       struct ldb_message *msg,
     403                                       struct drsuapi_DsReplicaLinkedAttribute **la_list,
     404                                       uint32_t *la_count,
     405                                       struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector)
     406{
     407        unsigned int i;
    240408        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
    241         struct ldb_message_element *el;
    242         enum ndr_err_code ndr_err;
    243 
    244         ZERO_STRUCTP(ouv);
    245 
    246         if (ldb_search(sam_ctx, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, NULL) != LDB_SUCCESS ||
    247             res->count < 1) {
    248                 DEBUG(0,("load_udv: failed to read partition object\n"));
    249                 talloc_free(tmp_ctx);
    250                 return WERR_DS_DRA_INTERNAL_ERROR;
    251         }
    252 
    253         el = ldb_msg_find_element(res->msgs[0], "replUpToDateVector");
    254         if (el == NULL || el->num_values < 1) {
    255                 talloc_free(tmp_ctx);
    256                 ouv->version = 2;
    257                 return WERR_OK;
    258         }
    259 
    260         ndr_err = ndr_pull_struct_blob(&el->values[0],
    261                                        mem_ctx, lp_iconv_convenience(ldb_get_opaque(sam_ctx, "loadparm")),
    262                                        ouv,
    263                                        (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob);
     409        uint64_t uSNChanged = ldb_msg_find_attr_as_int(msg, "uSNChanged", -1);
     410
     411        for (i=0; i<msg->num_elements; i++) {
     412                struct ldb_message_element *el = &msg->elements[i];
     413                const struct dsdb_attribute *sa;
     414                unsigned int j;
     415
     416                sa = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
     417
     418                if (!sa || sa->linkID == 0 || (sa->linkID & 1)) {
     419                        /* we only want forward links */
     420                        continue;
     421                }
     422
     423                if (el->num_values && !dsdb_dn_is_upgraded_link_val(&el->values[0])) {
     424                        /* its an old style link, it will have been
     425                         * sent in the main replication data */
     426                        continue;
     427                }
     428
     429                for (j=0; j<el->num_values; j++) {
     430                        struct dsdb_dn *dsdb_dn;
     431                        uint64_t local_usn;
     432                        NTSTATUS status;
     433                        WERROR werr;
     434
     435                        dsdb_dn = dsdb_dn_parse(tmp_ctx, sam_ctx, &el->values[j], sa->syntax->ldap_oid);
     436                        if (dsdb_dn == NULL) {
     437                                DEBUG(1,(__location__ ": Failed to parse DN for %s in %s\n",
     438                                         el->name, ldb_dn_get_linearized(msg->dn)));
     439                                talloc_free(tmp_ctx);
     440                                return WERR_DS_DRA_INTERNAL_ERROR;
     441                        }
     442
     443                        status = dsdb_get_extended_dn_uint64(dsdb_dn->dn, &local_usn, "RMD_LOCAL_USN");
     444                        if (!NT_STATUS_IS_OK(status)) {
     445                                /* this can happen for attributes
     446                                   given to us with old style meta
     447                                   data */
     448                                continue;
     449                        }
     450
     451                        if (local_usn > uSNChanged) {
     452                                DEBUG(1,(__location__ ": uSNChanged less than RMD_LOCAL_USN for %s on %s\n",
     453                                         el->name, ldb_dn_get_linearized(msg->dn)));
     454                                talloc_free(tmp_ctx);
     455                                return WERR_DS_DRA_INTERNAL_ERROR;
     456                        }
     457
     458                        if (local_usn < highest_usn) {
     459                                continue;
     460                        }
     461
     462                        werr = get_nc_changes_add_la(mem_ctx, sam_ctx, schema, sa, msg,
     463                                                     dsdb_dn, la_list, la_count);
     464                        if (!W_ERROR_IS_OK(werr)) {
     465                                talloc_free(tmp_ctx);
     466                                return werr;
     467                        }
     468                }
     469        }
     470
    264471        talloc_free(tmp_ctx);
    265         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    266                 DEBUG(0,(__location__ ": Failed to parse replUpToDateVector for %s\n",
    267                          ldb_dn_get_linearized(dn)));
    268                 return WERR_DS_DRA_INTERNAL_ERROR;
    269         }
    270        
    271472        return WERR_OK;
    272        
    273473}
    274474
     
    280480                                 struct drsuapi_DsReplicaCursor2CtrEx *udv)
    281481{
     482        int ret;
     483
     484        udv->version = 2;
     485        udv->reserved1 = 0;
     486        udv->reserved2 = 0;
     487
     488        ret = dsdb_load_udv_v2(sam_ctx, ncRoot_dn, udv, &udv->cursors, &udv->count);
     489        if (ret != LDB_SUCCESS) {
     490                DEBUG(0,(__location__ ": Failed to load UDV for %s - %s\n",
     491                         ldb_dn_get_linearized(ncRoot_dn), ldb_errstring(sam_ctx)));
     492                return WERR_DS_DRA_INTERNAL_ERROR;
     493        }
     494       
     495        return WERR_OK;
     496}
     497
     498
     499/* comparison function for linked attributes - see CompareLinks() in
     500 * MS-DRSR section 4.1.10.5.17 */
     501static int linked_attribute_compare(const struct drsuapi_DsReplicaLinkedAttribute *la1,
     502                                    const struct drsuapi_DsReplicaLinkedAttribute *la2,
     503                                    struct ldb_context *sam_ctx)
     504{
     505        int c;
    282506        WERROR werr;
    283         struct drsuapi_DsReplicaCursor2 *tmp_cursor;
    284         uint64_t highest_commited_usn;
    285         NTTIME now;
    286         time_t t = time(NULL);
     507        TALLOC_CTX *tmp_ctx;
     508        const struct dsdb_schema *schema;
     509        const struct dsdb_attribute *schema_attrib;
     510        struct dsdb_dn *dn1, *dn2;
     511        struct GUID guid1, guid2;
     512        NTSTATUS status;
     513
     514        c = GUID_compare(&la1->identifier->guid,
     515                         &la2->identifier->guid);
     516        if (c != 0) return c;
     517
     518        if (la1->attid != la2->attid) {
     519                return la1->attid < la2->attid? -1:1;
     520        }
     521
     522        if ((la1->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE) !=
     523            (la2->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)) {
     524                return (la1->flags & DRSUAPI_DS_LINKED_ATTRIBUTE_FLAG_ACTIVE)? 1:-1;
     525        }
     526
     527        /* we need to get the target GUIDs to compare */
     528        tmp_ctx = talloc_new(sam_ctx);
     529
     530        schema = dsdb_get_schema(sam_ctx, tmp_ctx);
     531        schema_attrib = dsdb_attribute_by_attributeID_id(schema, la1->attid);
     532
     533        werr = dsdb_dn_la_from_blob(sam_ctx, schema_attrib, schema, tmp_ctx, la1->value.blob, &dn1);
     534        if (!W_ERROR_IS_OK(werr)) {
     535                DEBUG(0,(__location__ ": Bad la1 blob in sort\n"));
     536                talloc_free(tmp_ctx);
     537                return 0;
     538        }
     539
     540        werr = dsdb_dn_la_from_blob(sam_ctx, schema_attrib, schema, tmp_ctx, la2->value.blob, &dn2);
     541        if (!W_ERROR_IS_OK(werr)) {
     542                DEBUG(0,(__location__ ": Bad la2 blob in sort\n"));
     543                talloc_free(tmp_ctx);
     544                return 0;
     545        }
     546
     547        status = dsdb_get_extended_dn_guid(dn1->dn, &guid1, "GUID");
     548        if (!NT_STATUS_IS_OK(status)) {
     549                DEBUG(0,(__location__ ": Bad la1 guid in sort\n"));
     550                talloc_free(tmp_ctx);
     551                return 0;
     552        }
     553        status = dsdb_get_extended_dn_guid(dn2->dn, &guid2, "GUID");
     554        if (!NT_STATUS_IS_OK(status)) {
     555                DEBUG(0,(__location__ ": Bad la2 guid in sort\n"));
     556                talloc_free(tmp_ctx);
     557                return 0;
     558        }
     559
     560        talloc_free(tmp_ctx);
     561
     562        return GUID_compare(&guid1, &guid2);
     563}
     564
     565
     566/*
     567  sort the objects we send by tree order
     568 */
     569static int site_res_cmp_parent_order(struct ldb_message **m1, struct ldb_message **m2)
     570{
     571        return ldb_dn_compare((*m2)->dn, (*m1)->dn);
     572}
     573
     574/*
     575  sort the objects we send first by uSNChanged
     576 */
     577static int site_res_cmp_usn_order(struct ldb_message **m1, struct ldb_message **m2)
     578{
     579        unsigned usnchanged1, usnchanged2;
     580        unsigned cn1, cn2;
     581        cn1 = ldb_dn_get_comp_num((*m1)->dn);
     582        cn2 = ldb_dn_get_comp_num((*m2)->dn);
     583        if (cn1 != cn2) {
     584                return cn1 > cn2 ? 1 : -1;
     585        }
     586        usnchanged1 = ldb_msg_find_attr_as_uint(*m1, "uSNChanged", 0);
     587        usnchanged2 = ldb_msg_find_attr_as_uint(*m2, "uSNChanged", 0);
     588        if (usnchanged1 == usnchanged2) {
     589                return 0;
     590        }
     591        return usnchanged1 > usnchanged2 ? 1 : -1;
     592}
     593
     594
     595/*
     596  handle a DRSUAPI_EXOP_FSMO_RID_ALLOC call
     597 */
     598static WERROR getncchanges_rid_alloc(struct drsuapi_bind_state *b_state,
     599                                     TALLOC_CTX *mem_ctx,
     600                                     struct drsuapi_DsGetNCChangesRequest10 *req10,
     601                                     struct drsuapi_DsGetNCChangesCtr6 *ctr6)
     602{
     603        struct ldb_dn *rid_manager_dn, *fsmo_role_dn, *req_dn;
    287604        int ret;
    288         struct replUpToDateVectorBlob ouv;
    289 
    290         werr = load_udv(sam_ctx, udv, ncRoot_dn, &ouv);
     605        struct ldb_context *ldb = b_state->sam_ctx;
     606        struct ldb_result *ext_res;
     607        struct ldb_dn *base_dn;
     608        struct dsdb_fsmo_extended_op *exop;
     609
     610        /*
     611          steps:
     612            - verify that the DN being asked for is the RID Manager DN
     613            - verify that we are the RID Manager
     614         */
     615
     616        /* work out who is the RID Manager */
     617        ret = samdb_rid_manager_dn(ldb, mem_ctx, &rid_manager_dn);
     618        if (ret != LDB_SUCCESS) {
     619                DEBUG(0, (__location__ ": Failed to find RID Manager object - %s\n", ldb_errstring(ldb)));
     620                return WERR_DS_DRA_INTERNAL_ERROR;
     621        }
     622
     623        req_dn = drs_ObjectIdentifier_to_dn(mem_ctx, ldb, req10->naming_context);
     624        if (!ldb_dn_validate(req_dn) ||
     625            ldb_dn_compare(req_dn, rid_manager_dn) != 0) {
     626                /* that isn't the RID Manager DN */
     627                DEBUG(0,(__location__ ": RID Alloc request for wrong DN %s\n",
     628                         drs_ObjectIdentifier_to_string(mem_ctx, req10->naming_context)));
     629                ctr6->extended_ret = DRSUAPI_EXOP_ERR_MISMATCH;
     630                return WERR_OK;
     631        }
     632
     633        /* find the DN of the RID Manager */
     634        ret = samdb_reference_dn(ldb, mem_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn);
     635        if (ret != LDB_SUCCESS) {
     636                DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s\n",
     637                         ldb_errstring(ldb)));
     638                ctr6->extended_ret = DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER;
     639                return WERR_DS_DRA_INTERNAL_ERROR;
     640        }
     641
     642        if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
     643                /* we're not the RID Manager - go away */
     644                DEBUG(0,(__location__ ": RID Alloc request when not RID Manager\n"));
     645                ctr6->extended_ret = DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER;
     646                return WERR_OK;
     647        }
     648
     649        exop = talloc(mem_ctx, struct dsdb_fsmo_extended_op);
     650        W_ERROR_HAVE_NO_MEMORY(exop);
     651
     652        exop->fsmo_info = req10->fsmo_info;
     653        exop->destination_dsa_guid = req10->destination_dsa_guid;
     654
     655        ret = ldb_transaction_start(ldb);
     656        if (ret != LDB_SUCCESS) {
     657                DEBUG(0,(__location__ ": Failed transaction start - %s\n",
     658                         ldb_errstring(ldb)));
     659                return WERR_DS_DRA_INTERNAL_ERROR;
     660        }
     661
     662        /*
     663         * FIXME (kim): this is a temp hack to return just few object,
     664         * but not the whole domain NC.
     665         * We should remove this hack and implement a 'scope'
     666         * building function to return just the set of object
     667         * documented for DRSUAPI_EXOP_FSMO_RID_ALLOC extended_op
     668         */
     669        ldb_sequence_number(ldb, LDB_SEQ_HIGHEST_SEQ, &req10->highwatermark.highest_usn);
     670
     671        ret = ldb_extended(ldb, DSDB_EXTENDED_ALLOCATE_RID_POOL, exop, &ext_res);
     672        if (ret != LDB_SUCCESS) {
     673                DEBUG(0,(__location__ ": Failed extended allocation RID pool operation - %s\n",
     674                         ldb_errstring(ldb)));
     675                ldb_transaction_cancel(ldb);
     676                return WERR_DS_DRA_INTERNAL_ERROR;
     677        }
     678
     679        ret = ldb_transaction_commit(ldb);
     680        if (ret != LDB_SUCCESS) {
     681                DEBUG(0,(__location__ ": Failed transaction commit - %s\n",
     682                         ldb_errstring(ldb)));
     683                return WERR_DS_DRA_INTERNAL_ERROR;
     684        }
     685
     686        talloc_free(ext_res);
     687
     688        base_dn = ldb_get_default_basedn(ldb);
     689
     690        DEBUG(2,("Allocated RID pool for server %s\n",
     691                 GUID_string(mem_ctx, &req10->destination_dsa_guid)));
     692
     693        ctr6->extended_ret = DRSUAPI_EXOP_ERR_SUCCESS;
     694
     695        return WERR_OK;
     696}
     697
     698/*
     699  return an array of SIDs from a ldb_message given an attribute name
     700  assumes the SIDs are in extended DN format
     701 */
     702static WERROR samdb_result_sid_array_dn(struct ldb_context *sam_ctx,
     703                                        struct ldb_message *msg,
     704                                        TALLOC_CTX *mem_ctx,
     705                                        const char *attr,
     706                                        const struct dom_sid ***sids)
     707{
     708        struct ldb_message_element *el;
     709        unsigned int i;
     710
     711        el = ldb_msg_find_element(msg, attr);
     712        if (!el) {
     713                *sids = NULL;
     714                return WERR_OK;
     715        }
     716
     717        (*sids) = talloc_array(mem_ctx, const struct dom_sid *, el->num_values + 1);
     718        W_ERROR_HAVE_NO_MEMORY(*sids);
     719
     720        for (i=0; i<el->num_values; i++) {
     721                struct ldb_dn *dn = ldb_dn_from_ldb_val(mem_ctx, sam_ctx, &el->values[i]);
     722                NTSTATUS status;
     723                struct dom_sid *sid;
     724
     725                sid = talloc(*sids, struct dom_sid);
     726                W_ERROR_HAVE_NO_MEMORY(sid);
     727                status = dsdb_get_extended_dn_sid(dn, sid, "SID");
     728                if (!NT_STATUS_IS_OK(status)) {
     729                        return WERR_INTERNAL_DB_CORRUPTION;
     730                }
     731                (*sids)[i] = sid;
     732        }
     733        (*sids)[i] = NULL;
     734
     735        return WERR_OK;
     736}
     737
     738
     739/*
     740  return an array of SIDs from a ldb_message given an attribute name
     741  assumes the SIDs are in NDR form
     742 */
     743static WERROR samdb_result_sid_array_ndr(struct ldb_context *sam_ctx,
     744                                         struct ldb_message *msg,
     745                                         TALLOC_CTX *mem_ctx,
     746                                         const char *attr,
     747                                         const struct dom_sid ***sids)
     748{
     749        struct ldb_message_element *el;
     750        unsigned int i;
     751
     752        el = ldb_msg_find_element(msg, attr);
     753        if (!el) {
     754                *sids = NULL;
     755                return WERR_OK;
     756        }
     757
     758        (*sids) = talloc_array(mem_ctx, const struct dom_sid *, el->num_values + 1);
     759        W_ERROR_HAVE_NO_MEMORY(*sids);
     760
     761        for (i=0; i<el->num_values; i++) {
     762                enum ndr_err_code ndr_err;
     763                struct dom_sid *sid;
     764
     765                sid = talloc(*sids, struct dom_sid);
     766                W_ERROR_HAVE_NO_MEMORY(sid);
     767
     768                ndr_err = ndr_pull_struct_blob(&el->values[i], sid, sid,
     769                                               (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
     770                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     771                        return WERR_INTERNAL_DB_CORRUPTION;
     772                }
     773                (*sids)[i] = sid;
     774        }
     775        (*sids)[i] = NULL;
     776
     777        return WERR_OK;
     778}
     779
     780/*
     781  see if any SIDs in list1 are in list2
     782 */
     783static bool sid_list_match(const struct dom_sid **list1, const struct dom_sid **list2)
     784{
     785        unsigned int i, j;
     786        /* do we ever have enough SIDs here to worry about O(n^2) ? */
     787        for (i=0; list1[i]; i++) {
     788                for (j=0; list2[j]; j++) {
     789                        if (dom_sid_equal(list1[i], list2[j])) {
     790                                return true;
     791                        }
     792                }
     793        }
     794        return false;
     795}
     796
     797/*
     798  handle a DRSUAPI_EXOP_REPL_SECRET call
     799 */
     800static WERROR getncchanges_repl_secret(struct drsuapi_bind_state *b_state,
     801                                       TALLOC_CTX *mem_ctx,
     802                                       struct drsuapi_DsGetNCChangesRequest10 *req10,
     803                                       struct dom_sid *user_sid,
     804                                       struct drsuapi_DsGetNCChangesCtr6 *ctr6)
     805{
     806        struct drsuapi_DsReplicaObjectIdentifier *ncRoot = req10->naming_context;
     807        struct ldb_dn *obj_dn, *rodc_dn, *krbtgt_link_dn;
     808        int ret;
     809        const char *rodc_attrs[] = { "msDS-KrbTgtLink", "msDS-NeverRevealGroup", "msDS-RevealOnDemandGroup", NULL };
     810        const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
     811        struct ldb_result *rodc_res, *obj_res;
     812        const struct dom_sid **never_reveal_sids, **reveal_sids, **token_sids;
     813        WERROR werr;
     814
     815        DEBUG(3,(__location__ ": DRSUAPI_EXOP_REPL_SECRET extended op on %s\n",
     816                 drs_ObjectIdentifier_to_string(mem_ctx, ncRoot)));
     817
     818        /*
     819         * we need to work out if we will allow this RODC to
     820         * replicate the secrets for this object
     821         *
     822         * see 4.1.10.5.14 GetRevealSecretsPolicyForUser for details
     823         * of this function
     824         */
     825
     826        if (b_state->sam_ctx_system == NULL) {
     827                /* this operation needs system level access */
     828                ctr6->extended_ret = DRSUAPI_EXOP_ERR_ACCESS_DENIED;
     829                return WERR_DS_DRA_SOURCE_DISABLED;
     830        }
     831
     832        obj_dn = drs_ObjectIdentifier_to_dn(mem_ctx, b_state->sam_ctx_system, ncRoot);
     833        if (!ldb_dn_validate(obj_dn)) goto failed;
     834
     835        rodc_dn = ldb_dn_new_fmt(mem_ctx, b_state->sam_ctx_system, "<SID=%s>",
     836                                 dom_sid_string(mem_ctx, user_sid));
     837        if (!ldb_dn_validate(rodc_dn)) goto failed;
     838
     839        /* do the two searches we need */
     840        ret = dsdb_search_dn(b_state->sam_ctx_system, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
     841                             DSDB_SEARCH_SHOW_EXTENDED_DN);
     842        if (ret != LDB_SUCCESS || rodc_res->count != 1) goto failed;
     843
     844        ret = dsdb_search_dn(b_state->sam_ctx_system, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
     845        if (ret != LDB_SUCCESS || obj_res->count != 1) goto failed;
     846
     847        /* if the object SID is equal to the user_sid, allow */
     848        if (dom_sid_equal(user_sid,
     849                          samdb_result_dom_sid(mem_ctx, obj_res->msgs[0], "objectSid"))) {
     850                goto allowed;
     851        }
     852
     853        /* an RODC is allowed to get its own krbtgt account secrets */
     854        krbtgt_link_dn = samdb_result_dn(b_state->sam_ctx_system, mem_ctx,
     855                                         rodc_res->msgs[0], "msDS-KrbTgtLink", NULL);
     856        if (krbtgt_link_dn != NULL &&
     857            ldb_dn_compare(obj_dn, krbtgt_link_dn) == 0) {
     858                goto allowed;
     859        }
     860
     861        /* but it isn't allowed to get anyone elses krbtgt secrets */
     862        if (samdb_result_dn(b_state->sam_ctx_system, mem_ctx,
     863                            obj_res->msgs[0], "msDS-KrbTgtLinkBL", NULL)) {
     864                goto denied;
     865        }
     866
     867        if (ldb_msg_find_attr_as_uint(obj_res->msgs[0],
     868                                      "userAccountControl", 0) &
     869            UF_INTERDOMAIN_TRUST_ACCOUNT) {
     870                goto denied;
     871        }
     872
     873        werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0],
     874                                         mem_ctx, "msDS-NeverRevealGroup", &never_reveal_sids);
    291875        if (!W_ERROR_IS_OK(werr)) {
    292                 return werr;
    293         }
    294        
    295         ret = ldb_sequence_number(sam_ctx, LDB_SEQ_HIGHEST_SEQ, &highest_commited_usn);
     876                goto denied;
     877        }
     878
     879        werr = samdb_result_sid_array_dn(b_state->sam_ctx_system, rodc_res->msgs[0],
     880                                         mem_ctx, "msDS-RevealOnDemandGroup", &reveal_sids);
     881        if (!W_ERROR_IS_OK(werr)) {
     882                goto denied;
     883        }
     884
     885        werr = samdb_result_sid_array_ndr(b_state->sam_ctx_system, obj_res->msgs[0],
     886                                         mem_ctx, "tokenGroups", &token_sids);
     887        if (!W_ERROR_IS_OK(werr) || token_sids==NULL) {
     888                goto denied;
     889        }
     890
     891        if (never_reveal_sids &&
     892            sid_list_match(token_sids, never_reveal_sids)) {
     893                goto denied;
     894        }
     895
     896        if (reveal_sids &&
     897            sid_list_match(token_sids, reveal_sids)) {
     898                goto allowed;
     899        }
     900
     901        /* default deny */
     902denied:
     903        DEBUG(2,(__location__ ": Denied RODC secret replication for %s by RODC %s\n",
     904                 ldb_dn_get_linearized(obj_dn), ldb_dn_get_linearized(rodc_res->msgs[0]->dn)));
     905        ctr6->extended_ret = DRSUAPI_EXOP_ERR_NONE;
     906        return WERR_DS_DRA_ACCESS_DENIED;
     907
     908allowed:
     909        DEBUG(2,(__location__ ": Allowed RODC secret replication for %s by RODC %s\n",
     910                 ldb_dn_get_linearized(obj_dn), ldb_dn_get_linearized(rodc_res->msgs[0]->dn)));
     911        ctr6->extended_ret = DRSUAPI_EXOP_ERR_SUCCESS;
     912        req10->highwatermark.highest_usn = 0;
     913        return WERR_OK;
     914
     915failed:
     916        DEBUG(2,(__location__ ": Failed RODC secret replication for %s by RODC %s\n",
     917                 ldb_dn_get_linearized(obj_dn), dom_sid_string(mem_ctx, user_sid)));
     918        ctr6->extended_ret = DRSUAPI_EXOP_ERR_NONE;
     919        return WERR_DS_DRA_BAD_DN;
     920}
     921
     922
     923/*
     924  handle a DRSUAPI_EXOP_REPL_OBJ call
     925 */
     926static WERROR getncchanges_repl_obj(struct drsuapi_bind_state *b_state,
     927                                    TALLOC_CTX *mem_ctx,
     928                                    struct drsuapi_DsGetNCChangesRequest10 *req10,
     929                                    struct dom_sid *user_sid,
     930                                    struct drsuapi_DsGetNCChangesCtr6 *ctr6)
     931{
     932        struct drsuapi_DsReplicaObjectIdentifier *ncRoot = req10->naming_context;
     933
     934        DEBUG(3,(__location__ ": DRSUAPI_EXOP_REPL_OBJ extended op on %s\n",
     935                 drs_ObjectIdentifier_to_string(mem_ctx, ncRoot)));
     936
     937        ctr6->extended_ret = DRSUAPI_EXOP_ERR_SUCCESS;
     938        req10->highwatermark.highest_usn = 0;
     939        return WERR_OK;
     940}
     941
     942
     943/*
     944  handle DRSUAPI_EXOP_FSMO_REQ_ROLE,
     945  DRSUAPI_EXOP_FSMO_RID_REQ_ROLE,
     946  and DRSUAPI_EXOP_FSMO_REQ_PDC calls
     947 */
     948static WERROR getncchanges_change_master(struct drsuapi_bind_state *b_state,
     949                                         TALLOC_CTX *mem_ctx,
     950                                         struct drsuapi_DsGetNCChangesRequest10 *req10,
     951                                         struct drsuapi_DsGetNCChangesCtr6 *ctr6)
     952{
     953        struct ldb_dn *fsmo_role_dn, *req_dn, *ntds_dn;
     954        int ret;
     955        unsigned int i;
     956        struct ldb_context *ldb = b_state->sam_ctx;
     957        struct ldb_message *msg;
     958
     959        /*
     960          steps:
     961            - verify that the client dn exists
     962            - verify that we are the current master
     963         */
     964
     965        req_dn = drs_ObjectIdentifier_to_dn(mem_ctx, ldb, req10->naming_context);
     966        if (!ldb_dn_validate(req_dn)) {
     967                /* that is not a valid dn */
     968                DEBUG(0,(__location__ ": FSMO role transfer request for invalid DN %s\n",
     969                         drs_ObjectIdentifier_to_string(mem_ctx, req10->naming_context)));
     970                ctr6->extended_ret = DRSUAPI_EXOP_ERR_MISMATCH;
     971                return WERR_OK;
     972        }
     973
     974        /* retrieve the current role owner */
     975        ret = samdb_reference_dn(ldb, mem_ctx, req_dn, "fSMORoleOwner", &fsmo_role_dn);
    296976        if (ret != LDB_SUCCESS) {
    297                 return WERR_DS_DRA_INTERNAL_ERROR;
    298         }
    299 
    300         tmp_cursor = talloc(udv, struct drsuapi_DsReplicaCursor2);
    301         tmp_cursor->source_dsa_invocation_id = *(samdb_ntds_invocation_id(sam_ctx));
    302         tmp_cursor->highest_usn = highest_commited_usn;
    303         unix_to_nt_time(&now, t);
    304         tmp_cursor->last_sync_success = now;
    305 
    306         udv->count = ouv.ctr.ctr2.count + 1;
    307         udv->cursors = talloc_steal(udv, ouv.ctr.ctr2.cursors);
    308         udv->cursors = talloc_realloc(udv, udv->cursors, struct drsuapi_DsReplicaCursor2, udv->count);
    309         if (!udv->cursors) {
    310                 return WERR_DS_DRA_INTERNAL_ERROR;
    311         }
    312         udv->cursors[udv->count - 1] = *tmp_cursor;
    313        
    314         qsort(udv->cursors, udv->count,
    315               sizeof(struct drsuapi_DsReplicaCursor2),
    316               (comparison_fn_t)drsuapi_DsReplicaCursor2_compare);
     977                DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in context - %s\n",
     978                         ldb_errstring(ldb)));
     979                ctr6->extended_ret = DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER;
     980                return WERR_DS_DRA_INTERNAL_ERROR;
     981        }
     982
     983        if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
     984                /* we're not the current owner - go away */
     985                DEBUG(0,(__location__ ": FSMO transfer request when not owner\n"));
     986                ctr6->extended_ret = DRSUAPI_EXOP_ERR_FSMO_NOT_OWNER;
     987                return WERR_OK;
     988        }
     989
     990        /* change the current master */
     991        msg = ldb_msg_new(ldb);
     992        W_ERROR_HAVE_NO_MEMORY(msg);
     993        msg->dn = drs_ObjectIdentifier_to_dn(msg, ldb, req10->naming_context);
     994        W_ERROR_HAVE_NO_MEMORY(msg->dn);
     995
     996        ret = dsdb_find_dn_by_guid(ldb, msg, &req10->destination_dsa_guid, &ntds_dn);
     997        if (ret != LDB_SUCCESS) {
     998                DEBUG(0, (__location__ ": Unable to find NTDS object for guid %s - %s\n",
     999                          GUID_string(mem_ctx, &req10->destination_dsa_guid), ldb_errstring(ldb)));
     1000                talloc_free(msg);
     1001                return WERR_DS_DRA_INTERNAL_ERROR;
     1002        }
     1003
     1004        ret = ldb_msg_add_string(msg, "fSMORoleOwner", ldb_dn_get_linearized(ntds_dn));
     1005        if (ret != 0) {
     1006                talloc_free(msg);
     1007                return WERR_DS_DRA_INTERNAL_ERROR;
     1008        }
     1009
     1010        for (i=0;i<msg->num_elements;i++) {
     1011                msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
     1012        }
     1013
     1014        ret = ldb_transaction_start(ldb);
     1015        if (ret != LDB_SUCCESS) {
     1016                DEBUG(0,(__location__ ": Failed transaction start - %s\n",
     1017                         ldb_errstring(ldb)));
     1018                return WERR_DS_DRA_INTERNAL_ERROR;
     1019        }
     1020
     1021        ret = ldb_modify(ldb, msg);
     1022        if (ret != LDB_SUCCESS) {
     1023                DEBUG(0,(__location__ ": Failed to change current owner - %s\n",
     1024                         ldb_errstring(ldb)));
     1025                ldb_transaction_cancel(ldb);
     1026                return WERR_DS_DRA_INTERNAL_ERROR;
     1027        }
     1028
     1029        ret = ldb_transaction_commit(ldb);
     1030        if (ret != LDB_SUCCESS) {
     1031                DEBUG(0,(__location__ ": Failed transaction commit - %s\n",
     1032                         ldb_errstring(ldb)));
     1033                return WERR_DS_DRA_INTERNAL_ERROR;
     1034        }
     1035
     1036        ctr6->extended_ret = DRSUAPI_EXOP_ERR_SUCCESS;
    3171037
    3181038        return WERR_OK;
     
    3211041/* state of a partially completed getncchanges call */
    3221042struct drsuapi_getncchanges_state {
    323         struct ldb_result *site_res;
    324         uint32_t num_sent;
    325         struct ldb_context *sam_ctx;
     1043        struct GUID *guids;
     1044        uint32_t num_records;
     1045        uint32_t num_processed;
    3261046        struct ldb_dn *ncRoot_dn;
    327         uint32_t min_usn;
     1047        bool is_schema_nc;
     1048        uint64_t min_usn;
     1049        uint64_t highest_usn;
     1050        struct ldb_dn *last_dn;
     1051        struct drsuapi_DsReplicaLinkedAttribute *la_list;
     1052        uint32_t la_count;
     1053        bool la_sorted;
     1054        uint32_t la_idx;
     1055        struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector;
    3281056};
     1057
     1058/*
     1059  see if this getncchanges request includes a request to reveal secret information
     1060 */
     1061static WERROR dcesrv_drsuapi_is_reveal_secrets_request(struct drsuapi_bind_state *b_state,
     1062                                                       struct drsuapi_DsGetNCChangesRequest10 *req10,
     1063                                                       bool *is_secret_request)
     1064{
     1065        enum drsuapi_DsExtendedOperation exop;
     1066        uint32_t i;
     1067        struct dsdb_schema *schema;
     1068
     1069        *is_secret_request = true;
     1070
     1071        exop = req10->extended_op;
     1072
     1073        switch (exop) {
     1074        case DRSUAPI_EXOP_FSMO_REQ_ROLE:
     1075        case DRSUAPI_EXOP_FSMO_RID_ALLOC:
     1076        case DRSUAPI_EXOP_FSMO_RID_REQ_ROLE:
     1077        case DRSUAPI_EXOP_FSMO_REQ_PDC:
     1078        case DRSUAPI_EXOP_FSMO_ABANDON_ROLE:
     1079                /* FSMO exops can reveal secrets */
     1080                *is_secret_request = true;
     1081                return WERR_OK;
     1082        case DRSUAPI_EXOP_REPL_SECRET:
     1083        case DRSUAPI_EXOP_REPL_OBJ:
     1084        case DRSUAPI_EXOP_NONE:
     1085                break;
     1086        }
     1087
     1088        if (req10->replica_flags & DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING) {
     1089                *is_secret_request = false;
     1090                return WERR_OK;
     1091        }
     1092
     1093        if (exop == DRSUAPI_EXOP_REPL_SECRET ||
     1094            req10->partial_attribute_set == NULL) {
     1095                /* they want secrets */
     1096                *is_secret_request = true;
     1097                return WERR_OK;
     1098        }
     1099
     1100        schema = dsdb_get_schema(b_state->sam_ctx, NULL);
     1101
     1102        /* check the attributes they asked for */
     1103        for (i=0; i<req10->partial_attribute_set->num_attids; i++) {
     1104                const struct dsdb_attribute *sa;
     1105                sa = dsdb_attribute_by_attributeID_id(schema, req10->partial_attribute_set->attids[i]);
     1106                if (sa == NULL) {
     1107                        return WERR_DS_DRA_SCHEMA_MISMATCH;
     1108                }
     1109                if (!dsdb_attr_in_rodc_fas(sa)) {
     1110                        *is_secret_request = true;
     1111                        return WERR_OK;
     1112                }
     1113        }
     1114
     1115        /* check the attributes they asked for */
     1116        for (i=0; i<req10->partial_attribute_set_ex->num_attids; i++) {
     1117                const struct dsdb_attribute *sa;
     1118                sa = dsdb_attribute_by_attributeID_id(schema, req10->partial_attribute_set_ex->attids[i]);
     1119                if (sa == NULL) {
     1120                        return WERR_DS_DRA_SCHEMA_MISMATCH;
     1121                }
     1122                if (!dsdb_attr_in_rodc_fas(sa)) {
     1123                        *is_secret_request = true;
     1124                        return WERR_OK;
     1125                }
     1126        }
     1127
     1128        *is_secret_request = false;
     1129        return WERR_OK;
     1130}
     1131
     1132
     1133/*
     1134  map from req8 to req10
     1135 */
     1136static struct drsuapi_DsGetNCChangesRequest10 *
     1137getncchanges_map_req8(TALLOC_CTX *mem_ctx,
     1138                      struct drsuapi_DsGetNCChangesRequest8 *req8)
     1139{
     1140        struct drsuapi_DsGetNCChangesRequest10 *req10 = talloc_zero(mem_ctx,
     1141                                                                    struct drsuapi_DsGetNCChangesRequest10);
     1142        if (req10 == NULL) {
     1143                return NULL;
     1144        }
     1145
     1146        req10->destination_dsa_guid = req8->destination_dsa_guid;
     1147        req10->source_dsa_invocation_id = req8->source_dsa_invocation_id;
     1148        req10->naming_context = req8->naming_context;
     1149        req10->highwatermark = req8->highwatermark;
     1150        req10->uptodateness_vector = req8->uptodateness_vector;
     1151        req10->replica_flags = req8->replica_flags;
     1152        req10->max_object_count = req8->max_object_count;
     1153        req10->max_ndr_size = req8->max_ndr_size;
     1154        req10->extended_op = req8->extended_op;
     1155        req10->fsmo_info = req8->fsmo_info;
     1156        req10->partial_attribute_set = req8->partial_attribute_set;
     1157        req10->partial_attribute_set_ex = req8->partial_attribute_set_ex;
     1158        req10->mapping_ctr = req8->mapping_ctr;
     1159
     1160        return req10;
     1161}
     1162
    3291163
    3301164/*
    3311165  drsuapi_DsGetNCChanges
     1166
     1167  see MS-DRSR 4.1.10.5.2 for basic logic of this function
    3321168*/
    3331169WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    3361172        struct drsuapi_DsReplicaObjectIdentifier *ncRoot;
    3371173        int ret;
    338         int i;
     1174        uint32_t i;
    3391175        struct dsdb_schema *schema;
    3401176        struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
     
    3421178        NTSTATUS status;
    3431179        DATA_BLOB session_key;
    344         const char *attrs[] = { "*", "distinguishedName", NULL };
     1180        const char *attrs[] = { "uSNChanged",
     1181                                "objectGUID" ,
     1182                                NULL };
    3451183        WERROR werr;
    3461184        struct dcesrv_handle *h;
    3471185        struct drsuapi_bind_state *b_state;     
    3481186        struct drsuapi_getncchanges_state *getnc_state;
     1187        struct drsuapi_DsGetNCChangesRequest10 *req10;
     1188        uint32_t options;
     1189        uint32_t max_objects;
     1190        uint32_t max_links;
     1191        uint32_t link_count = 0;
     1192        uint32_t link_total = 0;
     1193        uint32_t link_given = 0;
     1194        struct ldb_dn *search_dn = NULL;
     1195        bool am_rodc, null_scope=false;
     1196        enum security_user_level security_level;
     1197        struct ldb_context *sam_ctx;
     1198        struct dom_sid *user_sid;
     1199        bool is_secret_request;
    3491200
    3501201        DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
    3511202        b_state = h->data;
     1203
     1204        sam_ctx = b_state->sam_ctx_system?b_state->sam_ctx_system:b_state->sam_ctx;
    3521205
    3531206        *r->out.level_out = 6;
     
    3611214        r->out.ctr->ctr6.uptodateness_vector = NULL;
    3621215
    363         /* Check request revision. */
    364         if (r->in.level != 8) {
     1216        /* a RODC doesn't allow for any replication */
     1217        ret = samdb_rodc(sam_ctx, &am_rodc);
     1218        if (ret == LDB_SUCCESS && am_rodc) {
     1219                DEBUG(0,(__location__ ": DsGetNCChanges attempt on RODC\n"));
     1220                return WERR_DS_DRA_SOURCE_DISABLED;
     1221        }
     1222
     1223        /* Check request revision.
     1224         */
     1225        switch (r->in.level) {
     1226        case 8:
     1227                req10 = getncchanges_map_req8(mem_ctx, &r->in.req->req8);
     1228                if (req10 == NULL) {
     1229                        return WERR_NOMEM;
     1230                }
     1231                break;
     1232        case 10:
     1233                req10 = &r->in.req->req10;
     1234                break;
     1235        default:
     1236                DEBUG(0,(__location__ ": Request for DsGetNCChanges with unsupported level %u\n",
     1237                         r->in.level));
    3651238                return WERR_REVISION_MISMATCH;
    3661239        }
    3671240
     1241
    3681242        /* Perform access checks. */
    369         if (r->in.req->req8.naming_context == NULL) {
     1243        /* TODO: we need to support a sync on a specific non-root
     1244         * DN. We'll need to find the real partition root here */
     1245        ncRoot = req10->naming_context;
     1246        if (ncRoot == NULL) {
     1247                DEBUG(0,(__location__ ": Request for DsGetNCChanges with no NC\n"));
    3701248                return WERR_DS_DRA_INVALID_PARAMETER;
    3711249        }
    3721250
    373         ncRoot = r->in.req->req8.naming_context;
    374         if (ncRoot == NULL) {
    375                 return WERR_DS_DRA_BAD_NC;
    376         }
    377 
    378         if ((r->in.req->req8.replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_SYNC_PACKET)
    379             == DRSUAPI_DS_REPLICA_NEIGHBOUR_FULL_SYNC_PACKET) {
    380                 /* Ignore the _in_ uptpdateness vector*/
    381                 r->in.req->req8.uptodateness_vector = NULL;
    382         }
    383 
    384         werr = drs_security_level_check(dce_call, "DsGetNCChanges");
     1251        if (samdb_ntds_options(sam_ctx, &options) != LDB_SUCCESS) {
     1252                return WERR_DS_DRA_INTERNAL_ERROR;
     1253        }
     1254       
     1255        if ((options & DS_NTDSDSA_OPT_DISABLE_OUTBOUND_REPL) &&
     1256            !(req10->replica_flags & DRSUAPI_DRS_SYNC_FORCED)) {
     1257                return WERR_DS_DRA_SOURCE_DISABLED;
     1258        }
     1259
     1260        user_sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
     1261
     1262        werr = drs_security_access_check_nc_root(b_state->sam_ctx,
     1263                                                 mem_ctx,
     1264                                                 dce_call->conn->auth_state.session_info->security_token,
     1265                                                 req10->naming_context,
     1266                                                 GUID_DRS_GET_CHANGES);
    3851267        if (!W_ERROR_IS_OK(werr)) {
    3861268                return werr;
    3871269        }
    3881270
     1271        werr = dcesrv_drsuapi_is_reveal_secrets_request(b_state, req10, &is_secret_request);
     1272        if (!W_ERROR_IS_OK(werr)) {
     1273                return werr;
     1274        }
     1275        if (is_secret_request && req10->extended_op != DRSUAPI_EXOP_REPL_SECRET) {
     1276                werr = drs_security_access_check_nc_root(b_state->sam_ctx,
     1277                                                         mem_ctx,
     1278                                                         dce_call->conn->auth_state.session_info->security_token,
     1279                                                         req10->naming_context,
     1280                                                         GUID_DRS_GET_ALL_CHANGES);
     1281                if (!W_ERROR_IS_OK(werr)) {
     1282                        return werr;
     1283                }
     1284        }
     1285
     1286        /* for non-administrator replications, check that they have
     1287           given the correct source_dsa_invocation_id */
     1288        security_level = security_session_user_level(dce_call->conn->auth_state.session_info,
     1289                                                     samdb_domain_sid(sam_ctx));
     1290        if (security_level == SECURITY_RO_DOMAIN_CONTROLLER) {
     1291                if (req10->replica_flags & DRSUAPI_DRS_WRIT_REP) {
     1292                        /* we rely on this flag being unset for RODC requests */
     1293                        req10->replica_flags &= ~DRSUAPI_DRS_WRIT_REP;
     1294                }
     1295        }
     1296
     1297        if (req10->replica_flags & DRSUAPI_DRS_FULL_SYNC_PACKET) {
     1298                /* Ignore the _in_ uptpdateness vector*/
     1299                req10->uptodateness_vector = NULL;
     1300        }
     1301
    3891302        getnc_state = b_state->getncchanges_state;
     1303
     1304        /* see if a previous replication has been abandoned */
     1305        if (getnc_state) {
     1306                struct ldb_dn *new_dn = drs_ObjectIdentifier_to_dn(getnc_state, sam_ctx, ncRoot);
     1307                if (ldb_dn_compare(new_dn, getnc_state->ncRoot_dn) != 0) {
     1308                        DEBUG(0,(__location__ ": DsGetNCChanges 2nd replication on different DN %s %s (last_dn %s)\n",
     1309                                 ldb_dn_get_linearized(new_dn),
     1310                                 ldb_dn_get_linearized(getnc_state->ncRoot_dn),
     1311                                 ldb_dn_get_linearized(getnc_state->last_dn)));
     1312                        talloc_free(getnc_state);
     1313                        getnc_state = NULL;
     1314                }
     1315        }
     1316
    3901317        if (getnc_state == NULL) {
    3911318                getnc_state = talloc_zero(b_state, struct drsuapi_getncchanges_state);
     
    3941321                }
    3951322                b_state->getncchanges_state = getnc_state;
    396 
     1323                getnc_state->ncRoot_dn = drs_ObjectIdentifier_to_dn(getnc_state, sam_ctx, ncRoot);
     1324
     1325                /* find out if we are to replicate Schema NC */
     1326                ret = ldb_dn_compare(getnc_state->ncRoot_dn,
     1327                                     ldb_get_schema_basedn(b_state->sam_ctx));
     1328                getnc_state->is_schema_nc = (0 == ret);
    3971329
    3981330                /*
    399                  * connect to the samdb. TODO: We need to check that the caller
    400                  * has the rights to do this. This exposes all attributes,
    401                  * including all passwords.
     1331                 * This is the first replication cycle and it is
     1332                 * a good place to handle extended operations
     1333                 *
     1334                 * FIXME: we don't fully support extended operations yet
    4021335                 */
    403                 getnc_state->sam_ctx = samdb_connect(getnc_state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
    404                                                      system_session(getnc_state, dce_call->conn->dce_ctx->lp_ctx));
    405                 if (!getnc_state->sam_ctx) {
    406                         return WERR_FOOBAR;
    407                 }
     1336                switch (req10->extended_op) {
     1337                case DRSUAPI_EXOP_NONE:
     1338                        break;
     1339                case DRSUAPI_EXOP_FSMO_RID_ALLOC:
     1340                        werr = getncchanges_rid_alloc(b_state, mem_ctx, req10, &r->out.ctr->ctr6);
     1341                        W_ERROR_NOT_OK_RETURN(werr);
     1342                        search_dn = ldb_get_default_basedn(sam_ctx);
     1343                        break;
     1344                case DRSUAPI_EXOP_REPL_SECRET:
     1345                        werr = getncchanges_repl_secret(b_state, mem_ctx, req10, user_sid, &r->out.ctr->ctr6);
     1346                        r->out.result = werr;
     1347                        W_ERROR_NOT_OK_RETURN(werr);
     1348                        break;
     1349                case DRSUAPI_EXOP_FSMO_REQ_ROLE:
     1350                        werr = getncchanges_change_master(b_state, mem_ctx, req10, &r->out.ctr->ctr6);
     1351                        W_ERROR_NOT_OK_RETURN(werr);
     1352                        break;
     1353                case DRSUAPI_EXOP_FSMO_RID_REQ_ROLE:
     1354                        werr = getncchanges_change_master(b_state, mem_ctx, req10, &r->out.ctr->ctr6);
     1355                        W_ERROR_NOT_OK_RETURN(werr);
     1356                        break;
     1357                case DRSUAPI_EXOP_FSMO_REQ_PDC:
     1358                        werr = getncchanges_change_master(b_state, mem_ctx, req10, &r->out.ctr->ctr6);
     1359                        W_ERROR_NOT_OK_RETURN(werr);
     1360                        break;
     1361                case DRSUAPI_EXOP_REPL_OBJ:
     1362                        werr = getncchanges_repl_obj(b_state, mem_ctx, req10, user_sid, &r->out.ctr->ctr6);
     1363                        r->out.result = werr;
     1364                        W_ERROR_NOT_OK_RETURN(werr);
     1365                        break;
     1366
     1367                case DRSUAPI_EXOP_FSMO_ABANDON_ROLE:
     1368
     1369                        DEBUG(0,(__location__ ": Request for DsGetNCChanges unsupported extended op 0x%x\n",
     1370                                 (unsigned)req10->extended_op));
     1371                        return WERR_DS_DRA_NOT_SUPPORTED;
     1372                }
     1373        }
     1374
     1375        if (!ldb_dn_validate(getnc_state->ncRoot_dn) ||
     1376            ldb_dn_is_null(getnc_state->ncRoot_dn)) {
     1377                DEBUG(0,(__location__ ": Bad DN '%s'\n",
     1378                         drs_ObjectIdentifier_to_string(mem_ctx, ncRoot)));
     1379                return WERR_DS_DRA_INVALID_PARAMETER;
    4081380        }
    4091381
     
    4151387        }
    4161388
    417         if (getnc_state->site_res == NULL) {
     1389        /*
     1390           TODO: MS-DRSR section 4.1.10.1.1
     1391           Work out if this is the start of a new cycle */
     1392
     1393        if (getnc_state->guids == NULL) {
    4181394                char* search_filter;
    4191395                enum ldb_scope scope = LDB_SCOPE_SUBTREE;
    420 
    421                 getnc_state->min_usn = r->in.req->req8.highwatermark.highest_usn;
     1396                const char *extra_filter;
     1397                struct ldb_result *search_res;
     1398
     1399                if (req10->extended_op == DRSUAPI_EXOP_REPL_OBJ ||
     1400                    req10->extended_op == DRSUAPI_EXOP_REPL_SECRET) {
     1401                        scope = LDB_SCOPE_BASE;
     1402                }
     1403
     1404                extra_filter = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "object filter");
     1405
     1406                getnc_state->min_usn = req10->highwatermark.highest_usn;
    4221407
    4231408                /* Construct response. */
     
    4251410                                                "(uSNChanged>=%llu)",
    4261411                                                (unsigned long long)(getnc_state->min_usn+1));
    427                
    428                 if (r->in.req->req8.replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_CRITICAL_ONLY) {
     1412       
     1413                if (extra_filter) {
     1414                        search_filter = talloc_asprintf(mem_ctx, "(&%s(%s))", search_filter, extra_filter);
     1415                }
     1416
     1417                if (req10->replica_flags & DRSUAPI_DRS_CRITICAL_ONLY) {
    4291418                        search_filter = talloc_asprintf(mem_ctx,
    4301419                                                        "(&%s(isCriticalSystemObject=TRUE))",
     
    4321421                }
    4331422               
    434                 getnc_state->ncRoot_dn = ldb_dn_new(getnc_state, getnc_state->sam_ctx, ncRoot->dn);
    435                 if (r->in.req->req8.replica_flags & DRSUAPI_DS_REPLICA_NEIGHBOUR_ASYNC_REP) {
     1423                if (req10->replica_flags & DRSUAPI_DRS_ASYNC_REP) {
    4361424                        scope = LDB_SCOPE_BASE;
    4371425                }
    4381426               
    439                 DEBUG(6,(__location__ ": getncchanges on %s using filter %s\n",
     1427                if (!search_dn) {
     1428                        search_dn = getnc_state->ncRoot_dn;
     1429                }
     1430
     1431                DEBUG(2,(__location__ ": getncchanges on %s using filter %s\n",
    4401432                         ldb_dn_get_linearized(getnc_state->ncRoot_dn), search_filter));
    441                 ret = drsuapi_search_with_extended_dn(getnc_state->sam_ctx, getnc_state, &getnc_state->site_res,
    442                                                       getnc_state->ncRoot_dn, scope, attrs,
    443                                                       "distinguishedName",
     1433                ret = drsuapi_search_with_extended_dn(sam_ctx, getnc_state, &search_res,
     1434                                                      search_dn, scope, attrs,
    4441435                                                      search_filter);
    4451436                if (ret != LDB_SUCCESS) {
    4461437                        return WERR_DS_DRA_INTERNAL_ERROR;
    4471438                }
     1439
     1440                if (req10->replica_flags & DRSUAPI_DRS_GET_ANC) {
     1441                        TYPESAFE_QSORT(search_res->msgs,
     1442                                       search_res->count,
     1443                                       site_res_cmp_parent_order);
     1444                } else {
     1445                        TYPESAFE_QSORT(search_res->msgs,
     1446                                       search_res->count,
     1447                                       site_res_cmp_usn_order);
     1448                }
     1449
     1450                /* extract out the GUIDs list */
     1451                getnc_state->num_records = search_res->count;
     1452                getnc_state->guids = talloc_array(getnc_state, struct GUID, getnc_state->num_records);
     1453                W_ERROR_HAVE_NO_MEMORY(getnc_state->guids);
     1454
     1455                for (i=0; i<getnc_state->num_records; i++) {
     1456                        getnc_state->guids[i] = samdb_result_guid(search_res->msgs[i], "objectGUID");
     1457                        if (GUID_all_zero(&getnc_state->guids[i])) {
     1458                                DEBUG(2,("getncchanges: bad objectGUID from %s\n", ldb_dn_get_linearized(search_res->msgs[i]->dn)));
     1459                                return WERR_DS_DRA_INTERNAL_ERROR;
     1460                        }
     1461                }
     1462
     1463
     1464                talloc_free(search_res);
     1465
     1466                getnc_state->uptodateness_vector = talloc_steal(getnc_state, req10->uptodateness_vector);
     1467                if (getnc_state->uptodateness_vector) {
     1468                        /* make sure its sorted */
     1469                        TYPESAFE_QSORT(getnc_state->uptodateness_vector->cursors,
     1470                                       getnc_state->uptodateness_vector->count,
     1471                                       drsuapi_DsReplicaCursor_compare);
     1472                }
    4481473        }
    4491474
    4501475        /* Prefix mapping */
    451         schema = dsdb_get_schema(getnc_state->sam_ctx);
     1476        schema = dsdb_get_schema(sam_ctx, mem_ctx);
    4521477        if (!schema) {
    4531478                DEBUG(0,("No schema in sam_ctx\n"));
     
    4581483        *r->out.ctr->ctr6.naming_context = *ncRoot;
    4591484
    460         if (dsdb_find_guid_by_dn(getnc_state->sam_ctx, getnc_state->ncRoot_dn,
     1485        if (dsdb_find_guid_by_dn(sam_ctx, getnc_state->ncRoot_dn,
    4611486                                 &r->out.ctr->ctr6.naming_context->guid) != LDB_SUCCESS) {
    4621487                DEBUG(0,(__location__ ": Failed to find GUID of ncRoot_dn %s\n",
     
    4661491
    4671492        /* find the SID if there is one */
    468         dsdb_find_sid_by_dn(getnc_state->sam_ctx, getnc_state->ncRoot_dn, &r->out.ctr->ctr6.naming_context->sid);
     1493        dsdb_find_sid_by_dn(sam_ctx, getnc_state->ncRoot_dn, &r->out.ctr->ctr6.naming_context->sid);
    4691494
    4701495        dsdb_get_oid_mappings_drsuapi(schema, true, mem_ctx, &ctr);
    4711496        r->out.ctr->ctr6.mapping_ctr = *ctr;
    4721497
    473         r->out.ctr->ctr6.source_dsa_guid = *(samdb_ntds_objectGUID(getnc_state->sam_ctx));
    474         r->out.ctr->ctr6.source_dsa_invocation_id = *(samdb_ntds_invocation_id(getnc_state->sam_ctx));
    475 
    476         r->out.ctr->ctr6.old_highwatermark = r->in.req->req8.highwatermark;
    477         r->out.ctr->ctr6.new_highwatermark = r->in.req->req8.highwatermark;
     1498        r->out.ctr->ctr6.source_dsa_guid = *(samdb_ntds_objectGUID(sam_ctx));
     1499        r->out.ctr->ctr6.source_dsa_invocation_id = *(samdb_ntds_invocation_id(sam_ctx));
     1500
     1501        r->out.ctr->ctr6.old_highwatermark = req10->highwatermark;
     1502        r->out.ctr->ctr6.new_highwatermark = req10->highwatermark;
    4781503
    4791504        r->out.ctr->ctr6.first_object = NULL;
    4801505        currentObject = &r->out.ctr->ctr6.first_object;
    4811506
    482         for(i=getnc_state->num_sent;
    483             i<getnc_state->site_res->count &&
    484                     (r->out.ctr->ctr6.object_count < r->in.req->req8.max_object_count);
     1507        /* use this to force single objects at a time, which is useful
     1508         * for working out what object is giving problems
     1509         */
     1510        max_objects = lpcfg_parm_int(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "max object sync", 1000);
     1511        if (req10->max_object_count < max_objects) {
     1512                max_objects = req10->max_object_count;
     1513        }
     1514        /*
     1515         * TODO: work out how the maximum should be calculated
     1516         */
     1517        max_links = lpcfg_parm_int(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "max link sync", 1500);
     1518
     1519        for (i=getnc_state->num_processed;
     1520             i<getnc_state->num_records &&
     1521                     !null_scope &&
     1522                     (r->out.ctr->ctr6.object_count < max_objects);
    4851523            i++) {
    4861524                int uSN;
    4871525                struct drsuapi_DsReplicaObjectListItemEx *obj;
     1526                struct ldb_message *msg;
     1527                static const char * const msg_attrs[] = {
     1528                                            "*",
     1529                                            "nTSecurityDescriptor",
     1530                                            "parentGUID",
     1531                                            "replPropertyMetaData",
     1532                                            DSDB_SECRET_ATTRIBUTES,
     1533                                            NULL };
     1534                struct ldb_result *msg_res;
     1535                struct ldb_dn *msg_dn;
     1536
    4881537                obj = talloc_zero(mem_ctx, struct drsuapi_DsReplicaObjectListItemEx);
    489 
    490                 uSN = ldb_msg_find_attr_as_int(getnc_state->site_res->msgs[i], "uSNChanged", -1);
     1538                W_ERROR_HAVE_NO_MEMORY(obj);
     1539
     1540                msg_dn = ldb_dn_new_fmt(obj, sam_ctx, "<GUID=%s>", GUID_string(obj, &getnc_state->guids[i]));
     1541                W_ERROR_HAVE_NO_MEMORY(msg_dn);
     1542
     1543
     1544                /* by re-searching here we avoid having a lot of full
     1545                 * records in memory between calls to getncchanges
     1546                 */
     1547                ret = drsuapi_search_with_extended_dn(sam_ctx, obj, &msg_res,
     1548                                                      msg_dn,
     1549                                                      LDB_SCOPE_BASE, msg_attrs, NULL);
     1550                if (ret != LDB_SUCCESS) {
     1551                        if (ret != LDB_ERR_NO_SUCH_OBJECT) {
     1552                                DEBUG(1,("getncchanges: failed to fetch DN %s - %s\n",
     1553                                         ldb_dn_get_extended_linearized(obj, msg_dn, 1), ldb_errstring(sam_ctx)));
     1554                        }
     1555                        talloc_free(obj);
     1556                        continue;
     1557                }
     1558
     1559                msg = msg_res->msgs[0];
     1560
     1561                werr = get_nc_changes_build_object(obj, msg,
     1562                                                   sam_ctx, getnc_state->ncRoot_dn,
     1563                                                   getnc_state->is_schema_nc,
     1564                                                   schema, &session_key, getnc_state->min_usn,
     1565                                                   req10->replica_flags,
     1566                                                   req10->partial_attribute_set,
     1567                                                   getnc_state->uptodateness_vector,
     1568                                                   req10->extended_op);
     1569                if (!W_ERROR_IS_OK(werr)) {
     1570                        return werr;
     1571                }
     1572
     1573                werr = get_nc_changes_add_links(sam_ctx, getnc_state,
     1574                                                getnc_state->ncRoot_dn,
     1575                                                schema, getnc_state->min_usn,
     1576                                                req10->replica_flags,
     1577                                                msg,
     1578                                                &getnc_state->la_list,
     1579                                                &getnc_state->la_count,
     1580                                                getnc_state->uptodateness_vector);
     1581                if (!W_ERROR_IS_OK(werr)) {
     1582                        return werr;
     1583                }
     1584
     1585                uSN = ldb_msg_find_attr_as_int(msg, "uSNChanged", -1);
    4911586                if (uSN > r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn) {
    4921587                        r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn = uSN;
    4931588                }
    494 
    495                 werr = get_nc_changes_build_object(obj, getnc_state->site_res->msgs[i],
    496                                                    getnc_state->sam_ctx, getnc_state->ncRoot_dn,
    497                                                    schema, &session_key, getnc_state->min_usn,
    498                                                    r->in.req->req8.replica_flags);
    499                 if (!W_ERROR_IS_OK(werr)) {
    500                         return werr;
     1589                if (uSN > getnc_state->highest_usn) {
     1590                        getnc_state->highest_usn = uSN;
    5011591                }
    5021592
    5031593                if (obj->meta_data_ctr == NULL) {
    504                         DEBUG(0,(__location__ ": getncchanges skipping send of object %s\n",
    505                                  ldb_dn_get_linearized(getnc_state->site_res->msgs[i]->dn)));
     1594                        DEBUG(8,(__location__ ": getncchanges skipping send of object %s\n",
     1595                                 ldb_dn_get_linearized(msg->dn)));
    5061596                        /* no attributes to send */
    5071597                        talloc_free(obj);
     
    5131603                *currentObject = obj;
    5141604                currentObject = &obj->next_object;
    515         }
    516 
    517         getnc_state->num_sent += r->out.ctr->ctr6.object_count;
    518 
    519         r->out.ctr->ctr6.nc_object_count = getnc_state->site_res->count;
    520 
    521         if (i < getnc_state->site_res->count) {
     1605
     1606                talloc_free(getnc_state->last_dn);
     1607                getnc_state->last_dn = ldb_dn_copy(getnc_state, msg->dn);
     1608
     1609                DEBUG(8,(__location__ ": replicating object %s\n", ldb_dn_get_linearized(msg->dn)));
     1610
     1611                talloc_free(msg_res);
     1612                talloc_free(msg_dn);
     1613        }
     1614
     1615        getnc_state->num_processed = i;
     1616
     1617        r->out.ctr->ctr6.nc_object_count = getnc_state->num_records;
     1618
     1619        /* the client can us to call UpdateRefs on its behalf to
     1620           re-establish monitoring of the NC */
     1621        if ((req10->replica_flags & (DRSUAPI_DRS_ADD_REF | DRSUAPI_DRS_REF_GCSPN)) &&
     1622            !GUID_all_zero(&req10->destination_dsa_guid)) {
     1623                struct drsuapi_DsReplicaUpdateRefsRequest1 ureq;
     1624                DEBUG(3,("UpdateRefs on getncchanges for %s\n",
     1625                         GUID_string(mem_ctx, &req10->destination_dsa_guid)));
     1626                ureq.naming_context = ncRoot;
     1627                ureq.dest_dsa_dns_name = talloc_asprintf(mem_ctx, "%s._msdcs.%s",
     1628                                                         GUID_string(mem_ctx, &req10->destination_dsa_guid),
     1629                                                         lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx));
     1630                if (!ureq.dest_dsa_dns_name) {
     1631                        return WERR_NOMEM;
     1632                }
     1633                ureq.dest_dsa_guid = req10->destination_dsa_guid;
     1634                ureq.options = DRSUAPI_DRS_ADD_REF |
     1635                        DRSUAPI_DRS_ASYNC_OP |
     1636                        DRSUAPI_DRS_GETCHG_CHECK;
     1637
     1638                /* we also need to pass through the
     1639                   DRSUAPI_DRS_REF_GCSPN bit so that repsTo gets flagged
     1640                   to send notifies using the GC SPN */
     1641                ureq.options |= (req10->replica_flags & DRSUAPI_DRS_REF_GCSPN);
     1642
     1643                werr = drsuapi_UpdateRefs(b_state, mem_ctx, &ureq);
     1644                if (!W_ERROR_IS_OK(werr)) {
     1645                        DEBUG(0,(__location__ ": Failed UpdateRefs in DsGetNCChanges - %s\n",
     1646                                 win_errstr(werr)));
     1647                }
     1648        }
     1649
     1650        /*
     1651         * TODO:
     1652         * This is just a guess, how to calculate the
     1653         * number of linked attributes to send, we need to
     1654         * find out how to do this right.
     1655         */
     1656        if (r->out.ctr->ctr6.object_count >= max_links) {
     1657                max_links = 0;
     1658        } else {
     1659                max_links -= r->out.ctr->ctr6.object_count;
     1660        }
     1661
     1662        link_total = getnc_state->la_count;
     1663
     1664        if (i < getnc_state->num_records) {
    5221665                r->out.ctr->ctr6.more_data = true;
    5231666        } else {
     1667                /* sort the whole array the first time */
     1668                if (!getnc_state->la_sorted) {
     1669                        LDB_TYPESAFE_QSORT(getnc_state->la_list, getnc_state->la_count,
     1670                                           sam_ctx, linked_attribute_compare);
     1671                        getnc_state->la_sorted = true;
     1672                }
     1673
     1674                link_count = getnc_state->la_count - getnc_state->la_idx;
     1675                link_count = MIN(max_links, link_count);
     1676
     1677                r->out.ctr->ctr6.linked_attributes_count = link_count;
     1678                r->out.ctr->ctr6.linked_attributes = getnc_state->la_list + getnc_state->la_idx;
     1679
     1680                getnc_state->la_idx += link_count;
     1681                link_given = getnc_state->la_idx;
     1682
     1683                if (getnc_state->la_idx < getnc_state->la_count) {
     1684                        r->out.ctr->ctr6.more_data = true;
     1685                }
     1686        }
     1687
     1688        if (!r->out.ctr->ctr6.more_data) {
     1689                talloc_steal(mem_ctx, getnc_state->la_list);
     1690
    5241691                r->out.ctr->ctr6.uptodateness_vector = talloc(mem_ctx, struct drsuapi_DsReplicaCursor2CtrEx);
    525                 r->out.ctr->ctr6.uptodateness_vector->version = 2;
    526                 r->out.ctr->ctr6.uptodateness_vector->reserved1 = 0;
    527                 r->out.ctr->ctr6.uptodateness_vector->reserved2 = 0;
    528 
    5291692                r->out.ctr->ctr6.new_highwatermark.highest_usn = r->out.ctr->ctr6.new_highwatermark.tmp_highest_usn;
    5301693
    531                 werr = get_nc_changes_udv(getnc_state->sam_ctx, getnc_state->ncRoot_dn,
     1694                werr = get_nc_changes_udv(sam_ctx, getnc_state->ncRoot_dn,
    5321695                                          r->out.ctr->ctr6.uptodateness_vector);
    5331696                if (!W_ERROR_IS_OK(werr)) {
     
    5391702        }
    5401703
    541         DEBUG(3,("DsGetNCChanges with uSNChanged >= %llu on %s gave %u objects\n",
    542                  (unsigned long long)(r->in.req->req8.highwatermark.highest_usn+1),
    543                  ncRoot->dn, r->out.ctr->ctr6.object_count));
     1704        if (req10->extended_op != DRSUAPI_EXOP_NONE) {
     1705                r->out.ctr->ctr6.uptodateness_vector = NULL;
     1706                r->out.ctr->ctr6.nc_object_count = 0;
     1707                ZERO_STRUCT(r->out.ctr->ctr6.new_highwatermark);
     1708                r->out.ctr->ctr6.extended_ret = DRSUAPI_EXOP_ERR_SUCCESS;
     1709        }
     1710
     1711        DEBUG(r->out.ctr->ctr6.more_data?4:2,
     1712              ("DsGetNCChanges with uSNChanged >= %llu flags 0x%08x on %s gave %u objects (done %u/%u) %u links (done %u/%u (as %s))\n",
     1713               (unsigned long long)(req10->highwatermark.highest_usn+1),
     1714               req10->replica_flags, drs_ObjectIdentifier_to_string(mem_ctx, ncRoot),
     1715               r->out.ctr->ctr6.object_count,
     1716               i, r->out.ctr->ctr6.more_data?getnc_state->num_records:i,
     1717               r->out.ctr->ctr6.linked_attributes_count,
     1718               link_given, link_total,
     1719               dom_sid_string(mem_ctx, user_sid)));
     1720
     1721#if 0
     1722        if (!r->out.ctr->ctr6.more_data && req10->extended_op != DRSUAPI_EXOP_NONE) {
     1723                NDR_PRINT_FUNCTION_DEBUG(drsuapi_DsGetNCChanges, NDR_BOTH, r);
     1724        }
     1725#endif
    5441726
    5451727        return WERR_OK;
  • trunk/server/source4/rpc_server/drsuapi/updaterefs.c

    r414 r745  
    2323#include "rpc_server/dcerpc_server.h"
    2424#include "dsdb/samdb/samdb.h"
    25 #include "auth/auth.h"
     25#include "libcli/security/security.h"
     26#include "libcli/security/session.h"
    2627#include "rpc_server/drsuapi/dcesrv_drsuapi.h"
    27 #include "libcli/security/security.h"
     28#include "auth/session.h"
     29#include "librpc/gen_ndr/ndr_drsuapi.h"
    2830
    2931struct repsTo {
     
    3638 */
    3739static WERROR uref_add_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
    38                             struct ldb_dn *dn, struct repsFromTo1 *dest)
     40                            struct ldb_dn *dn, struct repsFromTo1 *dest,
     41                            uint32_t options)
    3942{
    4043        struct repsTo reps;
    4144        WERROR werr;
     45        unsigned int i;
    4246
    4347        werr = dsdb_loadreps(sam_ctx, mem_ctx, dn, "repsTo", &reps.r, &reps.count);
    4448        if (!W_ERROR_IS_OK(werr)) {
    4549                return werr;
     50        }
     51
     52        for (i=0; i<reps.count; i++) {
     53                if (GUID_compare(&dest->source_dsa_obj_guid,
     54                                 &reps.r[i].ctr.ctr1.source_dsa_obj_guid) == 0) {
     55                        if (options & DRSUAPI_DRS_GETCHG_CHECK) {
     56                                return WERR_OK;
     57                        } else {
     58                                return WERR_DS_DRA_REF_ALREADY_EXISTS;
     59                        }
     60                }
    4661        }
    4762
     
    5368        reps.r[reps.count].version = 1;
    5469        reps.r[reps.count].ctr.ctr1 = *dest;
     70        /* add the GCSPN flag if the client asked for it */
     71        reps.r[reps.count].ctr.ctr1.replica_flags |= (options & DRSUAPI_DRS_REF_GCSPN);
    5572        reps.count++;
    5673
     
    6784 */
    6885static WERROR uref_del_dest(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
    69                             struct ldb_dn *dn, struct GUID *dest_guid)
     86                            struct ldb_dn *dn, struct GUID *dest_guid,
     87                            uint32_t options)
    7088{
    7189        struct repsTo reps;
    7290        WERROR werr;
    73         int i;
     91        unsigned int i;
     92        bool found = false;
    7493
    7594        werr = dsdb_loadreps(sam_ctx, mem_ctx, dn, "repsTo", &reps.r, &reps.count);
     
    84103                        }
    85104                        reps.count--;
     105                        found = true;
    86106                }
    87107        }
     
    92112        }
    93113
     114        if (!found &&
     115            !(options & DRSUAPI_DRS_GETCHG_CHECK) &&
     116            !(options & DRSUAPI_DRS_ADD_REF)) {
     117                return WERR_DS_DRA_REF_NOT_FOUND;
     118        }
     119
    94120        return WERR_OK;
     121}
     122
     123/*
     124  drsuapi_DsReplicaUpdateRefs - a non RPC version callable from getncchanges
     125*/
     126WERROR drsuapi_UpdateRefs(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx,
     127                          struct drsuapi_DsReplicaUpdateRefsRequest1 *req)
     128{
     129        WERROR werr;
     130        struct ldb_dn *dn;
     131        struct ldb_context *sam_ctx = b_state->sam_ctx_system?b_state->sam_ctx_system:b_state->sam_ctx;
     132
     133        DEBUG(4,("DsReplicaUpdateRefs for host '%s' with GUID %s options 0x%08x nc=%s\n",
     134                 req->dest_dsa_dns_name, GUID_string(mem_ctx, &req->dest_dsa_guid),
     135                 req->options,
     136                 drs_ObjectIdentifier_to_string(mem_ctx, req->naming_context)));
     137
     138        dn = ldb_dn_new(mem_ctx, sam_ctx, req->naming_context->dn);
     139        if (dn == NULL) {
     140                return WERR_DS_INVALID_DN_SYNTAX;
     141        }
     142
     143        if (ldb_transaction_start(sam_ctx) != LDB_SUCCESS) {
     144                DEBUG(0,(__location__ ": Failed to start transaction on samdb: %s\n",
     145                         ldb_errstring(sam_ctx)));
     146                return WERR_DS_DRA_INTERNAL_ERROR;             
     147        }
     148
     149        if (req->options & DRSUAPI_DRS_DEL_REF) {
     150                werr = uref_del_dest(sam_ctx, mem_ctx, dn, &req->dest_dsa_guid, req->options);
     151                if (!W_ERROR_IS_OK(werr)) {
     152                        DEBUG(0,("Failed to delete repsTo for %s: %s\n",
     153                                 GUID_string(mem_ctx, &req->dest_dsa_guid),
     154                                 win_errstr(werr)));
     155                        goto failed;
     156                }
     157        }
     158
     159        if (req->options & DRSUAPI_DRS_ADD_REF) {
     160                struct repsFromTo1 dest;
     161                struct repsFromTo1OtherInfo oi;
     162               
     163                ZERO_STRUCT(dest);
     164                ZERO_STRUCT(oi);
     165
     166                oi.dns_name = req->dest_dsa_dns_name;
     167                dest.other_info          = &oi;
     168                dest.source_dsa_obj_guid = req->dest_dsa_guid;
     169                dest.replica_flags       = req->options;
     170
     171                werr = uref_add_dest(sam_ctx, mem_ctx, dn, &dest, req->options);
     172                if (!W_ERROR_IS_OK(werr)) {
     173                        DEBUG(0,("Failed to add repsTo for %s: %s\n",
     174                                 GUID_string(mem_ctx, &dest.source_dsa_obj_guid),
     175                                 win_errstr(werr)));
     176                        goto failed;
     177                }
     178        }
     179
     180        if (ldb_transaction_commit(sam_ctx) != LDB_SUCCESS) {
     181                DEBUG(0,(__location__ ": Failed to commit transaction on samdb: %s\n",
     182                         ldb_errstring(sam_ctx)));
     183                return WERR_DS_DRA_INTERNAL_ERROR;             
     184        }
     185
     186        return WERR_OK;
     187
     188failed:
     189        ldb_transaction_cancel(sam_ctx);
     190        return werr;
    95191}
    96192
     
    101197                                          struct drsuapi_DsReplicaUpdateRefs *r)
    102198{
     199        struct dcesrv_handle *h;
     200        struct drsuapi_bind_state *b_state;
    103201        struct drsuapi_DsReplicaUpdateRefsRequest1 *req;
    104         struct ldb_context *sam_ctx;
    105         WERROR werr;
    106         struct ldb_dn *dn;
    107 
    108         werr = drs_security_level_check(dce_call, "DsReplicaUpdateRefs");
    109         if (!W_ERROR_IS_OK(werr)) {
    110                 return werr;
    111         }
     202        WERROR werr;
     203        int ret;
     204        enum security_user_level security_level;
     205
     206        DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
     207        b_state = h->data;
    112208
    113209        if (r->in.level != 1) {
     
    115211                return WERR_DS_DRA_INVALID_PARAMETER;
    116212        }
    117 
    118213        req = &r->in.req.req1;
    119         DEBUG(4,("DsReplicaUpdateRefs for host '%s' with GUID %s options 0x%08x nc=%s\n",
    120                  req->dest_dsa_dns_name, GUID_string(mem_ctx, &req->dest_dsa_guid),
    121                  req->options,
    122                  drs_ObjectIdentifier_to_string(mem_ctx, req->naming_context)));
    123 
    124         /* TODO: We need to authenticate this operation pretty carefully */
    125         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
    126                                 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
    127         if (!sam_ctx) {
    128                 return WERR_DS_DRA_INTERNAL_ERROR;             
    129         }
    130 
    131         dn = ldb_dn_new(mem_ctx, sam_ctx, req->naming_context->dn);
    132         if (dn == NULL) {
    133                 talloc_free(sam_ctx);           
    134                 return WERR_DS_INVALID_DN_SYNTAX;
    135         }
    136 
    137         if (ldb_transaction_start(sam_ctx) != LDB_SUCCESS) {
    138                 DEBUG(0,(__location__ ": Failed to start transaction on samdb\n"));
    139                 talloc_free(sam_ctx);
    140                 return WERR_DS_DRA_INTERNAL_ERROR;             
    141         }
    142 
    143         if (req->options & DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE) {
    144                 werr = uref_del_dest(sam_ctx, mem_ctx, dn, &req->dest_dsa_guid);
    145                 if (!W_ERROR_IS_OK(werr)) {
    146                         DEBUG(0,("Failed to delete repsTo for %s\n",
    147                                  GUID_string(dce_call, &req->dest_dsa_guid)));
    148                         goto failed;
    149                 }
    150         }
    151 
    152         if (req->options & DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE) {
    153                 struct repsFromTo1 dest;
    154                 struct repsFromTo1OtherInfo oi;
    155                
    156                 ZERO_STRUCT(dest);
    157                 ZERO_STRUCT(oi);
    158 
    159                 oi.dns_name = req->dest_dsa_dns_name;
    160                 dest.other_info          = &oi;
    161                 dest.source_dsa_obj_guid = req->dest_dsa_guid;
    162                 dest.replica_flags       = req->options;
    163 
    164                 werr = uref_add_dest(sam_ctx, mem_ctx, dn, &dest);
    165                 if (!W_ERROR_IS_OK(werr)) {
    166                         DEBUG(0,("Failed to delete repsTo for %s\n",
    167                                  GUID_string(dce_call, &dest.source_dsa_obj_guid)));
    168                         goto failed;
    169                 }
    170         }
    171 
    172         if (ldb_transaction_commit(sam_ctx) != LDB_SUCCESS) {
    173                 DEBUG(0,(__location__ ": Failed to commit transaction on samdb\n"));
    174                 return WERR_DS_DRA_INTERNAL_ERROR;             
    175         }
    176 
    177         talloc_free(sam_ctx);
    178         return WERR_OK;
    179 
    180 failed:
    181         ldb_transaction_cancel(sam_ctx);
    182         talloc_free(sam_ctx);
     214        werr = drs_security_access_check(b_state->sam_ctx,
     215                                         mem_ctx,
     216                                         dce_call->conn->auth_state.session_info->security_token,
     217                                         req->naming_context,
     218                                         GUID_DRS_MANAGE_TOPOLOGY);
     219
     220        if (!W_ERROR_IS_OK(werr)) {
     221                return werr;
     222        }
     223
     224        security_level = security_session_user_level(dce_call->conn->auth_state.session_info, NULL);
     225        if (security_level < SECURITY_ADMINISTRATOR) {
     226                /* check that they are using an DSA objectGUID that they own */
     227                ret = dsdb_validate_dsa_guid(b_state->sam_ctx,
     228                                             &req->dest_dsa_guid,
     229                                             &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX]);
     230                if (ret != LDB_SUCCESS) {
     231                        DEBUG(0,(__location__ ": Refusing DsReplicaUpdateRefs for sid %s with GUID %s\n",
     232                                 dom_sid_string(mem_ctx,
     233                                                &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX]),
     234                                 GUID_string(mem_ctx, &req->dest_dsa_guid)));
     235                        return WERR_DS_DRA_ACCESS_DENIED;
     236                }
     237        }
     238
     239        werr = drsuapi_UpdateRefs(b_state, mem_ctx, req);
     240
     241#if 0
     242        NDR_PRINT_FUNCTION_DEBUG(drsuapi_DsReplicaUpdateRefs, NDR_BOTH, r);
     243#endif
     244
    183245        return werr;
    184246}
  • trunk/server/source4/rpc_server/echo/rpc_echo.c

    r414 r745  
    4040        }
    4141
    42         r->out.out_data = talloc_memdup(mem_ctx, r->in.in_data, r->in.len);
     42        r->out.out_data = (uint8_t *)talloc_memdup(mem_ctx, r->in.in_data, r->in.len);
    4343        if (!r->out.out_data) {
    4444                return NT_STATUS_NO_MEMORY;
     
    5555static NTSTATUS dcesrv_echo_SourceData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_SourceData *r)
    5656{
    57         int i;
     57        unsigned int i;
    5858
    5959        r->out.data = talloc_array(mem_ctx, uint8_t, r->in.len);
  • trunk/server/source4/rpc_server/epmapper/rpc_epmapper.c

    r414 r745  
    6666                        description->object = iface->iface.syntax_id;
    6767
    68                         status = dcerpc_binding_build_tower(mem_ctx, description, &(*eps)[total].ep);
     68                        status = dcerpc_binding_build_tower(*eps, description, &(*eps)[total].ep);
    6969                        if (NT_STATUS_IS_ERR(status)) {
    7070                                DEBUG(1, ("Unable to build tower for %s\n", iface->iface.name));
     
    104104        } *eps;
    105105        uint32_t num_ents;
    106         int i;
     106        unsigned int i;
    107107
    108108        DCESRV_PULL_HANDLE_FAULT(h, r->in.entry_handle, HTYPE_LOOKUP);
     
    169169{
    170170        uint32_t count;
    171         int i;
     171        unsigned int i;
    172172        struct dcesrv_ep_iface *eps;
    173173        struct epm_floor *floors;
  • trunk/server/source4/rpc_server/handles.c

    r414 r745  
    2323#include "../lib/util/dlinklist.h"
    2424#include "rpc_server/dcerpc_server.h"
    25 #include "libcli/security/dom_sid.h"
     25#include "libcli/security/security.h"
    2626#include "auth/session.h"
    2727
     
    4545        struct dom_sid *sid;
    4646
    47         sid = context->conn->auth_state.session_info->security_token->user_sid;
     47        sid = &context->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
    4848
    4949        h = talloc(context->assoc_group, struct dcesrv_handle);
     
    8181        struct dom_sid *sid;
    8282
    83         sid = context->conn->auth_state.session_info->security_token->user_sid;
     83        sid = &context->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
    8484
    8585        if (policy_handle_empty(p)) {
  • trunk/server/source4/rpc_server/lsa/dcesrv_lsa.c

    r414 r745  
    2929#include "librpc/gen_ndr/ndr_lsa.h"
    3030#include "../lib/crypto/crypto.h"
     31#include "lib/util/tsort.h"
     32#include "dsdb/common/util.h"
     33#include "libcli/security/session.h"
     34#include "kdc/kdc-policy.h"
    3135
    3236/*
     
    8185
    8286        status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
    83         NT_STATUS_NOT_OK_RETURN(status);
     87        NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
    8488
    8589        domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
     
    180184
    181185                /* Ensure user is permitted to delete this... */
    182                 switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     186                switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    183187                {
    184188                case SECURITY_SYSTEM:
     
    186190                        break;
    187191                default:
    188                         /* Users and annonymous are not allowed delete things */
     192                        /* Users and anonymous are not allowed to delete things */
    189193                        return NT_STATUS_ACCESS_DENIED;
    190194                }
     
    192196                ret = ldb_delete(secret_state->sam_ldb,
    193197                                 secret_state->secret_dn);
    194                 talloc_free(h);
    195                 if (ret != 0) {
     198                if (ret != LDB_SUCCESS) {
    196199                        return NT_STATUS_INVALID_HANDLE;
    197200                }
     
    200203
    201204                return NT_STATUS_OK;
     205
    202206        } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
    203207                struct lsa_trusted_domain_state *trusted_domain_state =
    204208                        talloc_get_type(h->data, struct lsa_trusted_domain_state);
    205209                ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
    206                 if (ret != 0) {
     210                if (ret != LDB_SUCCESS) {
    207211                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
    208212                }
     
    210214                ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
    211215                                 trusted_domain_state->trusted_domain_dn);
    212                 if (ret != 0) {
     216                if (ret != LDB_SUCCESS) {
    213217                        ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
    214218                        return NT_STATUS_INVALID_HANDLE;
     
    218222                        ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
    219223                                         trusted_domain_state->trusted_domain_user_dn);
    220                         if (ret != 0) {
     224                        if (ret != LDB_SUCCESS) {
    221225                                ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
    222226                                return NT_STATUS_INVALID_HANDLE;
     
    225229
    226230                ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
    227                 if (ret != 0) {
     231                if (ret != LDB_SUCCESS) {
    228232                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
    229233                }
    230                 talloc_free(h);
     234
    231235                ZERO_STRUCTP(r->out.handle);
    232236
    233237                return NT_STATUS_OK;
     238
    234239        } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
    235240                struct lsa_RightSet *rights;
     
    272277
    273278                ZERO_STRUCTP(r->out.handle);
     279
     280                return NT_STATUS_OK;
    274281        }
    275282       
     
    286293        struct dcesrv_handle *h;
    287294        struct lsa_policy_state *state;
    288         int i;
     295        uint32_t i;
     296        enum sec_privilege priv;
    289297        const char *privname;
    290298
     
    294302
    295303        i = *r->in.resume_handle;
    296         if (i == 0) i = 1;
    297 
    298         while ((privname = sec_privilege_name(i)) &&
     304
     305        while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
    299306               r->out.privs->count < r->in.max_count) {
    300307                struct lsa_PrivEntry *e;
    301 
     308                privname = sec_privilege_name(priv);
    302309                r->out.privs->privs = talloc_realloc(r->out.privs,
    303310                                                       r->out.privs->privs,
     
    308315                }
    309316                e = &r->out.privs->privs[r->out.privs->count];
    310                 e->luid.low = i;
     317                e->luid.low = priv;
    311318                e->luid.high = 0;
    312319                e->name.string = privname;
     
    334341        DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
    335342
    336         sid = dce_call->conn->auth_state.session_info->security_token->user_sid;
     343        sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
    337344
    338345        if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
     
    386393        union dssetup_DsRoleInfo *info;
    387394
    388         info = talloc(mem_ctx, union dssetup_DsRoleInfo);
     395        info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
    389396        W_ERROR_HAVE_NO_MEMORY(info);
    390397
     
    407414                ZERO_STRUCT(domain_guid);
    408415
    409                 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
     416                switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
    410417                case ROLE_STANDALONE:
    411418                        role            = DS_ROLE_STANDALONE_SERVER;
     
    423430                }
    424431
    425                 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
     432                switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
    426433                case ROLE_STANDALONE:
    427                         domain          = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
     434                        domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
    428435                        W_ERROR_HAVE_NO_MEMORY(domain);
    429436                        break;
    430437                case ROLE_DOMAIN_MEMBER:
    431                         domain          = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
     438                        domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
    432439                        W_ERROR_HAVE_NO_MEMORY(domain);
    433440                        /* TODO: what is with dns_domain and forest and guid? */
     
    477484                return WERR_INVALID_PARAM;
    478485        }
    479 
    480         return WERR_INVALID_PARAM;
    481486}
    482487
     
    551556                return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
    552557
    553 
    554558        case LSA_POLICY_INFO_ROLE:
    555559                info->role.role = LSA_ROLE_PRIMARY;
     
    683687        struct dcesrv_handle *h;
    684688        struct lsa_policy_state *state;
    685         int ret, i;
     689        int ret;
    686690        struct ldb_message **res;
    687691        const char * const attrs[] = { "objectSid", NULL};
    688         uint32_t count;
     692        uint32_t count, i;
    689693
    690694        DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
     
    695699           one privilege set
    696700        */
    697         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs,
     701        ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
    698702                           "(&(objectSid=*)(privilege=*))");
    699703        if (ret < 0) {
    700                 return NT_STATUS_NO_SUCH_USER;
     704                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    701705        }
    702706
     
    734738}
    735739
     740/* This decrypts and returns Trusted Domain Auth Information Internal data */
     741static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
     742                                       TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
     743                                       struct trustDomainPasswords *auth_struct)
     744{
     745        DATA_BLOB session_key = data_blob(NULL, 0);
     746        enum ndr_err_code ndr_err;
     747        NTSTATUS nt_status;
     748
     749        nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
     750        if (!NT_STATUS_IS_OK(nt_status)) {
     751                return nt_status;
     752        }
     753
     754        arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
     755        ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
     756                                       auth_struct,
     757                                       (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
     758        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     759                return NT_STATUS_INVALID_PARAMETER;
     760        }
     761
     762        return NT_STATUS_OK;
     763}
     764
     765static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
     766                                         TALLOC_CTX *mem_ctx,
     767                                         struct trustAuthInOutBlob *iopw,
     768                                         DATA_BLOB *trustauth_blob)
     769{
     770        enum ndr_err_code ndr_err;
     771
     772        ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
     773                                       iopw,
     774                                       (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
     775        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     776                return NT_STATUS_INVALID_PARAMETER;
     777        }
     778
     779        return NT_STATUS_OK;
     780}
     781
     782static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
     783                               struct ldb_context *sam_ldb,
     784                               struct ldb_dn *base_dn,
     785                               const char *netbios_name,
     786                               struct trustAuthInOutBlob *in,
     787                               struct ldb_dn **user_dn)
     788{
     789        struct ldb_message *msg;
     790        struct ldb_dn *dn;
     791        uint32_t i;
     792        int ret;
     793
     794        dn = ldb_dn_copy(mem_ctx, base_dn);
     795        if (!dn) {
     796                return NT_STATUS_NO_MEMORY;
     797        }
     798        if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
     799                return NT_STATUS_NO_MEMORY;
     800        }
     801
     802        msg = ldb_msg_new(mem_ctx);
     803        if (!msg) {
     804                return NT_STATUS_NO_MEMORY;
     805        }
     806        msg->dn = dn;
     807
     808        ret = ldb_msg_add_string(msg, "objectClass", "user");
     809        if (ret != LDB_SUCCESS) {
     810                return NT_STATUS_NO_MEMORY;
     811        }
     812
     813        ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
     814        if (ret != LDB_SUCCESS) {
     815                return NT_STATUS_NO_MEMORY;
     816        }
     817
     818        ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
     819                                 UF_INTERDOMAIN_TRUST_ACCOUNT);
     820        if (ret != LDB_SUCCESS) {
     821                return NT_STATUS_NO_MEMORY;
     822        }
     823
     824        for (i = 0; i < in->count; i++) {
     825                const char *attribute;
     826                struct ldb_val v;
     827                switch (in->current.array[i].AuthType) {
     828                case TRUST_AUTH_TYPE_NT4OWF:
     829                        attribute = "unicodePwd";
     830                        v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
     831                        v.length = 16;
     832                        break;
     833                case TRUST_AUTH_TYPE_CLEAR:
     834                        attribute = "clearTextPassword";
     835                        v.data = in->current.array[i].AuthInfo.clear.password;
     836                        v.length = in->current.array[i].AuthInfo.clear.size;
     837                        break;
     838                default:
     839                        continue;
     840                }
     841
     842                ret = ldb_msg_add_value(msg, attribute, &v, NULL);
     843                if (ret != LDB_SUCCESS) {
     844                        return NT_STATUS_NO_MEMORY;
     845                }
     846        }
     847
     848        /* create the trusted_domain user account */
     849        ret = ldb_add(sam_ldb, msg);
     850        if (ret != LDB_SUCCESS) {
     851                DEBUG(0,("Failed to create user record %s: %s\n",
     852                         ldb_dn_get_linearized(msg->dn),
     853                         ldb_errstring(sam_ldb)));
     854
     855                switch (ret) {
     856                case LDB_ERR_ENTRY_ALREADY_EXISTS:
     857                        return NT_STATUS_DOMAIN_EXISTS;
     858                case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
     859                        return NT_STATUS_ACCESS_DENIED;
     860                default:
     861                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     862                }
     863        }
     864
     865        if (user_dn) {
     866                *user_dn = dn;
     867        }
     868        return NT_STATUS_OK;
     869}
    736870
    737871/*
     
    747881        struct lsa_trusted_domain_state *trusted_domain_state;
    748882        struct dcesrv_handle *handle;
    749         struct ldb_message **msgs, *msg, *msg_user;
     883        struct ldb_message **msgs, *msg;
    750884        const char *attrs[] = {
    751885                NULL
     
    754888        const char *dns_name;
    755889        const char *name;
    756         DATA_BLOB session_key = data_blob(NULL, 0);
    757890        DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
    758891        struct trustDomainPasswords auth_struct;
    759892        int ret;
    760893        NTSTATUS nt_status;
    761         enum ndr_err_code ndr_err;
    762        
     894        struct ldb_context *sam_ldb;
     895
    763896        DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
    764897        ZERO_STRUCTP(r->out.trustdom_handle);
    765        
     898
    766899        policy_state = policy_handle->data;
    767 
    768         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
    769         if (!NT_STATUS_IS_OK(nt_status)) {
    770                 return nt_status;
    771         }
     900        sam_ldb = policy_state->sam_ldb;
    772901
    773902        netbios_name = r->in.info->netbios_name.string;
     
    775904                return NT_STATUS_INVALID_PARAMETER;
    776905        }
    777        
     906
    778907        dns_name = r->in.info->domain_name.string;
    779        
     908
    780909        trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
    781910        if (!trusted_domain_state) {
     
    785914
    786915        if (strcasecmp(netbios_name, "BUILTIN") == 0
    787             || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0) 
     916            || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
    788917            || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
    789                 return NT_STATUS_INVALID_PARAMETER;;
     918                return NT_STATUS_INVALID_PARAMETER;
    790919        }
    791920
    792921        if (strcasecmp(netbios_name, policy_state->domain_name) == 0
    793922            || strcasecmp(netbios_name, policy_state->domain_dns) == 0
    794             || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0) 
     923            || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
    795924            || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
    796925            || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
     
    804933                auth_struct.incoming.count = 0;
    805934        } else {
    806                 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data, r->in.auth_info->auth_blob.size);
    807                 arcfour_crypt_blob(auth_blob.data, auth_blob.length, &session_key);
    808                 ndr_err = ndr_pull_struct_blob(&auth_blob, mem_ctx,
    809                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
    810                                                &auth_struct,
    811                                                (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
    812                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    813                         return NT_STATUS_INVALID_PARAMETER;
    814                 }                               
     935                auth_blob = data_blob_const(r->in.auth_info->auth_blob.data,
     936                                            r->in.auth_info->auth_blob.size);
     937                nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
     938                                                   &auth_blob, &auth_struct);
     939                if (!NT_STATUS_IS_OK(nt_status)) {
     940                        return nt_status;
     941                }
    815942
    816943                if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
     
    822949
    823950        if (auth_struct.incoming.count) {
    824                 int i;
    825                 struct trustAuthInOutBlob incoming;
    826                
    827                 incoming.count = auth_struct.incoming.count;
    828                 incoming.current = talloc(mem_ctx, struct AuthenticationInformationArray);
    829                 if (!incoming.current) {
    830                         return NT_STATUS_NO_MEMORY;
    831                 }
    832                
    833                 incoming.current->array = *auth_struct.incoming.current;
    834                 if (!incoming.current->array) {
    835                         return NT_STATUS_NO_MEMORY;
    836                 }
    837 
    838                 incoming.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
    839                 if (!incoming.previous) {
    840                         return NT_STATUS_NO_MEMORY;
    841                 }
    842                 incoming.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, incoming.count);
    843                 if (!incoming.previous->array) {
    844                         return NT_STATUS_NO_MEMORY;
    845                 }
    846 
    847                 for (i = 0; i < incoming.count; i++) {
    848                         incoming.previous->array[i].LastUpdateTime = 0;
    849                         incoming.previous->array[i].AuthType = 0;
    850                 }
    851                 ndr_err = ndr_push_struct_blob(&trustAuthIncoming, mem_ctx,
    852                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
    853                                                &incoming,
    854                                                (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
    855                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    856                         return NT_STATUS_INVALID_PARAMETER;
     951                nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
     952                                                     &auth_struct.incoming,
     953                                                     &trustAuthIncoming);
     954                if (!NT_STATUS_IS_OK(nt_status)) {
     955                        return nt_status;
    857956                }
    858957        } else {
    859958                trustAuthIncoming = data_blob(NULL, 0);
    860959        }
    861        
     960
    862961        if (auth_struct.outgoing.count) {
    863                 int i;
    864                 struct trustAuthInOutBlob outgoing;
    865                
    866                 outgoing.count = auth_struct.outgoing.count;
    867                 outgoing.current = talloc(mem_ctx, struct AuthenticationInformationArray);
    868                 if (!outgoing.current) {
    869                         return NT_STATUS_NO_MEMORY;
    870                 }
    871                
    872                 outgoing.current->array = *auth_struct.outgoing.current;
    873                 if (!outgoing.current->array) {
    874                         return NT_STATUS_NO_MEMORY;
    875                 }
    876 
    877                 outgoing.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
    878                 if (!outgoing.previous) {
    879                         return NT_STATUS_NO_MEMORY;
    880                 }
    881                 outgoing.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, outgoing.count);
    882                 if (!outgoing.previous->array) {
    883                         return NT_STATUS_NO_MEMORY;
    884                 }
    885 
    886                 for (i = 0; i < outgoing.count; i++) {
    887                         outgoing.previous->array[i].LastUpdateTime = 0;
    888                         outgoing.previous->array[i].AuthType = 0;
    889                 }
    890                 ndr_err = ndr_push_struct_blob(&trustAuthOutgoing, mem_ctx,
    891                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
    892                                                &outgoing,
    893                                                (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
    894                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    895                         return NT_STATUS_INVALID_PARAMETER;
     962                nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
     963                                                     &auth_struct.outgoing,
     964                                                     &trustAuthOutgoing);
     965                if (!NT_STATUS_IS_OK(nt_status)) {
     966                        return nt_status;
    896967                }
    897968        } else {
     
    899970        }
    900971
    901         ret = ldb_transaction_start(policy_state->sam_ldb);
     972        ret = ldb_transaction_start(sam_ldb);
    902973        if (ret != LDB_SUCCESS) {
    903974                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     
    908979                char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
    909980                /* search for the trusted_domain record */
    910                 ret = gendb_search(policy_state->sam_ldb,
     981                ret = gendb_search(sam_ldb,
    911982                                   mem_ctx, policy_state->system_dn, &msgs, attrs,
    912                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))", 
     983                                   "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
    913984                                   dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
    914985                if (ret > 0) {
    915                         ldb_transaction_cancel(policy_state->sam_ldb);
     986                        ldb_transaction_cancel(sam_ldb);
    916987                        return NT_STATUS_OBJECT_NAME_COLLISION;
    917988                }
     
    919990                char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
    920991                /* search for the trusted_domain record */
    921                 ret = gendb_search(policy_state->sam_ldb,
     992                ret = gendb_search(sam_ldb,
    922993                                   mem_ctx, policy_state->system_dn, &msgs, attrs,
    923                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))", 
     994                                   "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
    924995                                   netbios_encoded, netbios_encoded, netbios_encoded);
    925996                if (ret > 0) {
    926                         ldb_transaction_cancel(policy_state->sam_ldb);
     997                        ldb_transaction_cancel(sam_ldb);
    927998                        return NT_STATUS_OBJECT_NAME_COLLISION;
    928999                }
    9291000        }
    930        
     1001
    9311002        if (ret < 0 ) {
    932                 ldb_transaction_cancel(policy_state->sam_ldb);
     1003                ldb_transaction_cancel(sam_ldb);
    9331004                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    9341005        }
    935        
     1006
    9361007        name = dns_name ? dns_name : netbios_name;
    9371008
     
    9431014        msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
    9441015        if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
    945                         ldb_transaction_cancel(policy_state->sam_ldb);
    946                 return NT_STATUS_NO_MEMORY;
    947         }
    948        
    949         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", netbios_name);
     1016                        ldb_transaction_cancel(sam_ldb);
     1017                return NT_STATUS_NO_MEMORY;
     1018        }
     1019
     1020        ldb_msg_add_string(msg, "flatname", netbios_name);
    9501021
    9511022        if (r->in.info->sid) {
    952                 const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid);
    953                 if (!sid_string) {
    954                         ldb_transaction_cancel(policy_state->sam_ldb);
    955                         return NT_STATUS_NO_MEMORY;
    956                 }
    957                        
    958                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "securityIdentifier", sid_string);
    959         }
    960 
    961         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
    962 
    963         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
    964 
    965         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
    966 
    967         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
    968        
     1023                ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
     1024                if (ret != LDB_SUCCESS) {
     1025                        ldb_transaction_cancel(sam_ldb);
     1026                        return NT_STATUS_INVALID_PARAMETER;
     1027                }
     1028        }
     1029
     1030        ldb_msg_add_string(msg, "objectClass", "trustedDomain");
     1031
     1032        samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
     1033
     1034        samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
     1035
     1036        samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
     1037
    9691038        if (dns_name) {
    970                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
     1039                ldb_msg_add_string(msg, "trustPartner", dns_name);
    9711040        }
    9721041
     
    9741043                ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
    9751044                if (ret != LDB_SUCCESS) {
    976                         ldb_transaction_cancel(policy_state->sam_ldb);
     1045                        ldb_transaction_cancel(sam_ldb);
    9771046                        return NT_STATUS_NO_MEMORY;
    9781047                }
     
    9811050                ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
    9821051                if (ret != LDB_SUCCESS) {
    983                         ldb_transaction_cancel(policy_state->sam_ldb);
     1052                        ldb_transaction_cancel(sam_ldb);
    9841053                        return NT_STATUS_NO_MEMORY;
    9851054                }
     
    9891058
    9901059        /* create the trusted_domain */
    991         ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg);
     1060        ret = ldb_add(sam_ldb, msg);
    9921061        switch (ret) {
    9931062        case  LDB_SUCCESS:
    9941063                break;
    9951064        case  LDB_ERR_ENTRY_ALREADY_EXISTS:
    996                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
     1065                ldb_transaction_cancel(sam_ldb);
    9971066                DEBUG(0,("Failed to create trusted domain record %s: %s\n",
    9981067                         ldb_dn_get_linearized(msg->dn),
    999                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
     1068                         ldb_errstring(sam_ldb)));
    10001069                return NT_STATUS_DOMAIN_EXISTS;
    10011070        case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
    1002                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
     1071                ldb_transaction_cancel(sam_ldb);
    10031072                DEBUG(0,("Failed to create trusted domain record %s: %s\n",
    10041073                         ldb_dn_get_linearized(msg->dn),
    1005                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
     1074                         ldb_errstring(sam_ldb)));
    10061075                return NT_STATUS_ACCESS_DENIED;
    10071076        default:
    1008                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
     1077                ldb_transaction_cancel(sam_ldb);
    10091078                DEBUG(0,("Failed to create user record %s: %s\n",
    10101079                         ldb_dn_get_linearized(msg->dn),
    1011                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
     1080                         ldb_errstring(sam_ldb)));
    10121081                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    10131082        }
    10141083
    10151084        if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
    1016                 msg_user = ldb_msg_new(mem_ctx);
    1017                 if (msg_user == NULL) {
    1018                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
    1019                         return NT_STATUS_NO_MEMORY;
    1020                 }
    1021 
     1085                struct ldb_dn *user_dn;
    10221086                /* Inbound trusts must also create a cn=users object to match */
    1023 
    1024                 trusted_domain_state->trusted_domain_user_dn = msg_user->dn
    1025                         = ldb_dn_copy(trusted_domain_state, policy_state->domain_dn);
    1026                 if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=users")) {
    1027                         ldb_transaction_cancel(policy_state->sam_ldb);
    1028                         return NT_STATUS_NO_MEMORY;
    1029                 }
    1030        
    1031                 if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=%s", netbios_name)) {
    1032                         ldb_transaction_cancel(policy_state->sam_ldb);
    1033                         return NT_STATUS_NO_MEMORY;
    1034                 }
    1035 
    1036                 ldb_msg_add_string(msg_user, "objectClass", "user");
    1037 
    1038                 ldb_msg_add_steal_string(msg_user, "samAccountName",
    1039                                          talloc_asprintf(mem_ctx, "%s$", netbios_name));
    1040 
    1041                 if (samdb_msg_add_uint(trusted_domain_state->policy->sam_ldb, mem_ctx, msg_user,
    1042                                        "userAccountControl",
    1043                                        UF_INTERDOMAIN_TRUST_ACCOUNT) != 0) {
    1044                         ldb_transaction_cancel(policy_state->sam_ldb);
    1045                         return NT_STATUS_NO_MEMORY;
    1046                 }
    1047 
    1048                 if (auth_struct.incoming.count) {
    1049                         int i;
    1050                         for (i=0; i < auth_struct.incoming.count; i++ ) {
    1051                                 if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_NT4OWF) {
    1052                                         samdb_msg_add_hash(trusted_domain_state->policy->sam_ldb,
    1053                                                            mem_ctx, msg_user, "unicodePwd",
    1054                                                            &auth_struct.incoming.current[i]->AuthInfo.nt4owf.password);
    1055                                 } else if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_CLEAR) {
    1056                                         DATA_BLOB new_password = data_blob_const(auth_struct.incoming.current[i]->AuthInfo.clear.password,
    1057                                                                                  auth_struct.incoming.current[i]->AuthInfo.clear.size);
    1058                                         ret = ldb_msg_add_value(msg_user, "clearTextPassword", &new_password, NULL);
    1059                                         if (ret != LDB_SUCCESS) {
    1060                                                 ldb_transaction_cancel(policy_state->sam_ldb);
    1061                                                 return NT_STATUS_NO_MEMORY;
    1062                                         }
    1063                                 }
    1064                         }
    1065                 }
    1066 
    1067                 /* create the cn=users trusted_domain account */
    1068                 ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg_user);
    1069                 switch (ret) {
    1070                 case  LDB_SUCCESS:
    1071                         break;
    1072                 case  LDB_ERR_ENTRY_ALREADY_EXISTS:
    1073                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
    1074                         DEBUG(0,("Failed to create trusted domain record %s: %s\n",
    1075                                  ldb_dn_get_linearized(msg_user->dn),
    1076                                  ldb_errstring(trusted_domain_state->policy->sam_ldb)));
    1077                         return NT_STATUS_DOMAIN_EXISTS;
    1078                 case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
    1079                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
    1080                         DEBUG(0,("Failed to create trusted domain record %s: %s\n",
    1081                                  ldb_dn_get_linearized(msg_user->dn),
    1082                                  ldb_errstring(trusted_domain_state->policy->sam_ldb)));
    1083                         return NT_STATUS_ACCESS_DENIED;
    1084                 default:
    1085                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
    1086                         DEBUG(0,("Failed to create user record %s: %s\n",
    1087                                  ldb_dn_get_linearized(msg_user->dn),
    1088                                  ldb_errstring(trusted_domain_state->policy->sam_ldb)));
    1089                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1090                 }
    1091         }
    1092 
    1093         ret = ldb_transaction_commit(policy_state->sam_ldb);
     1087                nt_status = add_trust_user(mem_ctx, sam_ldb,
     1088                                           policy_state->domain_dn,
     1089                                           netbios_name,
     1090                                           &auth_struct.incoming,
     1091                                           &user_dn);
     1092                if (!NT_STATUS_IS_OK(nt_status)) {
     1093                        ldb_transaction_cancel(sam_ldb);
     1094                        return nt_status;
     1095                }
     1096
     1097                /* save the trust user dn */
     1098                trusted_domain_state->trusted_domain_user_dn
     1099                        = talloc_steal(trusted_domain_state, user_dn);
     1100        }
     1101
     1102        ret = ldb_transaction_commit(sam_ldb);
    10941103        if (ret != LDB_SUCCESS) {
    10951104                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     
    11001109                return NT_STATUS_NO_MEMORY;
    11011110        }
    1102        
     1111
    11031112        handle->data = talloc_steal(handle, trusted_domain_state);
    1104        
     1113
    11051114        trusted_domain_state->access_mask = r->in.access_mask;
    11061115        trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
    1107        
     1116
    11081117        *r->out.trustdom_handle = handle->wire_handle;
    1109        
     1118
    11101119        return NT_STATUS_OK;
    11111120}
     
    12241233                ret = gendb_search(trusted_domain_state->policy->sam_ldb,
    12251234                                   mem_ctx, policy_state->domain_dn, &msgs, attrs,
    1226                                    "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%d))",
     1235                                   "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%u))",
    12271236                                   flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
    12281237                if (ret == 1) {
     
    12541263{
    12551264        struct dcesrv_handle *policy_handle;
    1256        
     1265
    12571266        struct lsa_policy_state *policy_state;
    12581267        struct lsa_trusted_domain_state *trusted_domain_state;
     
    12621271                NULL
    12631272        };
    1264 
     1273        char *td_name;
    12651274        int ret;
    12661275
     
    12721281                return NT_STATUS_INVALID_PARAMETER;
    12731282        }
    1274        
     1283
    12751284        trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
    12761285        if (!trusted_domain_state) {
     
    12801289
    12811290        /* search for the trusted_domain record */
     1291        td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
    12821292        ret = gendb_search(trusted_domain_state->policy->sam_ldb,
    12831293                           mem_ctx, policy_state->system_dn, &msgs, attrs,
    1284                            "(&(flatname=%s)(objectclass=trustedDomain))",
    1285                            ldb_binary_encode_string(mem_ctx, r->in.name.string));
     1294                           "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
     1295                             "(objectclass=trustedDomain))",
     1296                           td_name, td_name, td_name);
    12861297        if (ret == 0) {
    12871298                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    12881299        }
    1289        
     1300
    12901301        if (ret != 1) {
    12911302                DEBUG(0,("Found %d records matching DN %s\n", ret,
     
    12941305        }
    12951306
     1307        /* TODO: perform access checks */
     1308
    12961309        trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
    1297        
     1310
    12981311        handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
    12991312        if (!handle) {
    13001313                return NT_STATUS_NO_MEMORY;
    13011314        }
    1302        
     1315
    13031316        handle->data = talloc_steal(handle, trusted_domain_state);
    1304        
     1317
    13051318        trusted_domain_state->access_mask = r->in.access_mask;
    13061319        trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
    1307        
     1320
    13081321        *r->out.trustdom_handle = handle->wire_handle;
    1309        
     1322
    13101323        return NT_STATUS_OK;
    13111324}
     
    13241337
    13251338
    1326 /*
     1339/* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
     1340 * otherwise at least one must be provided */
     1341static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
     1342                        struct ldb_dn *basedn, const char *dns_domain,
     1343                        const char *netbios, struct dom_sid2 *sid,
     1344                        struct ldb_message ***msgs)
     1345{
     1346        const char *attrs[] = { "flatname", "trustPartner",
     1347                                "securityIdentifier", "trustDirection",
     1348                                "trustType", "trustAttributes",
     1349                                "trustPosixOffset",
     1350                                "msDs-supportedEncryptionTypes", NULL };
     1351        char *dns = NULL;
     1352        char *nbn = NULL;
     1353        char *sidstr = NULL;
     1354        char *filter;
     1355        int ret;
     1356
     1357
     1358        if (dns_domain || netbios || sid) {
     1359                filter = talloc_strdup(mem_ctx,
     1360                                   "(&(objectclass=trustedDomain)(|");
     1361        } else {
     1362                filter = talloc_strdup(mem_ctx,
     1363                                       "(objectclass=trustedDomain)");
     1364        }
     1365        if (!filter) {
     1366                return NT_STATUS_NO_MEMORY;
     1367        }
     1368
     1369        if (dns_domain) {
     1370                dns = ldb_binary_encode_string(mem_ctx, dns_domain);
     1371                if (!dns) {
     1372                        return NT_STATUS_NO_MEMORY;
     1373                }
     1374                filter = talloc_asprintf_append(filter,
     1375                                                "(trustPartner=%s)", dns);
     1376                if (!filter) {
     1377                        return NT_STATUS_NO_MEMORY;
     1378                }
     1379        }
     1380        if (netbios) {
     1381                nbn = ldb_binary_encode_string(mem_ctx, netbios);
     1382                if (!nbn) {
     1383                        return NT_STATUS_NO_MEMORY;
     1384                }
     1385                filter = talloc_asprintf_append(filter,
     1386                                                "(flatname=%s)", nbn);
     1387                if (!filter) {
     1388                        return NT_STATUS_NO_MEMORY;
     1389                }
     1390        }
     1391        if (sid) {
     1392                sidstr = dom_sid_string(mem_ctx, sid);
     1393                if (!sidstr) {
     1394                        return NT_STATUS_INVALID_PARAMETER;
     1395                }
     1396                filter = talloc_asprintf_append(filter,
     1397                                                "(securityIdentifier=%s)",
     1398                                                sidstr);
     1399                if (!filter) {
     1400                        return NT_STATUS_NO_MEMORY;
     1401                }
     1402        }
     1403        if (dns_domain || netbios || sid) {
     1404                filter = talloc_asprintf_append(filter, "))");
     1405                if (!filter) {
     1406                        return NT_STATUS_NO_MEMORY;
     1407                }
     1408        }
     1409
     1410        ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
     1411        if (ret == 0) {
     1412                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     1413        }
     1414
     1415        if (ret != 1) {
     1416                return NT_STATUS_OBJECT_NAME_COLLISION;
     1417        }
     1418
     1419        return NT_STATUS_OK;
     1420}
     1421
     1422static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
     1423                                      struct ldb_context *sam_ldb,
     1424                                      struct ldb_message *orig,
     1425                                      struct ldb_message *dest,
     1426                                      const char *attribute,
     1427                                      uint32_t value,
     1428                                      uint32_t *orig_value)
     1429{
     1430        const struct ldb_val *orig_val;
     1431        uint32_t orig_uint = 0;
     1432        int flags = 0;
     1433        int ret;
     1434
     1435        orig_val = ldb_msg_find_ldb_val(orig, attribute);
     1436        if (!orig_val || !orig_val->data) {
     1437                /* add new attribute */
     1438                flags = LDB_FLAG_MOD_ADD;
     1439
     1440        } else {
     1441                errno = 0;
     1442                orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
     1443                if (errno != 0 || orig_uint != value) {
     1444                        /* replace also if can't get value */
     1445                        flags = LDB_FLAG_MOD_REPLACE;
     1446                }
     1447        }
     1448
     1449        if (flags == 0) {
     1450                /* stored value is identical, nothing to change */
     1451                goto done;
     1452        }
     1453
     1454        ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
     1455        if (ret != LDB_SUCCESS) {
     1456                return NT_STATUS_NO_MEMORY;
     1457        }
     1458
     1459        ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
     1460        if (ret != LDB_SUCCESS) {
     1461                return NT_STATUS_NO_MEMORY;
     1462        }
     1463
     1464done:
     1465        if (orig_value) {
     1466                *orig_value = orig_uint;
     1467        }
     1468        return NT_STATUS_OK;
     1469}
     1470
     1471static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
     1472                                  struct ldb_context *sam_ldb,
     1473                                  struct ldb_dn *base_dn,
     1474                                  bool delete_user,
     1475                                  const char *netbios_name,
     1476                                  struct trustAuthInOutBlob *in)
     1477{
     1478        const char *attrs[] = { "userAccountControl", NULL };
     1479        struct ldb_message **msgs;
     1480        struct ldb_message *msg;
     1481        uint32_t uac;
     1482        uint32_t i;
     1483        int ret;
     1484
     1485        ret = gendb_search(sam_ldb, mem_ctx,
     1486                           base_dn, &msgs, attrs,
     1487                           "samAccountName=%s$", netbios_name);
     1488        if (ret > 1) {
     1489                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1490        }
     1491
     1492        if (ret == 0) {
     1493                if (delete_user) {
     1494                        return NT_STATUS_OK;
     1495                }
     1496
     1497                /* ok no existing user, add it from scratch */
     1498                return add_trust_user(mem_ctx, sam_ldb, base_dn,
     1499                                      netbios_name, in, NULL);
     1500        }
     1501
     1502        /* check user is what we are looking for */
     1503        uac = ldb_msg_find_attr_as_uint(msgs[0],
     1504                                        "userAccountControl", 0);
     1505        if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
     1506                return NT_STATUS_OBJECT_NAME_COLLISION;
     1507        }
     1508
     1509        if (delete_user) {
     1510                ret = ldb_delete(sam_ldb, msgs[0]->dn);
     1511                switch (ret) {
     1512                case LDB_SUCCESS:
     1513                        return NT_STATUS_OK;
     1514                case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
     1515                        return NT_STATUS_ACCESS_DENIED;
     1516                default:
     1517                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1518                }
     1519        }
     1520
     1521        /* entry exists, just modify secret if any */
     1522        if (in->count == 0) {
     1523                return NT_STATUS_OK;
     1524        }
     1525
     1526        msg = ldb_msg_new(mem_ctx);
     1527        if (!msg) {
     1528                return NT_STATUS_NO_MEMORY;
     1529        }
     1530        msg->dn = msgs[0]->dn;
     1531
     1532        for (i = 0; i < in->count; i++) {
     1533                const char *attribute;
     1534                struct ldb_val v;
     1535                switch (in->current.array[i].AuthType) {
     1536                case TRUST_AUTH_TYPE_NT4OWF:
     1537                        attribute = "unicodePwd";
     1538                        v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
     1539                        v.length = 16;
     1540                        break;
     1541                case TRUST_AUTH_TYPE_CLEAR:
     1542                        attribute = "clearTextPassword";
     1543                        v.data = in->current.array[i].AuthInfo.clear.password;
     1544                        v.length = in->current.array[i].AuthInfo.clear.size;
     1545                        break;
     1546                default:
     1547                        continue;
     1548                }
     1549
     1550                ret = ldb_msg_add_empty(msg, attribute,
     1551                                        LDB_FLAG_MOD_REPLACE, NULL);
     1552                if (ret != LDB_SUCCESS) {
     1553                        return NT_STATUS_NO_MEMORY;
     1554                }
     1555
     1556                ret = ldb_msg_add_value(msg, attribute, &v, NULL);
     1557                if (ret != LDB_SUCCESS) {
     1558                        return NT_STATUS_NO_MEMORY;
     1559                }
     1560        }
     1561
     1562        /* create the trusted_domain user account */
     1563        ret = ldb_modify(sam_ldb, msg);
     1564        if (ret != LDB_SUCCESS) {
     1565                DEBUG(0,("Failed to create user record %s: %s\n",
     1566                         ldb_dn_get_linearized(msg->dn),
     1567                         ldb_errstring(sam_ldb)));
     1568
     1569                switch (ret) {
     1570                case LDB_ERR_ENTRY_ALREADY_EXISTS:
     1571                        return NT_STATUS_DOMAIN_EXISTS;
     1572                case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
     1573                        return NT_STATUS_ACCESS_DENIED;
     1574                default:
     1575                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1576                }
     1577        }
     1578
     1579        return NT_STATUS_OK;
     1580}
     1581
     1582
     1583static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
     1584                                          struct dcesrv_handle *p_handle,
     1585                                          TALLOC_CTX *mem_ctx,
     1586                                          struct ldb_message *dom_msg,
     1587                                          enum lsa_TrustDomInfoEnum level,
     1588                                          union lsa_TrustedDomainInfo *info)
     1589{
     1590        struct lsa_policy_state *p_state = p_handle->data;
     1591        uint32_t *posix_offset = NULL;
     1592        struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
     1593        struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
     1594        struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
     1595        uint32_t *enc_types = NULL;
     1596        DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
     1597        struct trustDomainPasswords auth_struct;
     1598        NTSTATUS nt_status;
     1599        struct ldb_message **msgs;
     1600        struct ldb_message *msg;
     1601        bool add_outgoing = false;
     1602        bool add_incoming = false;
     1603        bool del_outgoing = false;
     1604        bool del_incoming = false;
     1605        bool in_transaction = false;
     1606        int ret;
     1607        bool am_rodc;
     1608
     1609        switch (level) {
     1610        case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
     1611                posix_offset = &info->posix_offset.posix_offset;
     1612                break;
     1613        case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
     1614                info_ex = &info->info_ex;
     1615                break;
     1616        case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
     1617                auth_info = &info->auth_info;
     1618                break;
     1619        case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
     1620                posix_offset = &info->full_info.posix_offset.posix_offset;
     1621                info_ex = &info->full_info.info_ex;
     1622                auth_info = &info->full_info.auth_info;
     1623                break;
     1624        case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
     1625                auth_info_int = &info->auth_info_internal;
     1626                break;
     1627        case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
     1628                posix_offset = &info->full_info_internal.posix_offset.posix_offset;
     1629                info_ex = &info->full_info_internal.info_ex;
     1630                auth_info_int = &info->full_info_internal.auth_info;
     1631                break;
     1632        case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
     1633                enc_types = &info->enc_types.enc_types;
     1634                break;
     1635        default:
     1636                return NT_STATUS_INVALID_PARAMETER;
     1637        }
     1638
     1639        if (auth_info) {
     1640                /* FIXME: not handled yet */
     1641                return NT_STATUS_INVALID_PARAMETER;
     1642        }
     1643
     1644        /* decode auth_info_int if set */
     1645        if (auth_info_int) {
     1646
     1647                /* now decrypt blob */
     1648                auth_blob = data_blob_const(auth_info_int->auth_blob.data,
     1649                                            auth_info_int->auth_blob.size);
     1650
     1651                nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
     1652                                                   &auth_blob, &auth_struct);
     1653                if (!NT_STATUS_IS_OK(nt_status)) {
     1654                        return nt_status;
     1655                }
     1656        }
     1657
     1658        if (info_ex) {
     1659                /* verify data matches */
     1660                if (info_ex->trust_attributes &
     1661                    LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
     1662                        /* TODO: check what behavior level we have */
     1663                       if (strcasecmp_m(p_state->domain_dns,
     1664                                        p_state->forest_dns) != 0) {
     1665                                return NT_STATUS_INVALID_DOMAIN_STATE;
     1666                        }
     1667                }
     1668
     1669                ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
     1670                if (ret == LDB_SUCCESS && am_rodc) {
     1671                        return NT_STATUS_NO_SUCH_DOMAIN;
     1672                }
     1673
     1674                /* verify only one object matches the dns/netbios/sid
     1675                 * triplet and that this is the one we already have */
     1676                nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
     1677                                    p_state->system_dn,
     1678                                    info_ex->domain_name.string,
     1679                                    info_ex->netbios_name.string,
     1680                                    info_ex->sid, &msgs);
     1681                if (!NT_STATUS_IS_OK(nt_status)) {
     1682                        return nt_status;
     1683                }
     1684                if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
     1685                        return NT_STATUS_OBJECT_NAME_COLLISION;
     1686                }
     1687                talloc_free(msgs);
     1688        }
     1689
     1690        /* TODO: should we fetch previous values from the existing entry
     1691         * and append them ? */
     1692        if (auth_struct.incoming.count) {
     1693                nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
     1694                                                     &auth_struct.incoming,
     1695                                                     &trustAuthIncoming);
     1696                if (!NT_STATUS_IS_OK(nt_status)) {
     1697                        return nt_status;
     1698                }
     1699        } else {
     1700                trustAuthIncoming = data_blob(NULL, 0);
     1701        }
     1702
     1703        if (auth_struct.outgoing.count) {
     1704                nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
     1705                                                     &auth_struct.outgoing,
     1706                                                     &trustAuthOutgoing);
     1707                if (!NT_STATUS_IS_OK(nt_status)) {
     1708                        return nt_status;
     1709                }
     1710        } else {
     1711                trustAuthOutgoing = data_blob(NULL, 0);
     1712        }
     1713
     1714        msg = ldb_msg_new(mem_ctx);
     1715        if (msg == NULL) {
     1716                return NT_STATUS_NO_MEMORY;
     1717        }
     1718        msg->dn = dom_msg->dn;
     1719
     1720        if (posix_offset) {
     1721                nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
     1722                                                  dom_msg, msg,
     1723                                                  "trustPosixOffset",
     1724                                                  *posix_offset, NULL);
     1725                if (!NT_STATUS_IS_OK(nt_status)) {
     1726                        return nt_status;
     1727                }
     1728        }
     1729
     1730        if (info_ex) {
     1731                uint32_t origattrs;
     1732                uint32_t origdir;
     1733                uint32_t tmp;
     1734                int origtype;
     1735
     1736                nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
     1737                                                  dom_msg, msg,
     1738                                                  "trustDirection",
     1739                                                  info_ex->trust_direction,
     1740                                                  &origdir);
     1741                if (!NT_STATUS_IS_OK(nt_status)) {
     1742                        return nt_status;
     1743                }
     1744
     1745                tmp = info_ex->trust_direction ^ origdir;
     1746                if (tmp & LSA_TRUST_DIRECTION_INBOUND) {
     1747                        if (origdir & LSA_TRUST_DIRECTION_INBOUND) {
     1748                                del_incoming = true;
     1749                        } else {
     1750                                add_incoming = true;
     1751                        }
     1752                }
     1753                if (tmp & LSA_TRUST_DIRECTION_OUTBOUND) {
     1754                        if (origdir & LSA_TRUST_DIRECTION_OUTBOUND) {
     1755                                del_outgoing = true;
     1756                        } else {
     1757                                add_outgoing = true;
     1758                        }
     1759                }
     1760
     1761                origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
     1762                if (origtype == -1 || origtype != info_ex->trust_type) {
     1763                        DEBUG(1, ("Attempted to change trust type! "
     1764                                  "Operation not handled\n"));
     1765                        return NT_STATUS_INVALID_PARAMETER;
     1766                }
     1767
     1768                nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
     1769                                                  dom_msg, msg,
     1770                                                  "trustAttributes",
     1771                                                  info_ex->trust_attributes,
     1772                                                  &origattrs);
     1773                if (!NT_STATUS_IS_OK(nt_status)) {
     1774                        return nt_status;
     1775                }
     1776                /* TODO: check forestFunctionality from ldb opaque */
     1777                /* TODO: check what is set makes sense */
     1778                /* for now refuse changes */
     1779                if (origattrs == -1 ||
     1780                    origattrs != info_ex->trust_attributes) {
     1781                        DEBUG(1, ("Attempted to change trust attributes! "
     1782                                  "Operation not handled\n"));
     1783                        return NT_STATUS_INVALID_PARAMETER;
     1784                }
     1785        }
     1786
     1787        if (enc_types) {
     1788                nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
     1789                                                  dom_msg, msg,
     1790                                                  "msDS-SupportedEncryptionTypes",
     1791                                                  *enc_types, NULL);
     1792                if (!NT_STATUS_IS_OK(nt_status)) {
     1793                        return nt_status;
     1794                }
     1795        }
     1796
     1797        if (add_incoming && trustAuthIncoming.data) {
     1798                ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
     1799                                        LDB_FLAG_MOD_REPLACE, NULL);
     1800                if (ret != LDB_SUCCESS) {
     1801                        return NT_STATUS_NO_MEMORY;
     1802                }
     1803                ret = ldb_msg_add_value(msg, "trustAuthIncoming",
     1804                                        &trustAuthIncoming, NULL);
     1805                if (ret != LDB_SUCCESS) {
     1806                        return NT_STATUS_NO_MEMORY;
     1807                }
     1808        }
     1809        if (add_outgoing && trustAuthOutgoing.data) {
     1810                ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
     1811                                        LDB_FLAG_MOD_REPLACE, NULL);
     1812                if (ret != LDB_SUCCESS) {
     1813                        return NT_STATUS_NO_MEMORY;
     1814                }
     1815                ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
     1816                                        &trustAuthOutgoing, NULL);
     1817                if (ret != LDB_SUCCESS) {
     1818                        return NT_STATUS_NO_MEMORY;
     1819                }
     1820        }
     1821
     1822        /* start transaction */
     1823        ret = ldb_transaction_start(p_state->sam_ldb);
     1824        if (ret != LDB_SUCCESS) {
     1825                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1826        }
     1827        in_transaction = true;
     1828
     1829        ret = ldb_modify(p_state->sam_ldb, msg);
     1830        if (ret != LDB_SUCCESS) {
     1831                DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
     1832                         ldb_dn_get_linearized(msg->dn),
     1833                         ldb_errstring(p_state->sam_ldb)));
     1834                if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
     1835                        nt_status = NT_STATUS_ACCESS_DENIED;
     1836                } else {
     1837                        nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
     1838                }
     1839                goto done;
     1840        }
     1841
     1842        if (add_incoming || del_incoming) {
     1843                const char *netbios_name;
     1844
     1845                netbios_name = ldb_msg_find_attr_as_string(dom_msg,
     1846                                                           "flatname", NULL);
     1847                if (!netbios_name) {
     1848                        nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
     1849                        goto done;
     1850                }
     1851
     1852                nt_status = update_trust_user(mem_ctx,
     1853                                              p_state->sam_ldb,
     1854                                              p_state->domain_dn,
     1855                                              del_incoming,
     1856                                              netbios_name,
     1857                                              &auth_struct.incoming);
     1858                if (!NT_STATUS_IS_OK(nt_status)) {
     1859                        goto done;
     1860                }
     1861        }
     1862
     1863        /* ok, all fine, commit transaction and return */
     1864        ret = ldb_transaction_commit(p_state->sam_ldb);
     1865        if (ret != LDB_SUCCESS) {
     1866                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1867        }
     1868        in_transaction = false;
     1869
     1870        nt_status = NT_STATUS_OK;
     1871
     1872done:
     1873        if (in_transaction) {
     1874                ldb_transaction_cancel(p_state->sam_ldb);
     1875        }
     1876        return nt_status;
     1877}
     1878
     1879/*
    13271880  lsa_SetInfomrationTrustedDomain
    13281881*/
    1329 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call,
    1330                                                 TALLOC_CTX *mem_ctx,
    1331                                                 struct lsa_SetInformationTrustedDomain *r)
    1332 {
    1333         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     1882static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
     1883                                struct dcesrv_call_state *dce_call,
     1884                                TALLOC_CTX *mem_ctx,
     1885                                struct lsa_SetInformationTrustedDomain *r)
     1886{
     1887        struct dcesrv_handle *h;
     1888        struct lsa_trusted_domain_state *td_state;
     1889        struct ldb_message **msgs;
     1890        NTSTATUS nt_status;
     1891
     1892        DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
     1893                           LSA_HANDLE_TRUSTED_DOMAIN);
     1894
     1895        td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
     1896
     1897        /* get the trusted domain object */
     1898        nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
     1899                            td_state->trusted_domain_dn,
     1900                            NULL, NULL, NULL, &msgs);
     1901        if (!NT_STATUS_IS_OK(nt_status)) {
     1902                if (NT_STATUS_EQUAL(nt_status,
     1903                                    NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     1904                        return nt_status;
     1905                }
     1906                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1907        }
     1908
     1909        return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
     1910                                         msgs[0], r->in.level, r->in.info);
    13341911}
    13351912
     
    14332010        case LSA_TRUSTED_DOMAIN_INFO_NAME:
    14342011                info->name.netbios_name.string
    1435                         = samdb_result_string(msg, "flatname", NULL);                                     
     2012                        = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
    14362013                break;
    14372014        case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
    14382015                info->posix_offset.posix_offset
    1439                         = samdb_result_uint(msg, "posixOffset", 0);                                       
     2016                        = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
    14402017                break;
    14412018#if 0  /* Win2k3 doesn't implement this */
     
    14532030                ZERO_STRUCT(info->full_info);
    14542031                return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
    1455 
    14562032        case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
    14572033                ZERO_STRUCT(info->full_info2_internal);
    14582034                info->full_info2_internal.posix_offset.posix_offset
    1459                         = samdb_result_uint(msg, "posixOffset", 0);                                       
     2035                        = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
    14602036                return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
    14612037               
    14622038        case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
    14632039                info->enc_types.enc_types
    1464                         = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
     2040                        = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
    14652041                break;
    14662042
     
    15272103                                               struct lsa_SetTrustedDomainInfoByName *r)
    15282104{
    1529         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     2105        struct dcesrv_handle *policy_handle;
     2106        struct lsa_policy_state *policy_state;
     2107        struct ldb_message **msgs;
     2108        NTSTATUS nt_status;
     2109
     2110        DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
     2111        policy_state = policy_handle->data;
     2112
     2113        /* get the trusted domain object */
     2114        nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
     2115                            policy_state->domain_dn,
     2116                            r->in.trusted_domain->string,
     2117                            r->in.trusted_domain->string,
     2118                            NULL, &msgs);
     2119        if (!NT_STATUS_IS_OK(nt_status)) {
     2120                if (NT_STATUS_EQUAL(nt_status,
     2121                                    NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     2122                        return nt_status;
     2123                }
     2124                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     2125        }
     2126
     2127        return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
     2128                                         msgs[0], r->in.level, r->in.info);
    15302129}
    15312130
     
    16232222        count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
    16242223                             "objectclass=trustedDomain");
    1625         if (count == -1) {
     2224        if (count < 0) {
    16262225                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    16272226        }
     
    16342233        for (i=0;i<count;i++) {
    16352234                entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
    1636                 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
     2235                entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
    16372236        }
    16382237
    16392238        /* sort the results by name */
    1640         qsort(entries, count, sizeof(*entries),
    1641               (comparison_fn_t)compare_DomainInfo);
     2239        TYPESAFE_QSORT(entries, count, compare_DomainInfo);
    16422240
    16432241        if (*r->in.resume_handle >= count) {
     
    17172315        count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
    17182316                             "objectclass=trustedDomain");
    1719         if (count == -1) {
     2317        if (count < 0) {
    17202318                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    17212319        }
     
    17342332
    17352333        /* sort the results by name */
    1736         qsort(entries, count, sizeof(*entries),
    1737               (comparison_fn_t)compare_TrustDomainInfoInfoEx);
     2334        TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
    17382335
    17392336        if (*r->in.resume_handle >= count) {
     
    18142411        struct dcesrv_handle *h;
    18152412        struct lsa_account_state *astate;
    1816         int ret, i;
     2413        int ret;
     2414        unsigned int i, j;
    18172415        struct ldb_message **res;
    18182416        const char * const attrs[] = { "privilege", NULL};
     
    18402438        }
    18412439
    1842         ret = gendb_search(astate->policy->sam_ldb, mem_ctx, NULL, &res, attrs,
     2440        ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
    18432441                           "objectSid=%s", sidstr);
     2442        if (ret < 0) {
     2443                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     2444        }
    18442445        if (ret != 1) {
    18452446                return NT_STATUS_OK;
     
    18572458        }
    18582459
     2460        j = 0;
    18592461        for (i=0;i<el->num_values;i++) {
    18602462                int id = sec_privilege_id((const char *)el->values[i].data);
    1861                 if (id == -1) {
    1862                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1863                 }
    1864                 privs->set[i].attribute = 0;
    1865                 privs->set[i].luid.low = id;
    1866                 privs->set[i].luid.high = 0;
    1867         }
    1868 
    1869         privs->count = el->num_values;
     2463                if (id == SEC_PRIV_INVALID) {
     2464                        /* Perhaps an account right, not a privilege */
     2465                        continue;
     2466                }
     2467                privs->set[j].attribute = 0;
     2468                privs->set[j].luid.low = id;
     2469                privs->set[j].luid.high = 0;
     2470                j++;
     2471        }
     2472
     2473        privs->count = j;
    18702474
    18712475        return NT_STATUS_OK;
     
    18812485        struct dcesrv_handle *h;
    18822486        struct lsa_policy_state *state;
    1883         int ret, i;
     2487        int ret;
     2488        unsigned int i;
    18842489        struct ldb_message **res;
    18852490        const char * const attrs[] = { "privilege", NULL};
     
    18962501        }
    18972502
    1898         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs,
     2503        ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
    18992504                           "(&(objectSid=%s)(privilege=*))", sidstr);
    19002505        if (ret == 0) {
    19012506                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    19022507        }
    1903         if (ret > 1) {
    1904                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1905         }
    1906         if (ret == -1) {
     2508        if (ret != 1) {
    19072509                DEBUG(3, ("searching for account rights for SID: %s failed: %s",
    19082510                          dom_sid_string(mem_ctx, r->in.sid),
    1909                           ldb_errstring(state->sam_ldb)));
     2511                          ldb_errstring(state->pdb)));
    19102512                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    19112513        }
     
    19422544                                           const struct lsa_RightSet *rights)
    19432545{
    1944         const char *sidstr;
     2546        const char *sidstr, *sidndrstr;
    19452547        struct ldb_message *msg;
    19462548        struct ldb_message_element *el;
    1947         int i, ret;
     2549        int ret;
     2550        uint32_t i;
    19482551        struct lsa_EnumAccountRights r2;
    1949 
    1950         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid);
    1951         if (sidstr == NULL) {
    1952                 return NT_STATUS_NO_MEMORY;
     2552        char *dnstr;
     2553
     2554        if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
     2555            SECURITY_ADMINISTRATOR) {
     2556                DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
     2557                return NT_STATUS_ACCESS_DENIED;
    19532558        }
    19542559
     
    19582563        }
    19592564
    1960         msg->dn = samdb_search_dn(state->sam_ldb, mem_ctx,
    1961                                   NULL, "objectSid=%s", sidstr);
    1962         if (msg->dn == NULL) {
    1963                 NTSTATUS status;
    1964                 if (ldb_flag == LDB_FLAG_MOD_DELETE) {
    1965                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    1966                 }
    1967                 status = samdb_create_foreign_security_principal(state->sam_ldb, mem_ctx,
    1968                                                                  sid, &msg->dn);
    1969                 if (!NT_STATUS_IS_OK(status)) {
    1970                         return status;
    1971                 }
    1972                 return NT_STATUS_NO_SUCH_USER;
    1973         }
    1974 
    1975         if (ldb_msg_add_empty(msg, "privilege", ldb_flag, NULL)) {
    1976                 return NT_STATUS_NO_MEMORY;
    1977         }
    1978 
    1979         if (ldb_flag == LDB_FLAG_MOD_ADD) {
     2565        sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
     2566        NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
     2567
     2568        sidstr = dom_sid_string(msg, sid);
     2569        NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
     2570
     2571        dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
     2572        NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
     2573
     2574        msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
     2575        NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
     2576
     2577        if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
    19802578                NTSTATUS status;
    19812579
     
    19912589
    19922590        for (i=0;i<rights->count;i++) {
    1993                 if (sec_privilege_id(rights->names[i].string) == -1) {
     2591                if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
     2592                        if (sec_right_bit(rights->names[i].string) == 0) {
     2593                                talloc_free(msg);
     2594                                return NT_STATUS_NO_SUCH_PRIVILEGE;
     2595                        }
     2596
     2597                        talloc_free(msg);
    19942598                        return NT_STATUS_NO_SUCH_PRIVILEGE;
    19952599                }
    19962600
    1997                 if (ldb_flag == LDB_FLAG_MOD_ADD) {
    1998                         int j;
     2601                if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
     2602                        uint32_t j;
    19992603                        for (j=0;j<r2.out.rights->count;j++) {
    20002604                                if (strcasecmp_m(r2.out.rights->names[j].string,
     
    20082612                ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
    20092613                if (ret != LDB_SUCCESS) {
     2614                        talloc_free(msg);
    20102615                        return NT_STATUS_NO_MEMORY;
    20112616                }
     
    20142619        el = ldb_msg_find_element(msg, "privilege");
    20152620        if (!el) {
     2621                talloc_free(msg);
    20162622                return NT_STATUS_OK;
    20172623        }
    20182624
    2019         ret = ldb_modify(state->sam_ldb, msg);
    2020         if (ret != 0) {
    2021                 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
    2022                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     2625        el->flags = ldb_flag;
     2626
     2627        ret = ldb_modify(state->pdb, msg);
     2628        if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     2629                if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
     2630                        talloc_free(msg);
     2631                        return NT_STATUS_NO_MEMORY;
     2632                }
     2633                ldb_msg_add_string(msg, "comment", "added via LSA");
     2634                ret = ldb_add(state->pdb, msg);         
     2635        }
     2636        if (ret != LDB_SUCCESS) {
     2637                if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
     2638                        talloc_free(msg);
     2639                        return NT_STATUS_OK;
    20232640                }
    20242641                DEBUG(3, ("Could not %s attributes from %s: %s",
    2025                           ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
    2026                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)));
     2642                          LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
     2643                          ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
     2644                talloc_free(msg);
    20272645                return NT_STATUS_UNEXPECTED_IO_ERROR;
    20282646        }
    20292647
     2648        talloc_free(msg);
    20302649        return NT_STATUS_OK;
    20312650}
     
    20402659        struct dcesrv_handle *h;
    20412660        struct lsa_account_state *astate;
    2042         int i;
     2661        uint32_t i;
    20432662
    20442663        DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
     
    20772696        struct dcesrv_handle *h;
    20782697        struct lsa_account_state *astate;
    2079         int i;
     2698        uint32_t i;
    20802699
    20812700        DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
     
    21562775                       struct lsa_GetSystemAccessAccount *r)
    21572776{
    2158         int i;
    2159         NTSTATUS status;
    2160         struct lsa_EnumPrivsAccount enumPrivs;
    2161         struct lsa_PrivilegeSet *privs;
    2162 
    2163         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
    2164         if (!privs) {
    2165                 return NT_STATUS_NO_MEMORY;
    2166         }
    2167         privs->count = 0;
    2168         privs->unknown = 0;
    2169         privs->set = NULL;
    2170 
    2171         enumPrivs.in.handle = r->in.handle;
    2172         enumPrivs.out.privs = &privs;
    2173 
    2174         status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
    2175         if (!NT_STATUS_IS_OK(status)) {
    2176                 return status;
    2177         }       
     2777        struct dcesrv_handle *h;
     2778        struct lsa_account_state *astate;
     2779        int ret;
     2780        unsigned int i;
     2781        struct ldb_message **res;
     2782        const char * const attrs[] = { "privilege", NULL};
     2783        struct ldb_message_element *el;
     2784        const char *sidstr;
    21782785
    21792786        *(r->out.access_mask) = 0x00000000;
    21802787
    2181         for (i = 0; i < privs->count; i++) {
    2182                 int priv = privs->set[i].luid.low;
    2183 
    2184                 switch (priv) {
    2185                 case SEC_PRIV_INTERACTIVE_LOGON:
    2186                         *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
    2187                         break;
    2188                 case SEC_PRIV_NETWORK_LOGON:
    2189                         *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
    2190                         break;
    2191                 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
    2192                         *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
    2193                         break;
    2194                 }
     2788        DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
     2789
     2790        astate = h->data;
     2791
     2792        sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
     2793        if (sidstr == NULL) {
     2794                return NT_STATUS_NO_MEMORY;
     2795        }
     2796
     2797        ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
     2798                           "objectSid=%s", sidstr);
     2799        if (ret < 0) {
     2800                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     2801        }
     2802        if (ret != 1) {
     2803                return NT_STATUS_OK;
     2804        }
     2805
     2806        el = ldb_msg_find_element(res[0], "privilege");
     2807        if (el == NULL || el->num_values == 0) {
     2808                return NT_STATUS_OK;
     2809        }
     2810
     2811        for (i=0;i<el->num_values;i++) {
     2812                uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
     2813                if (right_bit == 0) {
     2814                        /* Perhaps an privilege, not a right */
     2815                        continue;
     2816                }
     2817                *(r->out.access_mask) |= right_bit;
    21952818        }
    21962819
     
    22312854        ZERO_STRUCTP(r->out.sec_handle);
    22322855       
    2233         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     2856        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    22342857        {
    22352858        case SECURITY_SYSTEM:
     
    22482871       
    22492872        secret_state = talloc(mem_ctx, struct lsa_secret_state);
    2250         if (!secret_state) {
    2251                 return NT_STATUS_NO_MEMORY;
    2252         }
     2873        NT_STATUS_HAVE_NO_MEMORY(secret_state);
    22532874        secret_state->policy = policy_state;
    22542875
     
    22602881        if (strncmp("G$", r->in.name.string, 2) == 0) {
    22612882                const char *name2;
     2883
     2884                secret_state->global = true;
     2885
    22622886                name = &r->in.name.string[2];
    2263                         /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
    2264                 secret_state->sam_ldb = talloc_reference(secret_state,
    2265                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(secret_state, dce_call->conn->dce_ctx->lp_ctx)));
    2266                 secret_state->global = true;
    2267 
    2268                 if (strlen(name) < 1) {
     2887                if (strlen(name) == 0) {
    22692888                        return NT_STATUS_INVALID_PARAMETER;
    22702889                }
    22712890
    2272                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
     2891                name2 = talloc_asprintf(mem_ctx, "%s Secret",
     2892                                        ldb_binary_encode_string(mem_ctx, name));
     2893                NT_STATUS_HAVE_NO_MEMORY(name2);
     2894
     2895                /* We need to connect to the database as system, as this is one
     2896                 * of the rare RPC calls that must read the secrets (and this
     2897                 * is denied otherwise) */
     2898                secret_state->sam_ldb = talloc_reference(secret_state,
     2899                                                         samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
     2900                NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
     2901
    22732902                /* search for the secret record */
    22742903                ret = gendb_search(secret_state->sam_ldb,
     
    22802909                }
    22812910               
    2282                 if (ret == -1) {
     2911                if (ret < 0) {
    22832912                        DEBUG(0,("Failure searching for CN=%s: %s\n",
    22842913                                 name2, ldb_errstring(secret_state->sam_ldb)));
     
    22872916
    22882917                msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
    2289                 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
     2918                NT_STATUS_HAVE_NO_MEMORY(msg->dn);
     2919                if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
    22902920                        return NT_STATUS_NO_MEMORY;
    22912921                }
    2292                
    2293                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
    2294        
     2922
     2923                ret = ldb_msg_add_string(msg, "cn", name2);
     2924                if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
    22952925        } else {
    22962926                secret_state->global = false;
    22972927
    22982928                name = r->in.name.string;
    2299                 if (strlen(name) < 1) {
     2929                if (strlen(name) == 0) {
    23002930                        return NT_STATUS_INVALID_PARAMETER;
    23012931                }
    23022932
    23032933                secret_state->sam_ldb = talloc_reference(secret_state,
    2304                                                          secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
     2934                                                         secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
     2935                NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
     2936
    23052937                /* search for the secret record */
    23062938                ret = gendb_search(secret_state->sam_ldb, mem_ctx,
     
    23132945                }
    23142946               
    2315                 if (ret == -1) {
     2947                if (ret < 0) {
    23162948                        DEBUG(0,("Failure searching for CN=%s: %s\n",
    23172949                                 name, ldb_errstring(secret_state->sam_ldb)));
     
    23192951                }
    23202952
    2321                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
    2322                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
     2953                msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
     2954                                         "cn=%s,cn=LSA Secrets", name);
     2955                NT_STATUS_HAVE_NO_MEMORY(msg->dn);
     2956                ret = ldb_msg_add_string(msg, "cn", name);
     2957                if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
    23232958        }
    23242959
    2325         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
     2960        ret = ldb_msg_add_string(msg, "objectClass", "secret");
     2961        if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
    23262962       
    23272963        secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
     2964        NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
    23282965
    23292966        /* create the secret */
    23302967        ret = ldb_add(secret_state->sam_ldb, msg);
    2331         if (ret != 0) {
     2968        if (ret != LDB_SUCCESS) {
    23322969                DEBUG(0,("Failed to create secret record %s: %s\n",
    23332970                         ldb_dn_get_linearized(msg->dn),
     
    23362973        }
    23372974
     2975        handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
     2976        NT_STATUS_HAVE_NO_MEMORY(handle);
     2977
     2978        handle->data = talloc_steal(handle, secret_state);
     2979       
     2980        secret_state->access_mask = r->in.access_mask;
     2981        secret_state->policy = talloc_reference(secret_state, policy_state);
     2982        NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
     2983       
     2984        *r->out.sec_handle = handle->wire_handle;
     2985       
     2986        return NT_STATUS_OK;
     2987}
     2988
     2989
     2990/*
     2991  lsa_OpenSecret
     2992*/
     2993static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     2994                               struct lsa_OpenSecret *r)
     2995{
     2996        struct dcesrv_handle *policy_handle;
     2997       
     2998        struct lsa_policy_state *policy_state;
     2999        struct lsa_secret_state *secret_state;
     3000        struct dcesrv_handle *handle;
     3001        struct ldb_message **msgs;
     3002        const char *attrs[] = {
     3003                NULL
     3004        };
     3005
     3006        const char *name;
     3007
     3008        int ret;
     3009
     3010        DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
     3011        ZERO_STRUCTP(r->out.sec_handle);
     3012        policy_state = policy_handle->data;
     3013
     3014        if (!r->in.name.string) {
     3015                return NT_STATUS_INVALID_PARAMETER;
     3016        }
     3017       
     3018        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
     3019        {
     3020        case SECURITY_SYSTEM:
     3021        case SECURITY_ADMINISTRATOR:
     3022                break;
     3023        default:
     3024                /* Users and annonymous are not allowed to access secrets */
     3025                return NT_STATUS_ACCESS_DENIED;
     3026        }
     3027
     3028        secret_state = talloc(mem_ctx, struct lsa_secret_state);
     3029        if (!secret_state) {
     3030                return NT_STATUS_NO_MEMORY;
     3031        }
     3032        secret_state->policy = policy_state;
     3033
     3034        if (strncmp("G$", r->in.name.string, 2) == 0) {
     3035                name = &r->in.name.string[2];
     3036                /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
     3037                secret_state->sam_ldb = talloc_reference(secret_state,
     3038                                                         samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0));
     3039                secret_state->global = true;
     3040
     3041                if (strlen(name) < 1) {
     3042                        return NT_STATUS_INVALID_PARAMETER;
     3043                }
     3044
     3045                /* search for the secret record */
     3046                ret = gendb_search(secret_state->sam_ldb,
     3047                                   mem_ctx, policy_state->system_dn, &msgs, attrs,
     3048                                   "(&(cn=%s Secret)(objectclass=secret))",
     3049                                   ldb_binary_encode_string(mem_ctx, name));
     3050                if (ret == 0) {
     3051                        return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     3052                }
     3053               
     3054                if (ret != 1) {
     3055                        DEBUG(0,("Found %d records matching DN %s\n", ret,
     3056                                 ldb_dn_get_linearized(policy_state->system_dn)));
     3057                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     3058                }
     3059       
     3060        } else {
     3061                secret_state->global = false;
     3062                secret_state->sam_ldb = talloc_reference(secret_state,
     3063                                                         secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
     3064
     3065                name = r->in.name.string;
     3066                if (strlen(name) < 1) {
     3067                        return NT_STATUS_INVALID_PARAMETER;
     3068                }
     3069
     3070                /* search for the secret record */
     3071                ret = gendb_search(secret_state->sam_ldb, mem_ctx,
     3072                                   ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
     3073                                   &msgs, attrs,
     3074                                   "(&(cn=%s)(objectclass=secret))",
     3075                                   ldb_binary_encode_string(mem_ctx, name));
     3076                if (ret == 0) {
     3077                        return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     3078                }
     3079               
     3080                if (ret != 1) {
     3081                        DEBUG(0,("Found %d records matching CN=%s\n",
     3082                                 ret, ldb_binary_encode_string(mem_ctx, name)));
     3083                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     3084                }
     3085        }
     3086
     3087        secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
     3088       
    23383089        handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
    23393090        if (!handle) {
     
    23533104
    23543105/*
    2355   lsa_OpenSecret
    2356 */
    2357 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2358                                struct lsa_OpenSecret *r)
    2359 {
    2360         struct dcesrv_handle *policy_handle;
    2361        
    2362         struct lsa_policy_state *policy_state;
    2363         struct lsa_secret_state *secret_state;
    2364         struct dcesrv_handle *handle;
    2365         struct ldb_message **msgs;
    2366         const char *attrs[] = {
    2367                 NULL
    2368         };
    2369 
    2370         const char *name;
    2371 
    2372         int ret;
    2373 
    2374         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
    2375         ZERO_STRUCTP(r->out.sec_handle);
    2376         policy_state = policy_handle->data;
    2377 
    2378         if (!r->in.name.string) {
    2379                 return NT_STATUS_INVALID_PARAMETER;
    2380         }
    2381        
    2382         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
    2383         {
    2384         case SECURITY_SYSTEM:
    2385         case SECURITY_ADMINISTRATOR:
    2386                 break;
    2387         default:
    2388                 /* Users and annonymous are not allowed to access secrets */
    2389                 return NT_STATUS_ACCESS_DENIED;
    2390         }
    2391 
    2392         secret_state = talloc(mem_ctx, struct lsa_secret_state);
    2393         if (!secret_state) {
    2394                 return NT_STATUS_NO_MEMORY;
    2395         }
    2396         secret_state->policy = policy_state;
    2397 
    2398         if (strncmp("G$", r->in.name.string, 2) == 0) {
    2399                 name = &r->in.name.string[2];
    2400                 /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
    2401                 secret_state->sam_ldb = talloc_reference(secret_state,
    2402                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(secret_state, dce_call->conn->dce_ctx->lp_ctx)));
    2403                 secret_state->global = true;
    2404 
    2405                 if (strlen(name) < 1) {
    2406                         return NT_STATUS_INVALID_PARAMETER;
    2407                 }
    2408 
    2409                 /* search for the secret record */
    2410                 ret = gendb_search(secret_state->sam_ldb,
    2411                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
    2412                                    "(&(cn=%s Secret)(objectclass=secret))",
    2413                                    ldb_binary_encode_string(mem_ctx, name));
    2414                 if (ret == 0) {
    2415                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    2416                 }
    2417                
    2418                 if (ret != 1) {
    2419                         DEBUG(0,("Found %d records matching DN %s\n", ret,
    2420                                  ldb_dn_get_linearized(policy_state->system_dn)));
    2421                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2422                 }
    2423        
    2424         } else {
    2425                 secret_state->global = false;
    2426                 secret_state->sam_ldb = talloc_reference(secret_state,
    2427                                  secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
    2428 
    2429                 name = r->in.name.string;
    2430                 if (strlen(name) < 1) {
    2431                         return NT_STATUS_INVALID_PARAMETER;
    2432                 }
    2433 
    2434                 /* search for the secret record */
    2435                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
    2436                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
    2437                                    &msgs, attrs,
    2438                                    "(&(cn=%s)(objectclass=secret))",
    2439                                    ldb_binary_encode_string(mem_ctx, name));
    2440                 if (ret == 0) {
    2441                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    2442                 }
    2443                
    2444                 if (ret != 1) {
    2445                         DEBUG(0,("Found %d records matching CN=%s\n",
    2446                                  ret, ldb_binary_encode_string(mem_ctx, name)));
    2447                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2448                 }
    2449         }
    2450 
    2451         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
    2452        
    2453         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
    2454         if (!handle) {
    2455                 return NT_STATUS_NO_MEMORY;
    2456         }
    2457        
    2458         handle->data = talloc_steal(handle, secret_state);
    2459        
    2460         secret_state->access_mask = r->in.access_mask;
    2461         secret_state->policy = talloc_reference(secret_state, policy_state);
    2462        
    2463         *r->out.sec_handle = handle->wire_handle;
    2464        
    2465         return NT_STATUS_OK;
    2466 }
    2467 
    2468 
    2469 /*
    24703106  lsa_SetSecret
    24713107*/
     
    25183154               
    25193155                /* set value */
    2520                 if (samdb_msg_add_value(secret_state->sam_ldb,
    2521                                         mem_ctx, msg, "priorValue", &val) != 0) {
     3156                if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
    25223157                        return NT_STATUS_NO_MEMORY;
    25233158                }
     
    25253160                /* set old value mtime */
    25263161                if (samdb_msg_add_uint64(secret_state->sam_ldb,
    2527                                          mem_ctx, msg, "priorSetTime", nt_now) != 0) {
     3162                                         mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
    25283163                        return NT_STATUS_NO_MEMORY;
    25293164                }
     
    25593194                if (old_val) {
    25603195                        /* set old value */
    2561                         if (samdb_msg_add_value(secret_state->sam_ldb,
    2562                                                 mem_ctx, msg, "priorValue",
    2563                                                 old_val) != 0) {
     3196                        if (ldb_msg_add_value(msg, "priorValue",
     3197                                              old_val, NULL) != LDB_SUCCESS) {
    25643198                                return NT_STATUS_NO_MEMORY;
    25653199                        }
    25663200                } else {
    25673201                        if (samdb_msg_add_delete(secret_state->sam_ldb,
    2568                                                  mem_ctx, msg, "priorValue")) {
     3202                                                 mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
    25693203                                return NT_STATUS_NO_MEMORY;
    25703204                        }
     
    25753209                if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
    25763210                        if (samdb_msg_add_uint64(secret_state->sam_ldb,
    2577                                                  mem_ctx, msg, "priorSetTime", last_set_time) != 0) {
     3211                                                 mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
    25783212                                return NT_STATUS_NO_MEMORY;
    25793213                        }
    25803214                } else {
    25813215                        if (samdb_msg_add_uint64(secret_state->sam_ldb,
    2582                                                  mem_ctx, msg, "priorSetTime", nt_now) != 0) {
     3216                                                 mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
    25833217                                return NT_STATUS_NO_MEMORY;
    25843218                        }
     
    26003234               
    26013235                /* set value */
    2602                 if (samdb_msg_add_value(secret_state->sam_ldb,
    2603                                         mem_ctx, msg, "currentValue", &val) != 0) {
     3236                if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
    26043237                        return NT_STATUS_NO_MEMORY;
    26053238                }
     
    26073240                /* set new value mtime */
    26083241                if (samdb_msg_add_uint64(secret_state->sam_ldb,
    2609                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) {
     3242                                         mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
    26103243                        return NT_STATUS_NO_MEMORY;
    26113244                }
     
    26143247                /* NULL out the NEW value */
    26153248                if (samdb_msg_add_uint64(secret_state->sam_ldb,
    2616                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) {
     3249                                         mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
    26173250                        return NT_STATUS_NO_MEMORY;
    26183251                }
    26193252                if (samdb_msg_add_delete(secret_state->sam_ldb,
    2620                                          mem_ctx, msg, "currentValue")) {
     3253                                         mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
    26213254                        return NT_STATUS_NO_MEMORY;
    26223255                }
     
    26243257
    26253258        /* modify the samdb record */
    2626         ret = samdb_replace(secret_state->sam_ldb, mem_ctx, msg);
    2627         if (ret != 0) {
     3259        ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
     3260        if (ret != LDB_SUCCESS) {
    26283261                /* we really need samdb.c to return NTSTATUS */
    26293262                return NT_STATUS_UNSUCCESSFUL;
     
    26603293
    26613294        /* Ensure user is permitted to read this... */
    2662         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     3295        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    26633296        {
    26643297        case SECURITY_SYSTEM:
     
    27763409
    27773410        id = sec_privilege_id(r->in.name->string);
    2778         if (id == -1) {
     3411        if (id == SEC_PRIV_INVALID) {
    27793412                return NT_STATUS_NO_SUCH_PRIVILEGE;
    27803413        }
     
    28353468        struct lsa_policy_state *state;
    28363469        struct lsa_StringLarge *disp_name = NULL;
    2837         int id;
     3470        enum sec_privilege id;
    28383471
    28393472        DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
     
    28423475
    28433476        id = sec_privilege_id(r->in.name->string);
    2844         if (id == -1) {
     3477        if (id == SEC_PRIV_INVALID) {
    28453478                return NT_STATUS_NO_SUCH_PRIVILEGE;
    28463479        }
     
    28863519
    28873520        privname = r->in.name->string;
    2888         if (sec_privilege_id(privname) == -1) {
     3521        if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
    28893522                return NT_STATUS_NO_SUCH_PRIVILEGE;
    28903523        }
    28913524
    2892         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs,
     3525        ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
    28933526                           "privilege=%s", privname);
    2894         if (ret == -1) {
     3527        if (ret < 0) {
    28953528                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    28963529        }
     
    30043637        }
    30053638
    3006         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
    3007         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
     3639        account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
     3640        authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
    30083641
    30093642        _account_name = talloc(mem_ctx, struct lsa_String);
     
    30453678        union lsa_DomainInformationPolicy *info;
    30463679
    3047         info = talloc(r->out.info, union lsa_DomainInformationPolicy);
     3680        info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
    30483681        if (!info) {
    30493682                return NT_STATUS_NO_MEMORY;
     
    30683701                        return NT_STATUS_INTERNAL_ERROR;
    30693702                }
    3070                 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
    3071                 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
    3072                 k->user_tkt_lifetime = 0;    /* Need to find somewhere to store this, and query in KDC too */
    3073                 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
    3074                 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
     3703                kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
     3704                               smb_krb5_context,
     3705                               k);
    30753706                talloc_free(smb_krb5_context);
    30763707                *r->out.info = info;
     
    32333864}
    32343865
    3235 
    3236 /*
    3237   lsa_LSARSETFORESTTRUSTINFORMATION
    3238 */
    3239 static NTSTATUS dcesrv_lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3240                        struct lsa_LSARSETFORESTTRUSTINFORMATION *r)
    3241 {
    3242         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    3243 }
    3244 
     3866#define DNS_CMP_MATCH 0
     3867#define DNS_CMP_FIRST_IS_CHILD 1
     3868#define DNS_CMP_SECOND_IS_CHILD 2
     3869#define DNS_CMP_NO_MATCH 3
     3870
     3871/* this function assumes names are well formed DNS names.
     3872 * it doesn't validate them */
     3873static int dns_cmp(const char *s1, size_t l1,
     3874                   const char *s2, size_t l2)
     3875{
     3876        const char *p1, *p2;
     3877        size_t t1, t2;
     3878        int cret;
     3879
     3880        if (l1 == l2) {
     3881                if (strcasecmp_m(s1, s2) == 0) {
     3882                        return DNS_CMP_MATCH;
     3883                }
     3884                return DNS_CMP_NO_MATCH;
     3885        }
     3886
     3887        if (l1 > l2) {
     3888                p1 = s1;
     3889                p2 = s2;
     3890                t1 = l1;
     3891                t2 = l2;
     3892                cret = DNS_CMP_FIRST_IS_CHILD;
     3893        } else {
     3894                p1 = s2;
     3895                p2 = s1;
     3896                t1 = l2;
     3897                t2 = l1;
     3898                cret = DNS_CMP_SECOND_IS_CHILD;
     3899        }
     3900
     3901        if (p1[t1 - t2 - 1] != '.') {
     3902                return DNS_CMP_NO_MATCH;
     3903        }
     3904
     3905        if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
     3906                return cret;
     3907        }
     3908
     3909        return DNS_CMP_NO_MATCH;
     3910}
     3911
     3912/* decode all TDOs forest trust info blobs */
     3913static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
     3914                            struct ldb_message *msg,
     3915                            struct ForestTrustInfo *info)
     3916{
     3917        const struct ldb_val *ft_blob;
     3918        enum ndr_err_code ndr_err;
     3919
     3920        ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
     3921        if (!ft_blob || !ft_blob->data) {
     3922                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     3923        }
     3924        /* ldb_val is equivalent to DATA_BLOB */
     3925        ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
     3926                                           (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
     3927        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     3928                return NT_STATUS_INVALID_DOMAIN_STATE;
     3929        }
     3930
     3931        return NT_STATUS_OK;
     3932}
     3933
     3934static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
     3935                            struct ForestTrustInfo *fti)
     3936{
     3937        struct ForestTrustDataDomainInfo *info;
     3938        struct ForestTrustInfoRecord *rec;
     3939
     3940        fti->version = 1;
     3941        fti->count = 2;
     3942        fti->records = talloc_array(fti,
     3943                                    struct ForestTrustInfoRecordArmor, 2);
     3944        if (!fti->records) {
     3945                return NT_STATUS_NO_MEMORY;
     3946        }
     3947
     3948        /* TLN info */
     3949        rec = &fti->records[0].record;
     3950
     3951        rec->flags = 0;
     3952        rec->timestamp = 0;
     3953        rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
     3954
     3955        rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
     3956        if (!rec->data.name.string) {
     3957                return NT_STATUS_NO_MEMORY;
     3958        }
     3959        rec->data.name.size = strlen(rec->data.name.string);
     3960
     3961        /* DOMAIN info */
     3962        rec = &fti->records[1].record;
     3963
     3964        rec->flags = 0;
     3965        rec->timestamp = 0;
     3966        rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
     3967
     3968        info = &rec->data.info;
     3969
     3970        info->sid = *ps->domain_sid;
     3971        info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
     3972        if (!info->dns_name.string) {
     3973                return NT_STATUS_NO_MEMORY;
     3974        }
     3975        info->dns_name.size = strlen(info->dns_name.string);
     3976        info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
     3977        if (!info->netbios_name.string) {
     3978                return NT_STATUS_NO_MEMORY;
     3979        }
     3980        info->netbios_name.size = strlen(info->netbios_name.string);
     3981
     3982        return NT_STATUS_OK;
     3983}
     3984
     3985static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
     3986                             struct lsa_ForestTrustInformation *lfti,
     3987                             struct ForestTrustInfo *fti)
     3988{
     3989        struct lsa_ForestTrustRecord *lrec;
     3990        struct ForestTrustInfoRecord *rec;
     3991        struct lsa_StringLarge *tln;
     3992        struct lsa_ForestTrustDomainInfo *info;
     3993        uint32_t i;
     3994
     3995        fti->version = 1;
     3996        fti->count = lfti->count;
     3997        fti->records = talloc_array(mem_ctx,
     3998                                    struct ForestTrustInfoRecordArmor,
     3999                                    fti->count);
     4000        if (!fti->records) {
     4001                return NT_STATUS_NO_MEMORY;
     4002        }
     4003        for (i = 0; i < fti->count; i++) {
     4004                lrec = lfti->entries[i];
     4005                rec = &fti->records[i].record;
     4006
     4007                rec->flags = lrec->flags;
     4008                rec->timestamp = lrec->time;
     4009                rec->type = lrec->type;
     4010
     4011                switch (lrec->type) {
     4012                case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
     4013                case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
     4014                        tln = &lrec->forest_trust_data.top_level_name;
     4015                        rec->data.name.string =
     4016                                talloc_strdup(mem_ctx, tln->string);
     4017                        if (!rec->data.name.string) {
     4018                                return NT_STATUS_NO_MEMORY;
     4019                        }
     4020                        rec->data.name.size = strlen(rec->data.name.string);
     4021                        break;
     4022                case LSA_FOREST_TRUST_DOMAIN_INFO:
     4023                        info = &lrec->forest_trust_data.domain_info;
     4024                        rec->data.info.sid = *info->domain_sid;
     4025                        rec->data.info.dns_name.string =
     4026                                talloc_strdup(mem_ctx,
     4027                                            info->dns_domain_name.string);
     4028                        if (!rec->data.info.dns_name.string) {
     4029                                return NT_STATUS_NO_MEMORY;
     4030                        }
     4031                        rec->data.info.dns_name.size =
     4032                                strlen(rec->data.info.dns_name.string);
     4033                        rec->data.info.netbios_name.string =
     4034                                talloc_strdup(mem_ctx,
     4035                                            info->netbios_domain_name.string);
     4036                        if (!rec->data.info.netbios_name.string) {
     4037                                return NT_STATUS_NO_MEMORY;
     4038                        }
     4039                        rec->data.info.netbios_name.size =
     4040                                strlen(rec->data.info.netbios_name.string);
     4041                        break;
     4042                default:
     4043                        return NT_STATUS_INVALID_DOMAIN_STATE;
     4044                }
     4045        }
     4046
     4047        return NT_STATUS_OK;
     4048}
     4049
     4050static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
     4051                              uint32_t idx, uint32_t collision_type,
     4052                              uint32_t conflict_type, const char *tdo_name);
     4053
     4054static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
     4055                              const char *tdo_name,
     4056                              struct ForestTrustInfo *tdo_fti,
     4057                              struct ForestTrustInfo *new_fti,
     4058                              struct lsa_ForestTrustCollisionInfo *c_info)
     4059{
     4060        struct ForestTrustInfoRecord *nrec;
     4061        struct ForestTrustInfoRecord *trec;
     4062        const char *dns_name;
     4063        const char *nb_name;
     4064        struct dom_sid *sid;
     4065        const char *tname;
     4066        size_t dns_len;
     4067        size_t nb_len;
     4068        size_t tlen;
     4069        NTSTATUS nt_status;
     4070        uint32_t new_fti_idx;
     4071        uint32_t i;
     4072        /* use always TDO type, until we understand when Xref can be used */
     4073        uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
     4074        bool tln_conflict;
     4075        bool sid_conflict;
     4076        bool nb_conflict;
     4077        bool exclusion;
     4078        bool ex_rule;
     4079        int ret;
     4080
     4081        for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
     4082
     4083                nrec = &new_fti->records[new_fti_idx].record;
     4084                dns_name = NULL;
     4085                tln_conflict = false;
     4086                sid_conflict = false;
     4087                nb_conflict = false;
     4088                exclusion = false;
     4089
     4090                switch (nrec->type) {
     4091                case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
     4092                        /* exclusions do not conflict by definition */
     4093                        break;
     4094
     4095                case FOREST_TRUST_TOP_LEVEL_NAME:
     4096                        dns_name = nrec->data.name.string;
     4097                        dns_len = nrec->data.name.size;
     4098                        break;
     4099
     4100                case LSA_FOREST_TRUST_DOMAIN_INFO:
     4101                        dns_name = nrec->data.info.dns_name.string;
     4102                        dns_len = nrec->data.info.dns_name.size;
     4103                        nb_name = nrec->data.info.netbios_name.string;
     4104                        nb_len = nrec->data.info.netbios_name.size;
     4105                        sid = &nrec->data.info.sid;
     4106                        break;
     4107                }
     4108
     4109                if (!dns_name) continue;
     4110
     4111                /* check if this is already taken and not excluded */
     4112                for (i = 0; i < tdo_fti->count; i++) {
     4113                        trec = &tdo_fti->records[i].record;
     4114
     4115                        switch (trec->type) {
     4116                        case FOREST_TRUST_TOP_LEVEL_NAME:
     4117                                ex_rule = false;
     4118                                tname = trec->data.name.string;
     4119                                tlen = trec->data.name.size;
     4120                                break;
     4121                        case FOREST_TRUST_TOP_LEVEL_NAME_EX:
     4122                                ex_rule = true;
     4123                                tname = trec->data.name.string;
     4124                                tlen = trec->data.name.size;
     4125                                break;
     4126                        case FOREST_TRUST_DOMAIN_INFO:
     4127                                ex_rule = false;
     4128                                tname = trec->data.info.dns_name.string;
     4129                                tlen = trec->data.info.dns_name.size;
     4130                        }
     4131                        ret = dns_cmp(dns_name, dns_len, tname, tlen);
     4132                        switch (ret) {
     4133                        case DNS_CMP_MATCH:
     4134                                /* if it matches exclusion,
     4135                                 * it doesn't conflict */
     4136                                if (ex_rule) {
     4137                                        exclusion = true;
     4138                                        break;
     4139                                }
     4140                                /* fall through */
     4141                        case DNS_CMP_FIRST_IS_CHILD:
     4142                        case DNS_CMP_SECOND_IS_CHILD:
     4143                                tln_conflict = true;
     4144                                /* fall through */
     4145                        default:
     4146                                break;
     4147                        }
     4148
     4149                        /* explicit exclusion, no dns name conflict here */
     4150                        if (exclusion) {
     4151                                tln_conflict = false;
     4152                        }
     4153
     4154                        if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
     4155                                continue;
     4156                        }
     4157
     4158                        /* also test for domain info */
     4159                        if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
     4160                            dom_sid_compare(&trec->data.info.sid, sid) == 0) {
     4161                                sid_conflict = true;
     4162                        }
     4163                        if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
     4164                            strcasecmp_m(trec->data.info.netbios_name.string,
     4165                                         nb_name) == 0) {
     4166                                nb_conflict = true;
     4167                        }
     4168                }
     4169
     4170                if (tln_conflict) {
     4171                        nt_status = add_collision(c_info, new_fti_idx,
     4172                                                  collision_type,
     4173                                                  LSA_TLN_DISABLED_CONFLICT,
     4174                                                  tdo_name);
     4175                }
     4176                if (sid_conflict) {
     4177                        nt_status = add_collision(c_info, new_fti_idx,
     4178                                                  collision_type,
     4179                                                  LSA_SID_DISABLED_CONFLICT,
     4180                                                  tdo_name);
     4181                }
     4182                if (nb_conflict) {
     4183                        nt_status = add_collision(c_info, new_fti_idx,
     4184                                                  collision_type,
     4185                                                  LSA_NB_DISABLED_CONFLICT,
     4186                                                  tdo_name);
     4187                }
     4188        }
     4189
     4190        return NT_STATUS_OK;
     4191}
     4192
     4193static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
     4194                              uint32_t idx, uint32_t collision_type,
     4195                              uint32_t conflict_type, const char *tdo_name)
     4196{
     4197        struct lsa_ForestTrustCollisionRecord **es;
     4198        uint32_t i = c_info->count;
     4199
     4200        es = talloc_realloc(c_info, c_info->entries,
     4201                            struct lsa_ForestTrustCollisionRecord *, i + 1);
     4202        if (!es) {
     4203                return NT_STATUS_NO_MEMORY;
     4204        }
     4205        c_info->entries = es;
     4206        c_info->count = i + 1;
     4207
     4208        es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
     4209        if (!es[i]) {
     4210                return NT_STATUS_NO_MEMORY;
     4211        }
     4212
     4213        es[i]->index = idx;
     4214        es[i]->type = collision_type;
     4215        es[i]->flags.flags = conflict_type;
     4216        es[i]->name.string = talloc_strdup(es[i], tdo_name);
     4217        if (!es[i]->name.string) {
     4218                return NT_STATUS_NO_MEMORY;
     4219        }
     4220        es[i]->name.size = strlen(es[i]->name.string);
     4221
     4222        return NT_STATUS_OK;
     4223}
     4224
     4225/*
     4226  lsa_lsaRSetForestTrustInformation
     4227*/
     4228static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
     4229                                                         TALLOC_CTX *mem_ctx,
     4230                                                         struct lsa_lsaRSetForestTrustInformation *r)
     4231{
     4232        struct dcesrv_handle *h;
     4233        struct lsa_policy_state *p_state;
     4234        const char *trust_attrs[] = { "trustPartner", "trustAttributes",
     4235                                      "msDS-TrustForestTrustInfo", NULL };
     4236        struct ldb_message **dom_res = NULL;
     4237        struct ldb_dn *tdo_dn;
     4238        struct ldb_message *msg;
     4239        int num_res, i;
     4240        const char *td_name;
     4241        uint32_t trust_attributes;
     4242        struct lsa_ForestTrustCollisionInfo *c_info;
     4243        struct ForestTrustInfo *nfti;
     4244        struct ForestTrustInfo *fti;
     4245        DATA_BLOB ft_blob;
     4246        enum ndr_err_code ndr_err;
     4247        NTSTATUS nt_status;
     4248        bool am_rodc;
     4249        int ret;
     4250
     4251        DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
     4252
     4253        p_state = h->data;
     4254
     4255        if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
     4256                return NT_STATUS_INVALID_DOMAIN_STATE;
     4257        }
     4258
     4259        /* abort if we are not a PDC */
     4260        if (!samdb_is_pdc(p_state->sam_ldb)) {
     4261                return NT_STATUS_INVALID_DOMAIN_ROLE;
     4262        }
     4263
     4264        ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
     4265        if (ret == LDB_SUCCESS && am_rodc) {
     4266                return NT_STATUS_NO_SUCH_DOMAIN;
     4267        }
     4268
     4269        /* check caller has TRUSTED_SET_AUTH */
     4270
     4271        /* fetch all trusted domain objects */
     4272        num_res = gendb_search(p_state->sam_ldb, mem_ctx,
     4273                               p_state->system_dn,
     4274                               &dom_res, trust_attrs,
     4275                               "(objectclass=trustedDomain)");
     4276        if (num_res == 0) {
     4277                return NT_STATUS_NO_SUCH_DOMAIN;
     4278        }
     4279
     4280        for (i = 0; i < num_res; i++) {
     4281                td_name = ldb_msg_find_attr_as_string(dom_res[i],
     4282                                                      "trustPartner", NULL);
     4283                if (!td_name) {
     4284                        return NT_STATUS_INVALID_DOMAIN_STATE;
     4285                }
     4286                if (strcasecmp_m(td_name,
     4287                                 r->in.trusted_domain_name->string) == 0) {
     4288                        break;
     4289                }
     4290        }
     4291        if (i >= num_res) {
     4292                return NT_STATUS_NO_SUCH_DOMAIN;
     4293        }
     4294
     4295        tdo_dn = dom_res[i]->dn;
     4296
     4297        trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
     4298                                                     "trustAttributes", 0);
     4299        if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
     4300                return NT_STATUS_INVALID_PARAMETER;
     4301        }
     4302
     4303        if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
     4304                return NT_STATUS_INVALID_PARAMETER;
     4305        }
     4306
     4307        nfti = talloc(mem_ctx, struct ForestTrustInfo);
     4308        if (!nfti) {
     4309                return NT_STATUS_NO_MEMORY;
     4310        }
     4311
     4312        nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
     4313        if (!NT_STATUS_IS_OK(nt_status)) {
     4314                return nt_status;
     4315        }
     4316
     4317        c_info = talloc_zero(r->out.collision_info,
     4318                             struct lsa_ForestTrustCollisionInfo);
     4319        if (!c_info) {
     4320                return NT_STATUS_NO_MEMORY;
     4321        }
     4322
     4323        /* first check own info, then other domains */
     4324        fti = talloc(mem_ctx, struct ForestTrustInfo);
     4325        if (!fti) {
     4326                return NT_STATUS_NO_MEMORY;
     4327        }
     4328
     4329        nt_status = own_ft_info(p_state, fti);
     4330        if (!NT_STATUS_IS_OK(nt_status)) {
     4331                return nt_status;
     4332        }
     4333
     4334        nt_status = check_ft_info(c_info, p_state->domain_dns,
     4335                                  fti, nfti, c_info);
     4336        if (!NT_STATUS_IS_OK(nt_status)) {
     4337                return nt_status;
     4338        }
     4339
     4340        for (i = 0; i < num_res; i++) {
     4341                fti = talloc(mem_ctx, struct ForestTrustInfo);
     4342                if (!fti) {
     4343                        return NT_STATUS_NO_MEMORY;
     4344                }
     4345
     4346                nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
     4347                if (!NT_STATUS_IS_OK(nt_status)) {
     4348                        if (NT_STATUS_EQUAL(nt_status,
     4349                            NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     4350                                continue;
     4351                        }
     4352                        return nt_status;
     4353                }
     4354
     4355                td_name = ldb_msg_find_attr_as_string(dom_res[i],
     4356                                                      "trustPartner", NULL);
     4357                if (!td_name) {
     4358                        return NT_STATUS_INVALID_DOMAIN_STATE;
     4359                }
     4360
     4361                nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
     4362                if (!NT_STATUS_IS_OK(nt_status)) {
     4363                        return nt_status;
     4364                }
     4365        }
     4366
     4367        *r->out.collision_info = c_info;
     4368
     4369        if (r->in.check_only != 0) {
     4370                return NT_STATUS_OK;
     4371        }
     4372
     4373        /* not just a check, write info back */
     4374
     4375        ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
     4376                                       (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
     4377        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     4378                return NT_STATUS_INVALID_PARAMETER;
     4379        }
     4380
     4381        msg = ldb_msg_new(mem_ctx);
     4382        if (msg == NULL) {
     4383                return NT_STATUS_NO_MEMORY;
     4384        }
     4385
     4386        msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
     4387        if (!msg->dn) {
     4388                return NT_STATUS_NO_MEMORY;
     4389        }
     4390
     4391        ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
     4392                                LDB_FLAG_MOD_REPLACE, NULL);
     4393        if (ret != LDB_SUCCESS) {
     4394                return NT_STATUS_NO_MEMORY;
     4395        }
     4396        ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
     4397                                &ft_blob, NULL);
     4398        if (ret != LDB_SUCCESS) {
     4399                return NT_STATUS_NO_MEMORY;
     4400        }
     4401
     4402        ret = ldb_modify(p_state->sam_ldb, msg);
     4403        if (ret != LDB_SUCCESS) {
     4404                DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
     4405                          ldb_errstring(p_state->sam_ldb)));
     4406
     4407                switch (ret) {
     4408                case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
     4409                        return NT_STATUS_ACCESS_DENIED;
     4410                default:
     4411                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     4412                }
     4413        }
     4414
     4415        return NT_STATUS_OK;
     4416}
    32454417
    32464418/*
  • trunk/server/source4/rpc_server/lsa/lsa.h

    r414 r745  
    2727#include "dsdb/samdb/samdb.h"
    2828#include "libcli/ldap/ldap_ndr.h"
    29 #include "lib/ldb/include/ldb_errors.h"
     29#include <ldb_errors.h>
    3030#include "libcli/security/security.h"
    3131#include "libcli/auth/libcli_auth.h"
     
    4141        struct dcesrv_handle *handle;
    4242        struct ldb_context *sam_ldb;
     43        struct ldb_context *pdb;
    4344        uint32_t access_mask;
    4445        struct ldb_dn *domain_dn;
  • trunk/server/source4/rpc_server/lsa/lsa_init.c

    r414 r745  
    4444
    4545        /* make sure the sam database is accessible */
    46         state->sam_ldb = samdb_connect(state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
     46        state->sam_ldb = samdb_connect(state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info, 0);
    4747        if (state->sam_ldb == NULL) {
     48                return NT_STATUS_INVALID_SYSTEM_SERVICE;
     49        }
     50
     51        /* and the privilege database */
     52        state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
     53        if (state->pdb == NULL) {
    4854                return NT_STATUS_INVALID_SYSTEM_SERVICE;
    4955        }
     
    5864        /* work out the forest root_dn - useful for so many calls its worth
    5965           fetching here */
    60         state->forest_dn = samdb_root_dn(state->sam_ldb);
     66        state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
    6167        if (!state->forest_dn) {
    6268                return NT_STATUS_NO_MEMORY;             
     
    8389        talloc_free(dom_res);
    8490
    85         state->domain_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
     91        state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
    8692
    8793        state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
  • trunk/server/source4/rpc_server/lsa/lsa_lookup.c

    r414 r745  
    2222
    2323#include "rpc_server/lsa/lsa.h"
     24#include "libds/common/flag_mapping.h"
    2425
    2526static const struct {
     
    2728        const char *name;
    2829        const char *sid;
    29         int rtype;
     30        enum lsa_SidType rtype;
    3031} well_known[] = {
    3132        {
     
    194195static NTSTATUS lookup_well_known_names(TALLOC_CTX *mem_ctx, const char *domain,
    195196                                        const char *name, const char **authority_name,
    196                                         struct dom_sid **sid, uint32_t *rtype)
    197 {
    198         int i;
     197                                        struct dom_sid **sid, enum lsa_SidType *rtype)
     198{
     199        unsigned int i;
    199200        for (i=0; well_known[i].sid; i++) {
    200201                if (domain) {
     
    220221static NTSTATUS lookup_well_known_sids(TALLOC_CTX *mem_ctx,
    221222                                       const char *sid_str, const char **authority_name,
    222                                        const char **name, uint32_t *rtype)
    223 {
    224         int i;
     223                                       const char **name, enum lsa_SidType *rtype)
     224{
     225        unsigned int i;
    225226        for (i=0; well_known[i].sid; i++) {
    226227                if (strcasecmp_m(sid_str, well_known[i].sid) == 0) {
     
    240241                                       struct loadparm_context *lp_ctx,
    241242                                       struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
    242                                 const char *name, const char **authority_name,
    243                                 struct dom_sid **sid, enum lsa_SidType *rtype)
    244 {
    245         int ret, atype, i;
     243                                       const char *name, const char **authority_name,
     244                                       struct dom_sid **sid, enum lsa_SidType *rtype,
     245                                       uint32_t *rid)
     246{
     247        int ret, i;
     248        uint32_t atype;
    246249        struct ldb_message **res;
    247250        const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
     
    275278                status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
    276279                if (NT_STATUS_IS_OK(status)) {
     280                        dom_sid_split_rid(NULL, *sid, NULL, rid);
     281                        return NT_STATUS_OK;
     282                }
     283
     284                if (username == NULL) {
     285                        *authority_name = NAME_BUILTIN;
     286                        *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
     287                        *rtype = SID_NAME_DOMAIN;
     288                        *rid = 0xFFFFFFFF;
    277289                        return NT_STATUS_OK;
    278290                }
     
    282294                        *sid =  dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
    283295                        *rtype = SID_NAME_DOMAIN;
     296                        dom_sid_split_rid(NULL, *sid, NULL, rid);
    284297                        return NT_STATUS_OK;
    285298                }
     
    288301                        *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
    289302                        *rtype = SID_NAME_DOMAIN;
     303                        *rid = 0xFFFFFFFF;
    290304                        return NT_STATUS_OK;
    291305                }
     
    294308                        *sid =  state->domain_sid;
    295309                        *rtype = SID_NAME_DOMAIN;
     310                        *rid = 0xFFFFFFFF;
    296311                        return NT_STATUS_OK;
    297312                }
     
    300315                        *sid =  state->domain_sid;
    301316                        *rtype = SID_NAME_DOMAIN;
     317                        *rid = 0xFFFFFFFF;
    302318                        return NT_STATUS_OK;
    303319                }
     
    308324                        return NT_STATUS_NO_MEMORY;
    309325                }
    310                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
     326                status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
    311327                if (NT_STATUS_IS_OK(status)) {
    312328                        return status;
     
    318334                        return NT_STATUS_NO_MEMORY;
    319335                }
    320                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
     336                status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
    321337                if (NT_STATUS_IS_OK(status)) {
    322338                        return status;
     
    328344                        return NT_STATUS_NO_MEMORY;
    329345                }
    330                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
     346                status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
    331347                if (NT_STATUS_IS_OK(status)) {
    332348                        return status;
     
    339355                        *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
    340356                        *rtype = SID_NAME_DOMAIN;
     357                        dom_sid_split_rid(NULL, *sid, NULL, rid);
    341358                        return NT_STATUS_OK;
    342359                }
    343360
    344361                /* Look up table of well known names */
    345                 return lookup_well_known_names(mem_ctx, domain, username, authority_name,
    346                                                sid, rtype);
     362                status = lookup_well_known_names(mem_ctx, domain, username, authority_name,
     363                                                 sid, rtype);
     364                if (NT_STATUS_IS_OK(status)) {
     365                        dom_sid_split_rid(NULL, *sid, NULL, rid);
     366                }
     367                return status;
    347368        } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
    348369                *authority_name = NAME_BUILTIN;
     
    360381
    361382        ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
    362         if (ret == 1) {
    363                 domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
    364                 if (domain_sid == NULL) {
    365                         return NT_STATUS_INVALID_SID;
    366                 }
    367         } else {
     383        if (ret != 1) {
     384                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     385        }
     386        domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
     387        if (domain_sid == NULL) {
    368388                return NT_STATUS_INVALID_SID;
    369389        }
     
    372392                *sid = domain_sid;
    373393                *rtype = SID_NAME_DOMAIN;
     394                *rid = 0xFFFFFFFF;
    374395                return NT_STATUS_OK;
    375396        }
     
    378399                           "(&(sAMAccountName=%s)(objectSid=*))",
    379400                           ldb_binary_encode_string(mem_ctx, username));
    380         if (ret == -1) {
    381                 return NT_STATUS_INVALID_SID;
     401        if (ret < 0) {
     402                return NT_STATUS_INTERNAL_DB_CORRUPTION;
    382403        }
    383404
     
    393414                }
    394415
    395                 atype = samdb_result_uint(res[i], "sAMAccountType", 0);
     416                atype = ldb_msg_find_attr_as_uint(res[i], "sAMAccountType", 0);
    396417                       
    397418                *rtype = ds_atype_map(atype);
     
    400421                }
    401422
     423                dom_sid_split_rid(NULL, *sid, NULL, rid);
    402424                return NT_STATUS_OK;
    403425        }
     
    420442{
    421443        struct dom_sid *authority_sid;
    422         int i;
     444        uint32_t i;
    423445
    424446        if (rtype != SID_NAME_DOMAIN) {
     
    490512        }
    491513
     514        /* need to re-add a check for an allocated sid */
     515
    492516        ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
    493517                           "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
    494         if (ret == 1) {
    495                 *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
     518        if ((ret < 0) || (ret > 1)) {
     519                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     520        }
     521        if (ret == 0) {
     522                return NT_STATUS_NOT_FOUND;
     523        }
     524
     525        *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
     526        if (!*name) {
     527                *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
    496528                if (!*name) {
    497                         *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
    498                         if (!*name) {
    499                                 *name = talloc_strdup(mem_ctx, sid_str);
    500                                 NT_STATUS_HAVE_NO_MEMORY(*name);
    501                         }
    502                 }
    503 
    504                 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
    505 
    506                 *rtype = ds_atype_map(atype);
    507 
    508                 return NT_STATUS_OK;
    509         }
    510 
    511         /* need to re-add a check for an allocated sid */
    512 
    513         return NT_STATUS_NOT_FOUND;
     529                        *name = talloc_strdup(mem_ctx, sid_str);
     530                        NT_STATUS_HAVE_NO_MEMORY(*name);
     531                }
     532        }
     533
     534        atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0);
     535        *rtype = ds_atype_map(atype);
     536
     537        return NT_STATUS_OK;
    514538}
    515539
     
    524548        struct lsa_policy_state *state;
    525549        struct lsa_RefDomainList *domains = NULL;
    526         int i;
     550        uint32_t i;
    527551        NTSTATUS status = NT_STATUS_OK;
    528552
     
    683707        struct lsa_LookupSids2 r2;
    684708        NTSTATUS status;
    685         int i;
     709        uint32_t i;
    686710
    687711        ZERO_STRUCT(r2);
     
    737761        struct lsa_policy_state *policy_state;
    738762        struct dcesrv_handle *policy_handle;
    739         int i;
     763        uint32_t i;
    740764        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
    741765        struct lsa_RefDomainList *domains;
     
    775799                const char *authority_name;
    776800                struct dom_sid *sid;
    777                 uint32_t sid_index;
     801                uint32_t sid_index, rid;
    778802                enum lsa_SidType rtype;
    779803                NTSTATUS status2;
     
    786810                r->out.sids->sids[i].flags       = 0;
    787811
    788                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name, &authority_name, &sid, &rtype);
     812                status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name,
     813                                                 &authority_name, &sid, &rtype, &rid);
    789814                if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
    790815                        continue;
     
    878903        struct lsa_policy_state *state;
    879904        struct dcesrv_handle *h;
    880         int i;
     905        uint32_t i;
    881906        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
    882907        struct lsa_RefDomainList *domains;
     
    916941                const char *authority_name;
    917942                struct dom_sid *sid;
    918                 uint32_t rtype, sid_index;
     943                uint32_t sid_index, rid=0;
     944                enum lsa_SidType rtype;
    919945                NTSTATUS status2;
    920946
     
    929955                r->out.sids->sids[i].unknown     = 0;
    930956
    931                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name, 
    932                                                  &authority_name, &sid, &rtype);
     957                status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name,
     958                                                 &authority_name, &sid, &rtype, &rid);
    933959                if (!NT_STATUS_IS_OK(status2)) {
    934960                        continue;
     
    942968
    943969                r->out.sids->sids[i].sid_type    = rtype;
    944                 r->out.sids->sids[i].rid         = sid->sub_auths[sid->num_auths-1];
     970                r->out.sids->sids[i].rid         = rid;
    945971                r->out.sids->sids[i].sid_index   = sid_index;
    946972                r->out.sids->sids[i].unknown     = 0;
     
    967993        struct lsa_LookupNames2 r2;
    968994        NTSTATUS status;
    969         int i;
     995        uint32_t i;
    970996
    971997        ZERO_STRUCT(r2);
  • trunk/server/source4/rpc_server/netlogon/dcerpc_netlogon.c

    r414 r745  
    1 /* 
     1/*
    22   Unix SMB/CIFS implementation.
    33
     
    66   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
    77   Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
    8    Copyright (C) Matthias Dieter Wallnöfer            2009
    9    
     8   Copyright (C) Matthias Dieter Wallnöfer            2009-2010
     9
    1010   This program is free software; you can redistribute it and/or modify
    1111   it under the terms of the GNU General Public License as published by
    1212   the Free Software Foundation; either version 3 of the License, or
    1313   (at your option) any later version.
    14    
     14
    1515   This program is distributed in the hope that it will be useful,
    1616   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1717   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1818   GNU General Public License for more details.
    19    
     19
    2020   You should have received a copy of the GNU General Public License
    2121   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2929#include "../lib/util/util_ldb.h"
    3030#include "../libcli/auth/schannel.h"
    31 #include "auth/gensec/schannel_state.h"
    3231#include "libcli/security/security.h"
    3332#include "param/param.h"
    3433#include "lib/messaging/irpc.h"
     34#include "librpc/gen_ndr/ndr_irpc_c.h"
     35#include "../libcli/ldap/ldap_ndr.h"
     36#include "cldap_server/cldap_server.h"
     37#include "lib/tsocket/tsocket.h"
     38#include "librpc/gen_ndr/ndr_netlogon.h"
    3539#include "librpc/gen_ndr/ndr_irpc.h"
    3640
     
    4044};
    4145
    42 
    4346static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4447                                        struct netr_ServerReqChallenge *r)
     
    5558                dce_call->context->private_data = NULL;
    5659        }
    57        
     60
    5861        pipe_state = talloc(dce_call->context, struct netlogon_server_pipe_state);
    5962        NT_STATUS_HAVE_NO_MEMORY(pipe_state);
     
    6164        pipe_state->client_challenge = *r->in.credentials;
    6265
    63         generate_random_buffer(pipe_state->server_challenge.data, 
     66        generate_random_buffer(pipe_state->server_challenge.data,
    6467                               sizeof(pipe_state->server_challenge.data));
    6568
     
    7780                talloc_get_type(dce_call->context->private_data, struct netlogon_server_pipe_state);
    7881        struct netlogon_creds_CredentialState *creds;
    79         struct ldb_context *schannel_ldb;
    8082        struct ldb_context *sam_ctx;
    8183        struct samr_Password *mach_pwd;
     
    8486        struct ldb_message **msgs;
    8587        NTSTATUS nt_status;
    86         const char *attrs[] = {"unicodePwd", "userAccountControl", 
     88        const char *attrs[] = {"unicodePwd", "userAccountControl",
    8789                               "objectSid", NULL};
    8890
     
    124126                                  NETLOGON_NEG_AUTHENTICATED_RPC;
    125127
    126         if (!pipe_state) {
    127                 DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
    128                 return NT_STATUS_ACCESS_DENIED;
    129         }
    130 
    131         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
    132                                 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
     128        switch (r->in.secure_channel_type) {
     129        case SEC_CHAN_WKSTA:
     130        case SEC_CHAN_DNS_DOMAIN:
     131        case SEC_CHAN_DOMAIN:
     132        case SEC_CHAN_BDC:
     133        case SEC_CHAN_RODC:
     134                break;
     135        default:
     136                DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
     137                          r->in.secure_channel_type));
     138                return NT_STATUS_INVALID_PARAMETER;
     139        }
     140
     141        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
     142                                system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
    133143        if (sam_ctx == NULL) {
    134144                return NT_STATUS_INVALID_SYSTEM_SERVICE;
     
    150160                num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs,
    151161                                           trust_dom_attrs,
    152                                            "(&(trustPartner=%s)(objectclass=trustedDomain))", 
     162                                           "(&(trustPartner=%s)(objectclass=trustedDomain))",
    153163                                           encoded_account);
    154                
     164
    155165                if (num_records == 0) {
    156                         DEBUG(3,("Couldn't find trust [%s] in samdb.\n", 
     166                        DEBUG(3,("Couldn't find trust [%s] in samdb.\n",
    157167                                 encoded_account));
    158                         return NT_STATUS_ACCESS_DENIED;
    159                 }
    160                
     168                        return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
     169                }
     170
    161171                if (num_records > 1) {
    162172                        DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name));
    163173                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
    164174                }
    165                
     175
    166176                flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
    167177                if (!flatname) {
    168178                        /* No flatname for this trust - we can't proceed */
    169                         return NT_STATUS_ACCESS_DENIED;
     179                        return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
    170180                }
    171181                account_name = talloc_asprintf(mem_ctx, "%s$", flatname);
     
    174184                        return NT_STATUS_NO_MEMORY;
    175185                }
    176                
     186
    177187        } else {
    178188                account_name = r->in.account_name;
    179189        }
    180        
     190
    181191        /* pull the user attributes */
    182192        num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
    183                                    "(&(sAMAccountName=%s)(objectclass=user))", 
     193                                   "(&(sAMAccountName=%s)(objectclass=user))",
    184194                                   ldb_binary_encode_string(mem_ctx, account_name));
    185195
    186196        if (num_records == 0) {
    187                 DEBUG(3,("Couldn't find user [%s] in samdb.\n", 
     197                DEBUG(3,("Couldn't find user [%s] in samdb.\n",
    188198                         r->in.account_name));
    189                 return NT_STATUS_ACCESS_DENIED;
     199                return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
    190200        }
    191201
     
    195205        }
    196206
    197        
    198207        user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
    199208
    200209        if (user_account_control & UF_ACCOUNTDISABLE) {
    201210                DEBUG(1, ("Account [%s] is disabled\n", r->in.account_name));
    202                 return NT_STATUS_ACCESS_DENIED;
     211                return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
    203212        }
    204213
     
    206215                if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
    207216                        DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control));
    208                         return NT_STATUS_ACCESS_DENIED;
    209                 }
    210         } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN || 
     217                        return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
     218                }
     219        } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
    211220                   r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
    212221                if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
    213222                        DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control));
    214                        
    215                         return NT_STATUS_ACCESS_DENIED;
     223
     224                        return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
    216225                }
    217226        } else if (r->in.secure_channel_type == SEC_CHAN_BDC) {
    218227                if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
    219228                        DEBUG(1, ("Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x\n", user_account_control));
    220                         return NT_STATUS_ACCESS_DENIED;
     229                        return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
     230                }
     231        } else if (r->in.secure_channel_type == SEC_CHAN_RODC) {
     232                if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
     233                        DEBUG(1, ("Client asked for a RODC secure channel, but is not a RODC: acb flags: 0x%x\n", user_account_control));
     234                        return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
    221235                }
    222236        } else {
    223                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
    224                           r->in.secure_channel_type));
    225                 return NT_STATUS_ACCESS_DENIED;
    226         }
    227 
    228         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
     237                /* we should never reach this */
     238                return NT_STATUS_INTERNAL_ERROR;
     239        }
     240
     241        *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
    229242                                                "objectSid", 0);
    230243
     
    234247        }
    235248
    236         creds = netlogon_creds_server_init(mem_ctx,     
     249        if (!pipe_state) {
     250                DEBUG(1, ("No challenge requested by client, cannot authenticate\n"));
     251                return NT_STATUS_ACCESS_DENIED;
     252        }
     253
     254        creds = netlogon_creds_server_init(mem_ctx,
    237255                                           r->in.account_name,
    238256                                           r->in.computer_name,
    239257                                           r->in.secure_channel_type,
    240                                            &pipe_state->client_challenge, 
    241                                            &pipe_state->server_challenge, 
     258                                           &pipe_state->client_challenge,
     259                                           &pipe_state->server_challenge,
    242260                                           mach_pwd,
    243261                                           r->in.credentials,
    244262                                           r->out.return_credentials,
    245263                                           *r->in.negotiate_flags);
    246        
     264
    247265        if (!creds) {
    248266                return NT_STATUS_ACCESS_DENIED;
     
    251269        creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
    252270
    253         schannel_ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
    254         if (!schannel_ldb) {
    255                 return NT_STATUS_ACCESS_DENIED;
    256         }
    257 
    258         nt_status = schannel_store_session_key_ldb(schannel_ldb, mem_ctx, creds);
    259         talloc_free(schannel_ldb);
     271        nt_status = schannel_save_creds_state(mem_ctx,
     272                                              lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
     273                                              creds);
    260274
    261275        return nt_status;
    262276}
    263                                                  
     277
    264278static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    265279                                        struct netr_ServerAuthenticate *r)
     
    267281        struct netr_ServerAuthenticate3 a;
    268282        uint32_t rid;
    269         /* TODO: 
     283        /* TODO:
    270284         * negotiate_flags is used as an [in] parameter
    271285         * so it need to be initialised.
     
    305319        r3.out.negotiate_flags = r->out.negotiate_flags;
    306320        r3.out.rid = &rid;
    307        
     321
    308322        return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
    309323}
    310324
    311325/*
    312   Validate an incoming authenticator against the credentials for the remote machine.
    313 
    314   The credentials are (re)read and from the schannel database, and
    315   written back after the caclulations are performed.
    316 
    317   The creds_out parameter (if not NULL) returns the credentials, if
    318   the caller needs some of that information.
    319 
    320 */
     326 * NOTE: The following functions are nearly identical to the ones available in
     327 * source3/rpc_server/srv_nelog_nt.c
     328 * The reason we keep 2 copies is that they use different structures to
     329 * represent the auth_info and the decrpc pipes.
     330 */
     331
     332/*
     333 * If schannel is required for this call test that it actually is available.
     334 */
     335static NTSTATUS schannel_check_required(struct dcerpc_auth *auth_info,
     336                                        const char *computer_name,
     337                                        bool integrity, bool privacy)
     338{
     339
     340        if (auth_info && auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
     341                if (!privacy && !integrity) {
     342                        return NT_STATUS_OK;
     343                }
     344
     345                if ((!privacy && integrity) &&
     346                    auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
     347                        return NT_STATUS_OK;
     348                }
     349
     350                if ((privacy || integrity) &&
     351                    auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
     352                        return NT_STATUS_OK;
     353                }
     354        }
     355
     356        /* test didn't pass */
     357        DEBUG(0, ("schannel_check_required: [%s] is not using schannel\n",
     358                  computer_name));
     359
     360        return NT_STATUS_ACCESS_DENIED;
     361}
     362
    321363static NTSTATUS dcesrv_netr_creds_server_step_check(struct dcesrv_call_state *dce_call,
    322                                                     TALLOC_CTX *mem_ctx, 
     364                                                    TALLOC_CTX *mem_ctx,
    323365                                                    const char *computer_name,
    324366                                                    struct netr_Authenticator *received_authenticator,
    325367                                                    struct netr_Authenticator *return_authenticator,
    326                                                     struct netlogon_creds_CredentialState **creds_out) 
     368                                                    struct netlogon_creds_CredentialState **creds_out)
    327369{
    328370        NTSTATUS nt_status;
    329         struct ldb_context *ldb;
    330         bool schannel_global_required = false; /* Should be lp_schannel_server() == true */
    331         bool schannel_in_use = dce_call->conn->auth_state.auth_info
    332                 && dce_call->conn->auth_state.auth_info->auth_type == DCERPC_AUTH_TYPE_SCHANNEL
    333                 && (dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_INTEGRITY
    334                     || dce_call->conn->auth_state.auth_info->auth_level == DCERPC_AUTH_LEVEL_PRIVACY);
    335 
    336         ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
    337         if (!ldb) {
    338                 return NT_STATUS_ACCESS_DENIED;
    339         }
    340         nt_status = schannel_creds_server_step_check_ldb(ldb, mem_ctx,
    341                                                          computer_name,
    342                                                          schannel_global_required,
    343                                                          schannel_in_use,
    344                                                         received_authenticator,
    345                                                          return_authenticator, creds_out);
    346         talloc_free(ldb);
     371        struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
     372        bool schannel_global_required = false; /* Should be lpcfg_schannel_server() == true */
     373
     374        if (schannel_global_required) {
     375                nt_status = schannel_check_required(auth_info,
     376                                                    computer_name,
     377                                                    true, false);
     378                if (!NT_STATUS_IS_OK(nt_status)) {
     379                        return nt_status;
     380                }
     381        }
     382
     383        nt_status = schannel_check_creds_state(mem_ctx,
     384                                               lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
     385                                               computer_name,
     386                                              received_authenticator,
     387                                               return_authenticator,
     388                                               creds_out);
    347389        return nt_status;
    348390}
    349391
    350 /* 
     392/*
    351393  Change the machine account password for the currently connected
    352394  client.  Supplies only the NT#.
     
    358400        struct netlogon_creds_CredentialState *creds;
    359401        struct ldb_context *sam_ctx;
     402        const char * const attrs[] = { "unicodePwd", NULL };
     403        struct ldb_message **res;
     404        struct samr_Password *oldNtHash;
    360405        NTSTATUS nt_status;
     406        int ret;
    361407
    362408        nt_status = dcesrv_netr_creds_server_step_check(dce_call,
    363                                                         mem_ctx, 
    364                                                         r->in.computer_name, 
     409                                                        mem_ctx,
     410                                                        r->in.computer_name,
    365411                                                        r->in.credential, r->out.return_authenticator,
    366412                                                        &creds);
    367413        NT_STATUS_NOT_OK_RETURN(nt_status);
    368414
    369         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));
     415        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
    370416        if (sam_ctx == NULL) {
    371417                return NT_STATUS_INVALID_SYSTEM_SERVICE;
     
    374420        netlogon_creds_des_decrypt(creds, r->in.new_password);
    375421
     422        /* fetch the old password hashes (the NT hash has to exist) */
     423
     424        ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
     425                           "(&(objectClass=user)(objectSid=%s))",
     426                           ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
     427        if (ret != 1) {
     428                return NT_STATUS_WRONG_PASSWORD;
     429        }
     430
     431        nt_status = samdb_result_passwords(mem_ctx,
     432                                           dce_call->conn->dce_ctx->lp_ctx,
     433                                           res[0], NULL, &oldNtHash);
     434        if (!NT_STATUS_IS_OK(nt_status) || !oldNtHash) {
     435                return NT_STATUS_WRONG_PASSWORD;
     436        }
     437
    376438        /* Using the sid for the account as the key, set the password */
    377         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx, 
     439        nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
    378440                                           creds->sid,
    379441                                           NULL, /* Don't have plaintext */
    380442                                           NULL, r->in.new_password,
    381                                            true, /* Password change */
     443                                           NULL, oldNtHash, /* Password change */
    382444                                           NULL, NULL);
    383445        return nt_status;
    384446}
    385447
    386 /* 
     448/*
    387449  Change the machine account password for the currently connected
    388450  client.  Supplies new plaintext.
     
    393455        struct netlogon_creds_CredentialState *creds;
    394456        struct ldb_context *sam_ctx;
     457        const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
     458        struct ldb_message **res;
     459        struct samr_Password *oldLmHash, *oldNtHash;
    395460        NTSTATUS nt_status;
    396461        DATA_BLOB new_password;
     462        int ret;
    397463
    398464        struct samr_CryptPassword password_buf;
    399465
    400466        nt_status = dcesrv_netr_creds_server_step_check(dce_call,
    401                                                         mem_ctx, 
    402                                                         r->in.computer_name, 
     467                                                        mem_ctx,
     468                                                        r->in.computer_name,
    403469                                                        r->in.credential, r->out.return_authenticator,
    404470                                                        &creds);
    405471        NT_STATUS_NOT_OK_RETURN(nt_status);
    406472
    407         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));
     473        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
    408474        if (sam_ctx == NULL) {
    409475                return NT_STATUS_INVALID_SYSTEM_SERVICE;
     
    418484                return NT_STATUS_WRONG_PASSWORD;
    419485        }
    420                
     486
     487        /* fetch the old password hashes (at least one of both has to exist) */
     488
     489        ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
     490                           "(&(objectClass=user)(objectSid=%s))",
     491                           ldap_encode_ndr_dom_sid(mem_ctx, creds->sid));
     492        if (ret != 1) {
     493                return NT_STATUS_WRONG_PASSWORD;
     494        }
     495
     496        nt_status = samdb_result_passwords(mem_ctx,
     497                                           dce_call->conn->dce_ctx->lp_ctx,
     498                                           res[0], &oldLmHash, &oldNtHash);
     499        if (!NT_STATUS_IS_OK(nt_status) || (!oldLmHash && !oldNtHash)) {
     500                return NT_STATUS_WRONG_PASSWORD;
     501        }
     502
    421503        /* Using the sid for the account as the key, set the password */
    422504        nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
     
    424506                                           &new_password, /* we have plaintext */
    425507                                           NULL, NULL,
    426                                            true, /* Password change */
     508                                           oldLmHash, oldNtHash, /* Password change */
    427509                                           NULL, NULL);
    428510        return nt_status;
     
    430512
    431513
    432 /* 
    433   netr_LogonUasLogon 
     514/*
     515  netr_LogonUasLogon
    434516*/
    435517static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    440522
    441523
    442 /* 
    443   netr_LogonUasLogoff 
     524/*
     525  netr_LogonUasLogoff
    444526*/
    445527static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    450532
    451533
    452 /*
     534static NTSTATUS dcesrv_netr_LogonSamLogon_check(const struct netr_LogonSamLogonEx *r)
     535{
     536        switch (r->in.logon_level) {
     537        case NetlogonInteractiveInformation:
     538        case NetlogonServiceInformation:
     539        case NetlogonInteractiveTransitiveInformation:
     540        case NetlogonServiceTransitiveInformation:
     541                if (r->in.logon->password == NULL) {
     542                        return NT_STATUS_INVALID_PARAMETER;
     543                }
     544
     545                switch (r->in.validation_level) {
     546                case NetlogonValidationSamInfo:  /* 2 */
     547                case NetlogonValidationSamInfo2: /* 3 */
     548                case NetlogonValidationSamInfo4: /* 6 */
     549                        break;
     550                default:
     551                        return NT_STATUS_INVALID_INFO_CLASS;
     552                }
     553
     554                break;
     555        case NetlogonNetworkInformation:
     556        case NetlogonNetworkTransitiveInformation:
     557                if (r->in.logon->network == NULL) {
     558                        return NT_STATUS_INVALID_PARAMETER;
     559                }
     560
     561                switch (r->in.validation_level) {
     562                case NetlogonValidationSamInfo:  /* 2 */
     563                case NetlogonValidationSamInfo2: /* 3 */
     564                case NetlogonValidationSamInfo4: /* 6 */
     565                        break;
     566                default:
     567                        return NT_STATUS_INVALID_INFO_CLASS;
     568                }
     569
     570                break;
     571
     572        case NetlogonGenericInformation:
     573                if (r->in.logon->generic == NULL) {
     574                        return NT_STATUS_INVALID_PARAMETER;
     575                }
     576
     577                switch (r->in.validation_level) {
     578                /* TODO: case NetlogonValidationGenericInfo: 4 */
     579                case NetlogonValidationGenericInfo2: /* 5 */
     580                        break;
     581                default:
     582                        return NT_STATUS_INVALID_INFO_CLASS;
     583                }
     584
     585                break;
     586        default:
     587                return NT_STATUS_INVALID_PARAMETER;
     588        }
     589
     590        return NT_STATUS_OK;
     591}
     592
     593/*
    453594  netr_LogonSamLogon_base
    454595
     
    462603        struct auth_context *auth_context;
    463604        struct auth_usersupplied_info *user_info;
    464         struct auth_serversupplied_info *server_info;
     605        struct auth_user_info_dc *user_info_dc;
    465606        NTSTATUS nt_status;
    466607        static const char zeros[16];
     
    469610        struct netr_SamInfo3 *sam3;
    470611        struct netr_SamInfo6 *sam6;
    471        
    472         user_info = talloc(mem_ctx, struct auth_usersupplied_info);
     612
     613        *r->out.authoritative = 1;
     614
     615        user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
    473616        NT_STATUS_HAVE_NO_MEMORY(user_info);
    474 
    475         user_info->flags = 0;
    476         user_info->mapped_state = false;
    477         user_info->remote_host = NULL;
    478617
    479618        switch (r->in.logon_level) {
     
    483622        case NetlogonServiceTransitiveInformation:
    484623                if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
    485                         netlogon_creds_arcfour_crypt(creds, 
     624                        netlogon_creds_arcfour_crypt(creds,
    486625                                            r->in.logon->password->lmpassword.hash,
    487626                                            sizeof(r->in.logon->password->lmpassword.hash));
    488                         netlogon_creds_arcfour_crypt(creds, 
     627                        netlogon_creds_arcfour_crypt(creds,
    489628                                            r->in.logon->password->ntpassword.hash,
    490629                                            sizeof(r->in.logon->password->ntpassword.hash));
     
    495634
    496635                /* TODO: we need to deny anonymous access here */
    497                 nt_status = auth_context_create(mem_ctx, 
     636                nt_status = auth_context_create(mem_ctx,
    498637                                                dce_call->event_ctx, dce_call->msg_ctx,
    499638                                                dce_call->conn->dce_ctx->lp_ctx,
     
    505644                user_info->client.domain_name = r->in.logon->password->identity_info.domain_name.string;
    506645                user_info->workstation_name = r->in.logon->password->identity_info.workstation.string;
    507                
     646
    508647                user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
    509648                user_info->password_state = AUTH_PASSWORD_HASH;
     
    522661
    523662                /* TODO: we need to deny anonymous access here */
    524                 nt_status = auth_context_create(mem_ctx, 
     663                nt_status = auth_context_create(mem_ctx,
    525664                                                dce_call->event_ctx, dce_call->msg_ctx,
    526665                                                dce_call->conn->dce_ctx->lp_ctx,
     
    535674                user_info->client.domain_name = r->in.logon->network->identity_info.domain_name.string;
    536675                user_info->workstation_name = r->in.logon->network->identity_info.workstation.string;
    537                
     676
    538677                user_info->password_state = AUTH_PASSWORD_RESPONSE;
    539678                user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
    540679                user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
    541        
     680
    542681                break;
    543682
    544                
     683
    545684        case NetlogonGenericInformation:
    546685        {
    547686                if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
    548                         netlogon_creds_arcfour_crypt(creds, 
     687                        netlogon_creds_arcfour_crypt(creds,
    549688                                            r->in.logon->generic->data, r->in.logon->generic->length);
    550689                } else {
     
    555694                if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
    556695                        NTSTATUS status;
    557                         struct server_id *kdc;
     696                        struct dcerpc_binding_handle *irpc_handle;
    558697                        struct kdc_check_generic_kerberos check;
    559698                        struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
    560699                        NT_STATUS_HAVE_NO_MEMORY(generic);
    561700                        *r->out.authoritative = 1;
    562                        
     701
    563702                        /* TODO: Describe and deal with these flags */
    564703                        *r->out.flags = 0;
    565704
    566705                        r->out.validation->generic = generic;
    567        
    568                         kdc = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, "kdc_server");
    569                         if ((kdc == NULL) || (kdc[0].id == 0)) {
     706
     707                        irpc_handle = irpc_binding_handle_by_name(mem_ctx,
     708                                                                  dce_call->msg_ctx,
     709                                                                  "kdc_server",
     710                                                                  &ndr_table_irpc);
     711                        if (irpc_handle == NULL) {
    570712                                return NT_STATUS_NO_LOGON_SERVERS;
    571713                        }
    572                        
    573                         check.in.generic_request = 
     714
     715                        check.in.generic_request =
    574716                                data_blob_const(r->in.logon->generic->data,
    575717                                                r->in.logon->generic->length);
    576                        
    577                         status = irpc_call(dce_call->msg_ctx, kdc[0],
    578                                            &ndr_table_irpc, NDR_KDC_CHECK_GENERIC_KERBEROS,
    579                                            &check, mem_ctx);
     718
     719                        status = dcerpc_kdc_check_generic_kerberos_r(irpc_handle,
     720                                                                     mem_ctx,
     721                                                                     &check);
    580722                        if (!NT_STATUS_IS_OK(status)) {
    581723                                return status;
     
    592734                return NT_STATUS_INVALID_PARAMETER;
    593735        }
    594        
    595         nt_status = auth_check_password(auth_context, mem_ctx, user_info, &server_info);
     736
     737        nt_status = auth_check_password(auth_context, mem_ctx, user_info, &user_info_dc);
     738        /* TODO: set *r->out.authoritative = 0 on specific errors */
    596739        NT_STATUS_NOT_OK_RETURN(nt_status);
    597740
    598         nt_status = auth_convert_server_info_sambaseinfo(mem_ctx, server_info, &sam);
    599         NT_STATUS_NOT_OK_RETURN(nt_status);
     741        switch (r->in.validation_level) {
     742        case 2:
     743                nt_status = auth_convert_user_info_dc_sambaseinfo(mem_ctx, user_info_dc, &sam);
     744                NT_STATUS_NOT_OK_RETURN(nt_status);
     745
     746                sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
     747                NT_STATUS_HAVE_NO_MEMORY(sam2);
     748                sam2->base = *sam;
     749
     750                /* And put into the talloc tree */
     751                talloc_steal(sam2, sam);
     752                r->out.validation->sam2 = sam2;
     753
     754                sam = &sam2->base;
     755                break;
     756
     757        case 3:
     758                nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
     759                                                              user_info_dc,
     760                                                              &sam3);
     761                NT_STATUS_NOT_OK_RETURN(nt_status);
     762
     763                r->out.validation->sam3 = sam3;
     764
     765                sam = &sam3->base;
     766                break;
     767
     768        case 6:
     769                nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
     770                                                           user_info_dc,
     771                                                           &sam3);
     772                NT_STATUS_NOT_OK_RETURN(nt_status);
     773
     774                sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
     775                NT_STATUS_HAVE_NO_MEMORY(sam6);
     776                sam6->base = sam3->base;
     777                sam = &sam6->base;
     778                sam6->sidcount = sam3->sidcount;
     779                sam6->sids = sam3->sids;
     780
     781                sam6->dns_domainname.string = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
     782                sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
     783                                                         sam->account_name.string, sam6->dns_domainname.string);
     784                NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
     785                /* And put into the talloc tree */
     786                talloc_steal(sam6, sam3);
     787
     788                r->out.validation->sam6 = sam6;
     789                break;
     790
     791        default:
     792                return NT_STATUS_INVALID_INFO_CLASS;
     793        }
    600794
    601795        /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
     
    605799                /* This key is sent unencrypted without the ARCFOUR flag set */
    606800                if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
    607                         netlogon_creds_arcfour_crypt(creds, 
    608                                             sam->key.key, 
     801                        netlogon_creds_arcfour_crypt(creds,
     802                                            sam->key.key,
    609803                                            sizeof(sam->key.key));
    610804                }
     
    616810            memcmp(sam->LMSessKey.key, zeros, sizeof(sam->LMSessKey.key)) != 0) {
    617811                if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
    618                         netlogon_creds_arcfour_crypt(creds, 
    619                                             sam->LMSessKey.key, 
     812                        netlogon_creds_arcfour_crypt(creds,
     813                                            sam->LMSessKey.key,
    620814                                            sizeof(sam->LMSessKey.key));
    621815                } else {
    622                         netlogon_creds_des_encrypt_LMKey(creds, 
     816                        netlogon_creds_des_encrypt_LMKey(creds,
    623817                                                &sam->LMSessKey);
    624818                }
    625819        }
    626 
    627         switch (r->in.validation_level) {
    628         case 2:
    629                 sam2 = talloc_zero(mem_ctx, struct netr_SamInfo2);
    630                 NT_STATUS_HAVE_NO_MEMORY(sam2);
    631                 sam2->base = *sam;
    632                 r->out.validation->sam2 = sam2;
    633                 break;
    634 
    635         case 3:
    636                 sam3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
    637                 NT_STATUS_HAVE_NO_MEMORY(sam3);
    638                 sam3->base = *sam;
    639                 r->out.validation->sam3 = sam3;
    640                 break;
    641 
    642         case 6:
    643                 sam6 = talloc_zero(mem_ctx, struct netr_SamInfo6);
    644                 NT_STATUS_HAVE_NO_MEMORY(sam6);
    645                 sam6->base = *sam;
    646                 sam6->forest.string = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
    647                 sam6->principle.string = talloc_asprintf(mem_ctx, "%s@%s",
    648                                                          sam->account_name.string, sam6->forest.string);
    649                 NT_STATUS_HAVE_NO_MEMORY(sam6->principle.string);
    650                 r->out.validation->sam6 = sam6;
    651                 break;
    652 
    653         default:
    654                 break;
    655         }
    656 
    657         *r->out.authoritative = 1;
    658820
    659821        /* TODO: Describe and deal with these flags */
     
    664826
    665827static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    666                                      struct netr_LogonSamLogonEx *r) 
     828                                     struct netr_LogonSamLogonEx *r)
    667829{
    668830        NTSTATUS nt_status;
    669831        struct netlogon_creds_CredentialState *creds;
    670         struct ldb_context *ldb = schannel_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
    671         if (!ldb) {
    672                 return NT_STATUS_ACCESS_DENIED;
    673         }
    674        
    675         nt_status = schannel_fetch_session_key_ldb(ldb, mem_ctx, r->in.computer_name, &creds);
     832
     833        *r->out.authoritative = 1;
     834
     835        nt_status = dcesrv_netr_LogonSamLogon_check(r);
     836        if (!NT_STATUS_IS_OK(nt_status)) {
     837                return nt_status;
     838        }
     839
     840        nt_status = schannel_get_creds_state(mem_ctx,
     841                                             lpcfg_private_dir(dce_call->conn->dce_ctx->lp_ctx),
     842                                             r->in.computer_name, &creds);
    676843        if (!NT_STATUS_IS_OK(nt_status)) {
    677844                return nt_status;
     
    685852}
    686853
    687 /* 
     854/*
    688855  netr_LogonSamLogonWithFlags
    689856
     
    697864
    698865        struct netr_Authenticator *return_authenticator;
    699 
    700         return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
    701         NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
    702 
    703         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
    704                                                         mem_ctx,
    705                                                         r->in.computer_name,
    706                                                         r->in.credential, return_authenticator,
    707                                                         &creds);
    708         NT_STATUS_NOT_OK_RETURN(nt_status);
    709866
    710867        ZERO_STRUCT(r2);
     
    720877        r2.out.flags            = r->out.flags;
    721878
     879        *r->out.authoritative = 1;
     880
     881        nt_status = dcesrv_netr_LogonSamLogon_check(&r2);
     882        if (!NT_STATUS_IS_OK(nt_status)) {
     883                return nt_status;
     884        }
     885
     886        return_authenticator = talloc(mem_ctx, struct netr_Authenticator);
     887        NT_STATUS_HAVE_NO_MEMORY(return_authenticator);
     888
     889        nt_status = dcesrv_netr_creds_server_step_check(dce_call,
     890                                                        mem_ctx,
     891                                                        r->in.computer_name,
     892                                                        r->in.credential, return_authenticator,
     893                                                        &creds);
     894        NT_STATUS_NOT_OK_RETURN(nt_status);
     895
    722896        nt_status = dcesrv_netr_LogonSamLogon_base(dce_call, mem_ctx, &r2, creds);
    723897
     
    727901}
    728902
    729 /* 
     903/*
    730904  netr_LogonSamLogon
    731905*/
     
    759933
    760934
    761 /* 
    762   netr_LogonSamLogoff 
     935/*
     936  netr_LogonSamLogoff
    763937*/
    764938static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    770944
    771945
    772 /* 
    773   netr_DatabaseDeltas 
     946/*
     947  netr_DatabaseDeltas
    774948*/
    775949static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    780954
    781955
    782 /* 
    783   netr_DatabaseSync2 
     956/*
     957  netr_DatabaseSync2
    784958*/
    785959static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    791965
    792966
    793 /* 
    794   netr_DatabaseSync 
     967/*
     968  netr_DatabaseSync
    795969*/
    796970static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    818992
    819993
    820 /* 
    821   netr_AccountDeltas 
     994/*
     995  netr_AccountDeltas
    822996*/
    823997static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    8291003
    8301004
    831 /* 
    832   netr_AccountSync 
     1005/*
     1006  netr_AccountSync
    8331007*/
    8341008static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    8401014
    8411015
    842 /* 
    843   netr_GetDcName 
     1016/*
     1017  netr_GetDcName
    8441018*/
    8451019static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    8531027        const char *dcname;
    8541028
     1029        /*
     1030         * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
     1031         * that the domainname needs to be a valid netbios domain
     1032         * name, if it is not NULL.
     1033         */
     1034        if (r->in.domainname) {
     1035                const char *dot = strchr(r->in.domainname, '.');
     1036                size_t len = strlen(r->in.domainname);
     1037
     1038                if (dot || len > 15) {
     1039                        return WERR_DCNOTFOUND;
     1040                }
     1041
     1042                /*
     1043                 * TODO: Should we also varify that only valid
     1044                 *       netbios name characters are used?
     1045                 */
     1046        }
     1047
    8551048        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
    8561049                                dce_call->conn->dce_ctx->lp_ctx,
    857                                 dce_call->conn->auth_state.session_info);
     1050                                dce_call->conn->auth_state.session_info, 0);
    8581051        if (sam_ctx == NULL) {
    8591052                return WERR_DS_UNAVAILABLE;
     
    8761069         */
    8771070        dcname = talloc_asprintf(mem_ctx, "\\\\%s",
    878                                  lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
     1071                                 lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
    8791072        W_ERROR_HAVE_NO_MEMORY(dcname);
    8801073
     
    8841077
    8851078
    886 /* 
    887   netr_LogonControl2Ex 
     1079/*
     1080  netr_LogonControl2Ex
    8881081*/
    8891082static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    8941087
    8951088
    896 /* 
    897   netr_LogonControl 
     1089/*
     1090  netr_LogonControl
    8981091*/
    8991092static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    9231116
    9241117
    925 /* 
    926   netr_LogonControl2 
     1118/*
     1119  netr_LogonControl2
    9271120*/
    9281121static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    9451138}
    9461139
    947 
    948 /*
    949   netr_GetAnyDCName
     1140static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
     1141                                         struct ldb_context *sam_ctx,
     1142                                         struct netr_DomainTrustList *trusts,
     1143                                         uint32_t trust_flags);
     1144
     1145/*
     1146  netr_GetAnyDCName
    9501147*/
    9511148static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    9521149                       struct netr_GetAnyDCName *r)
    9531150{
    954         struct netr_GetDcName r2;
     1151        struct netr_DomainTrustList *trusts;
     1152        struct ldb_context *sam_ctx;
     1153        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     1154        uint32_t i;
    9551155        WERROR werr;
    9561156
    957         ZERO_STRUCT(r2);
    958 
    959         r2.in.logon_server      = r->in.logon_server;
    960         r2.in.domainname        = r->in.domainname;
    961         r2.out.dcname           = r->out.dcname;
    962 
    963         werr = dcesrv_netr_GetDcName(dce_call, mem_ctx, &r2);
    964 
    965         return werr;
    966 }
    967 
    968 
    969 /*
    970   netr_DatabaseRedo
     1157        *r->out.dcname = NULL;
     1158
     1159        if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
     1160                /* if the domainname parameter wasn't set assume our domain */
     1161                r->in.domainname = lpcfg_workgroup(lp_ctx);
     1162        }
     1163
     1164        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
     1165                                dce_call->conn->auth_state.session_info, 0);
     1166        if (sam_ctx == NULL) {
     1167                return WERR_DS_UNAVAILABLE;
     1168        }
     1169
     1170        if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
     1171                /* well we asked for a DC of our own domain */
     1172                if (samdb_is_pdc(sam_ctx)) {
     1173                        /* we are the PDC of the specified domain */
     1174                        return WERR_NO_SUCH_DOMAIN;
     1175                }
     1176
     1177                *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
     1178                                                lpcfg_netbios_name(lp_ctx));
     1179                W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
     1180
     1181                return WERR_OK;
     1182        }
     1183
     1184        /* Okay, now we have to consider the trusted domains */
     1185
     1186        trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
     1187        W_ERROR_HAVE_NO_MEMORY(trusts);
     1188
     1189        trusts->count = 0;
     1190
     1191        werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
     1192                                          NETR_TRUST_FLAG_INBOUND
     1193                                          | NETR_TRUST_FLAG_OUTBOUND);
     1194        W_ERROR_NOT_OK_RETURN(werr);
     1195
     1196        for (i = 0; i < trusts->count; i++) {
     1197                if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
     1198                        /* FIXME: Here we need to find a DC for the specified
     1199                         * trusted domain. */
     1200
     1201                        /* return WERR_OK; */
     1202                        return WERR_NO_SUCH_DOMAIN;
     1203                }
     1204        }
     1205
     1206        return WERR_NO_SUCH_DOMAIN;
     1207}
     1208
     1209
     1210/*
     1211  netr_DatabaseRedo
    9711212*/
    9721213static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    9771218
    9781219
    979 /* 
    980   netr_NetrEnumerateTurstedDomains
    981 */
    982 static WERROR dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     1220/*
     1221  netr_NetrEnumerateTrustedDomains
     1222*/
     1223static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    9831224                       struct netr_NetrEnumerateTrustedDomains *r)
    9841225{
     
    9871228
    9881229
    989 /* 
     1230/*
    9901231  netr_LogonGetCapabilities
    9911232*/
     
    9981239
    9991240
    1000 /* 
    1001   netr_NETRLOGONSETSERVICEBITS 
     1241/*
     1242  netr_NETRLOGONSETSERVICEBITS
    10021243*/
    10031244static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    10181259
    10191260
    1020 /* 
    1021   netr_NETRLOGONCOMPUTESERVERDIGEST 
     1261/*
     1262  netr_NETRLOGONCOMPUTESERVERDIGEST
    10221263*/
    10231264static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    10281269
    10291270
    1030 /* 
    1031   netr_NETRLOGONCOMPUTECLIENTDIGEST 
     1271/*
     1272  netr_NETRLOGONCOMPUTECLIENTDIGEST
    10321273*/
    10331274static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    10391280
    10401281
    1041 /* 
     1282/*
    10421283  netr_DsRGetSiteName
    10431284*/
     
    10451286                                  struct netr_DsRGetSiteName *r)
    10461287{
    1047         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     1288        struct ldb_context *sam_ctx;
     1289        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     1290
     1291        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
     1292                                dce_call->conn->auth_state.session_info, 0);
     1293        if (sam_ctx == NULL) {
     1294                return WERR_DS_UNAVAILABLE;
     1295        }
     1296
     1297        *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
     1298        W_ERROR_HAVE_NO_MEMORY(*r->out.site);
     1299
     1300        return WERR_OK;
    10481301}
    10491302
     
    10651318                info->trust_extension.info = talloc_zero(mem_ctx, struct netr_trust_extension);
    10661319                info->trust_extension.length = 16;
    1067                 info->trust_extension.info->flags = 
     1320                info->trust_extension.info->flags =
    10681321                        NETR_TRUST_FLAG_TREEROOT |
    1069                         NETR_TRUST_FLAG_IN_FOREST | 
     1322                        NETR_TRUST_FLAG_IN_FOREST |
    10701323                        NETR_TRUST_FLAG_PRIMARY |
    10711324                        NETR_TRUST_FLAG_NATIVE;
     
    10811334                info->dns_forestname.string = NULL;
    10821335        } else {
    1083                 char *p;
    1084                 /* TODO: we need a common function for pulling the forest */
    1085                 info->dns_forestname.string = ldb_dn_canonical_string(info, ldb_get_root_basedn(sam_ctx));
    1086                 if (!info->dns_forestname.string) {
    1087                         return NT_STATUS_NO_SUCH_DOMAIN;               
    1088                 }
    1089                 p = strchr(info->dns_forestname.string, '/');
    1090                 if (p) {
    1091                         *p = '\0';
    1092                 }
     1336                info->dns_forestname.string = samdb_forest_name(sam_ctx, mem_ctx);
     1337                NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
    10931338                info->dns_forestname.string = talloc_asprintf(mem_ctx, "%s.", info->dns_forestname.string);
    1094                                        
     1339                NT_STATUS_HAVE_NO_MEMORY(info->dns_forestname.string);
    10951340        }
    10961341
    10971342        if (is_local) {
    1098                 info->domainname.string = lp_sam_name(lp_ctx);
    1099                 info->dns_domainname.string = lp_realm(lp_ctx);
     1343                info->domainname.string = lpcfg_workgroup(lp_ctx);
     1344                info->dns_domainname.string = lpcfg_dnsdomain(lp_ctx);
    11001345                info->domain_guid = samdb_result_guid(res, "objectGUID");
    11011346                info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "objectSid");
    11021347        } else {
    1103                 info->domainname.string = samdb_result_string(res, "flatName", NULL);
    1104                 info->dns_domainname.string = samdb_result_string(res, "trustPartner", NULL);
     1348                info->domainname.string = ldb_msg_find_attr_as_string(res, "flatName", NULL);
     1349                info->dns_domainname.string = ldb_msg_find_attr_as_string(res, "trustPartner", NULL);
    11051350                info->domain_guid = samdb_result_guid(res, "objectGUID");
    11061351                info->domain_sid = samdb_result_dom_sid(mem_ctx, res, "securityIdentifier");
     
    11131358}
    11141359
    1115 /* 
     1360/*
    11161361  netr_LogonGetDomainInfo
    11171362  this is called as part of the ADS domain logon procedure.
     
    11261371        const char * const attrs[] = { "objectSid", "objectGUID", "flatName",
    11271372                "securityIdentifier", "trustPartner", NULL };
    1128         const char *temp_str;
    1129         const char *old_dns_hostname;
     1373        const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
     1374                "msDS-SupportedEncryptionTypes", NULL };
     1375        const char *sam_account_name, *old_dns_hostname, *prefix1, *prefix2;
    11301376        struct ldb_context *sam_ctx;
    1131         struct ldb_message **res1, **res2, *new_msg;
     1377        struct ldb_message **res1, **res2, **res3, *new_msg;
    11321378        struct ldb_dn *workstation_dn;
    11331379        struct netr_DomainInformation *domain_info;
    11341380        struct netr_LsaPolicyInformation *lsa_policy_info;
    1135         struct netr_OsVersionInfoEx *os_version;
    11361381        uint32_t default_supported_enc_types = 0xFFFFFFFF;
    1137         int ret1, ret2, i;
     1382        bool update_dns_hostname = true;
     1383        int ret, ret3, i;
    11381384        NTSTATUS status;
    11391385
    11401386        status = dcesrv_netr_creds_server_step_check(dce_call,
    1141                                                      mem_ctx, 
    1142                                                      r->in.computer_name, 
    1143                                                      r->in.credential, 
     1387                                                     mem_ctx,
     1388                                                     r->in.computer_name,
     1389                                                     r->in.credential,
    11441390                                                     r->out.return_authenticator,
    11451391                                                     &creds);
     
    11501396
    11511397        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
    1152                 dce_call->conn->dce_ctx->lp_ctx,
    1153                 system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
     1398                                dce_call->conn->dce_ctx->lp_ctx,
     1399                                system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
    11541400        if (sam_ctx == NULL) {
    11551401                return NT_STATUS_INVALID_SYSTEM_SERVICE;
     
    11591405        case 1: /* Domain information */
    11601406
    1161                 /* TODO: check NTSTATUS results - and fail also on SAMDB
    1162                  * errors (needs some testing against Windows Server 2008) */
     1407                if (r->in.query->workstation_info == NULL) {
     1408                        return NT_STATUS_INVALID_PARAMETER;
     1409                }
     1410
     1411                /* Prepares the workstation DN */
     1412                workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
     1413                                                dom_sid_string(mem_ctx, creds->sid));
     1414                NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
     1415
     1416                /* Lookup for attributes in workstation object */
     1417                ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
     1418                                      attrs2);
     1419                if (ret != 1) {
     1420                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1421                }
     1422
     1423                /* Gets the sam account name which is checked against the DNS
     1424                 * hostname parameter. */
     1425                sam_account_name = ldb_msg_find_attr_as_string(res1[0],
     1426                                                               "sAMAccountName",
     1427                                                               NULL);
     1428                if (sam_account_name == NULL) {
     1429                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
     1430                }
    11631431
    11641432                /*
    1165                  * Check that the computer name parameter matches as prefix with
    1166                  * the DNS hostname in the workstation info structure.
     1433                 * Checks that the sam account name without a possible "$"
     1434                 * matches as prefix with the DNS hostname in the workstation
     1435                 * info structure.
    11671436                 */
    1168                 temp_str = strndup(r->in.query->workstation_info->dns_hostname,
    1169                         strcspn(r->in.query->workstation_info->dns_hostname,
    1170                         "."));
    1171                 if (strcasecmp(r->in.computer_name, temp_str) != 0)
    1172                         return NT_STATUS_INVALID_PARAMETER;
    1173 
    1174                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
    1175                         dom_sid_string(mem_ctx, creds->sid));
    1176                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
     1437                prefix1 = talloc_strndup(mem_ctx, sam_account_name,
     1438                                         strcspn(sam_account_name, "$"));
     1439                NT_STATUS_HAVE_NO_MEMORY(prefix1);
     1440                if (r->in.query->workstation_info->dns_hostname != NULL) {
     1441                        prefix2 = talloc_strndup(mem_ctx,
     1442                                                 r->in.query->workstation_info->dns_hostname,
     1443                                                 strcspn(r->in.query->workstation_info->dns_hostname, "."));
     1444                        NT_STATUS_HAVE_NO_MEMORY(prefix2);
     1445
     1446                        if (strcasecmp(prefix1, prefix2) != 0) {
     1447                                update_dns_hostname = false;
     1448                        }
     1449                } else {
     1450                        update_dns_hostname = false;
     1451                }
    11771452
    11781453                /* Gets the old DNS hostname */
    1179                 old_dns_hostname = samdb_search_string(sam_ctx, mem_ctx,
    1180                                                         workstation_dn,
    1181                                                         "dNSHostName",
    1182                                                         NULL);
    1183 
    1184                 /* Gets host informations and put them in our directory */
     1454                old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
     1455                                                               "dNSHostName",
     1456                                                               NULL);
     1457
     1458                /*
     1459                 * Updates the DNS hostname when the client wishes that the
     1460                 * server should handle this for him
     1461                 * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set). And this is
     1462                 * obviously only checked when we do already have a
     1463                 * "dNSHostName".
     1464                 * See MS-NRPC section 3.5.4.3.9
     1465                 */
     1466                if ((old_dns_hostname != NULL) &&
     1467                    (r->in.query->workstation_info->workstation_flags
     1468                    & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
     1469                        update_dns_hostname = false;
     1470                }
     1471
     1472                /* Gets host information and put them into our directory */
     1473
    11851474                new_msg = ldb_msg_new(mem_ctx);
    11861475                NT_STATUS_HAVE_NO_MEMORY(new_msg);
     
    11881477                new_msg->dn = workstation_dn;
    11891478
    1190                 /* Deletes old OS version values */
    1191                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
    1192                         "operatingSystemServicePack");
    1193                 samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
    1194                         "operatingSystemVersion");
    1195 
    1196                 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
    1197                         DEBUG(3,("Impossible to update samdb: %s\n",
    1198                                 ldb_errstring(sam_ctx)));
    1199                 }
    1200 
    1201                 talloc_free(new_msg);
    1202 
    1203                 new_msg = ldb_msg_new(mem_ctx);
    1204                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
    1205 
    1206                 new_msg->dn = workstation_dn;
    1207 
    12081479                /* Sets the OS name */
    1209                 samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
    1210                         "operatingSystem",
    1211                         r->in.query->workstation_info->os_name.string);
    1212 
    1213                 if (r->in.query->workstation_info->dns_hostname) {
    1214                         /* TODO: should this always be done? */
    1215                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
    1216                                              "dNSHostname",
    1217                                              r->in.query->workstation_info->dns_hostname);
     1480
     1481                if (r->in.query->workstation_info->os_name.string == NULL) {
     1482                        return NT_STATUS_INVALID_PARAMETER;
     1483                }
     1484
     1485                ret = ldb_msg_add_string(new_msg, "operatingSystem",
     1486                                         r->in.query->workstation_info->os_name.string);
     1487                if (ret != LDB_SUCCESS) {
     1488                        return NT_STATUS_NO_MEMORY;
    12181489                }
    12191490
    12201491                /*
    1221                  * Sets informations from "os_version". On a empty structure
     1492                 * Sets information from "os_version". On an empty structure
    12221493                 * the values are cleared.
    12231494                 */
    12241495                if (r->in.query->workstation_info->os_version.os != NULL) {
     1496                        struct netr_OsVersionInfoEx *os_version;
     1497                        const char *os_version_str;
     1498
    12251499                        os_version = &r->in.query->workstation_info->os_version.os->os;
    12261500
    1227                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
    1228                                              "operatingSystemServicePack",
    1229                                              os_version->CSDVersion);
    1230 
    1231                         samdb_msg_set_string(sam_ctx, mem_ctx, new_msg,
    1232                                 "operatingSystemVersion",
    1233                                 talloc_asprintf(mem_ctx, "%d.%d (%d)",
    1234                                         os_version->MajorVersion,
    1235                                         os_version->MinorVersion,
    1236                                         os_version->BuildNumber
    1237                                 )
    1238                         );
     1501                        if (os_version->CSDVersion == NULL) {
     1502                                return NT_STATUS_INVALID_PARAMETER;
     1503                        }
     1504
     1505                        os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
     1506                                                         os_version->MajorVersion,
     1507                                                         os_version->MinorVersion,
     1508                                                         os_version->BuildNumber);
     1509                        NT_STATUS_HAVE_NO_MEMORY(os_version_str);
     1510
     1511                        ret = ldb_msg_add_string(new_msg,
     1512                                                 "operatingSystemServicePack",
     1513                                                 os_version->CSDVersion);
     1514                        if (ret != LDB_SUCCESS) {
     1515                                return NT_STATUS_NO_MEMORY;
     1516                        }
     1517
     1518                        ret = ldb_msg_add_string(new_msg,
     1519                                                 "operatingSystemVersion",
     1520                                                 os_version_str);
     1521                        if (ret != LDB_SUCCESS) {
     1522                                return NT_STATUS_NO_MEMORY;
     1523                        }
     1524                } else {
     1525                        ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
     1526                                                   "operatingSystemServicePack");
     1527                        if (ret != LDB_SUCCESS) {
     1528                                return NT_STATUS_NO_MEMORY;
     1529                        }
     1530
     1531                        ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
     1532                                                   "operatingSystemVersion");
     1533                        if (ret != LDB_SUCCESS) {
     1534                                return NT_STATUS_NO_MEMORY;
     1535                        }
    12391536                }
    12401537
    12411538                /*
    1242                  * Updates the "dNSHostname" and the "servicePrincipalName"s
    1243                  * since the client wishes that the server should handle this
    1244                  * for him ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
    1245                  * See MS-NRPC section 3.5.4.3.9
     1539                 * If the boolean "update_dns_hostname" remained true, then we
     1540                 * are fine to start the update.
    12461541                 */
    1247                 if ((r->in.query->workstation_info->workstation_flags
    1248                         & NETR_WS_FLAG_HANDLES_SPN_UPDATE) == 0) {
    1249 
    1250                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
    1251                                 "servicePrincipalName",
    1252                                 talloc_asprintf(mem_ctx, "HOST/%s",
    1253                                 r->in.computer_name)
    1254                         );
    1255                         samdb_msg_add_string(sam_ctx, mem_ctx, new_msg,
    1256                                 "servicePrincipalName",
    1257                                 talloc_asprintf(mem_ctx, "HOST/%s",
    1258                                 r->in.query->workstation_info->dns_hostname)
    1259                         );
    1260                 }
    1261 
    1262                 if (samdb_replace(sam_ctx, mem_ctx, new_msg) != LDB_SUCCESS) {
     1542                if (update_dns_hostname) {
     1543                        ret = ldb_msg_add_string(new_msg,
     1544                                                 "dNSHostname",
     1545                                                 r->in.query->workstation_info->dns_hostname);
     1546                        if (ret != LDB_SUCCESS) {
     1547                                return NT_STATUS_NO_MEMORY;
     1548                        }
     1549
     1550                        /* This manual "servicePrincipalName" generation is
     1551                         * still needed! Since the update in the samldb LDB
     1552                         * module does only work if the entries already exist
     1553                         * which isn't always the case. */
     1554                        ret = ldb_msg_add_string(new_msg,
     1555                                                 "servicePrincipalName",
     1556                                                 talloc_asprintf(new_msg, "HOST/%s",
     1557                                                 r->in.computer_name));
     1558                        if (ret != LDB_SUCCESS) {
     1559                                return NT_STATUS_NO_MEMORY;
     1560                        }
     1561
     1562                        ret = ldb_msg_add_string(new_msg,
     1563                                                 "servicePrincipalName",
     1564                                                 talloc_asprintf(new_msg, "HOST/%s",
     1565                                                 r->in.query->workstation_info->dns_hostname));
     1566                        if (ret != LDB_SUCCESS) {
     1567                                return NT_STATUS_NO_MEMORY;
     1568                        }
     1569                }
     1570
     1571                if (dsdb_replace(sam_ctx, new_msg, 0) != LDB_SUCCESS) {
    12631572                        DEBUG(3,("Impossible to update samdb: %s\n",
    12641573                                ldb_errstring(sam_ctx)));
     
    12741583                   put the primary domain into the lists of returned trusts as
    12751584                   well. */
    1276                 ret1 = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(sam_ctx),
    1277                         &res1, attrs);
    1278                 if (ret1 != 1) {
     1585                ret = gendb_search_dn(sam_ctx, mem_ctx, ldb_get_default_basedn(sam_ctx),
     1586                        &res2, attrs);
     1587                if (ret != 1) {
    12791588                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
    12801589                }
    12811590
    1282                 ret2 = gendb_search(sam_ctx, mem_ctx, NULL, &res2, attrs,
     1591                ret3 = gendb_search(sam_ctx, mem_ctx, NULL, &res3, attrs,
    12831592                        "(objectClass=trustedDomain)");
    1284                 if (ret2 == -1) {
     1593                if (ret3 == -1) {
    12851594                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
    12861595                }
     
    12951604                status = fill_one_domain_info(mem_ctx,
    12961605                        dce_call->conn->dce_ctx->lp_ctx,
    1297                         sam_ctx, res1[0], &domain_info->primary_domain,
     1606                        sam_ctx, res2[0], &domain_info->primary_domain,
    12981607                        true, false);
    12991608                NT_STATUS_NOT_OK_RETURN(status);
    13001609
    1301                 domain_info->trusted_domain_count = ret2 + 1;
     1610                domain_info->trusted_domain_count = ret3 + 1;
    13021611                domain_info->trusted_domains = talloc_array(mem_ctx,
    13031612                        struct netr_OneDomainInfo,
     
    13051614                NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
    13061615
    1307                 for (i=0;i<ret2;i++) {
     1616                for (i=0;i<ret3;i++) {
    13081617                        status = fill_one_domain_info(mem_ctx,
    13091618                                dce_call->conn->dce_ctx->lp_ctx,
    1310                                 sam_ctx, res2[i],
     1619                                sam_ctx, res3[i],
    13111620                                &domain_info->trusted_domains[i],
    13121621                                false, true);
     
    13151624
    13161625                status = fill_one_domain_info(mem_ctx,
    1317                         dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res1[0],
     1626                        dce_call->conn->dce_ctx->lp_ctx, sam_ctx, res2[0],
    13181627                        &domain_info->trusted_domains[i], true, true);
    13191628                NT_STATUS_NOT_OK_RETURN(status);
    13201629
    13211630                /* Sets the supported encryption types */
    1322                 domain_info->supported_enc_types = samdb_search_uint(
    1323                         sam_ctx, mem_ctx,
    1324                         default_supported_enc_types, workstation_dn,
    1325                         "msDS-SupportedEncryptionTypes", NULL);
    1326 
    1327                 /* Other host domain informations */
     1631                domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
     1632                        "msDS-SupportedEncryptionTypes",
     1633                        default_supported_enc_types);
     1634
     1635                /* Other host domain information */
    13281636
    13291637                lsa_policy_info = talloc(mem_ctx,
     
    13341642                domain_info->lsa_policy = *lsa_policy_info;
    13351643
    1336                 domain_info->dns_hostname.string = old_dns_hostname;
     1644                /* The DNS hostname is only returned back when there is a chance
     1645                 * for a change. */
     1646                if ((r->in.query->workstation_info->workstation_flags
     1647                    & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
     1648                        domain_info->dns_hostname.string = old_dns_hostname;
     1649                } else {
     1650                        domain_info->dns_hostname.string = NULL;
     1651                }
     1652
    13371653                domain_info->workstation_flags =
    13381654                        r->in.query->workstation_info->workstation_flags;
     
    13571673
    13581674
    1359 
    13601675/*
    13611676  netr_ServerPasswordGet
     
    13681683
    13691684
    1370 /* 
    1371   netr_NETRLOGONSENDTOSAM 
     1685/*
     1686  netr_NETRLOGONSENDTOSAM
    13721687*/
    13731688static WERROR dcesrv_netr_NETRLOGONSENDTOSAM(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    13781693
    13791694
    1380 /*
    1381   netr_DsRAddressToSitenamesW
    1382 */
    1383 static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1384                        struct netr_DsRAddressToSitenamesW *r)
    1385 {
    1386         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1387 }
    1388 
    1389 
    1390 /*
     1695/*
    13911696  netr_DsRGetDCNameEx2
    13921697*/
    1393 static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1394                                    struct netr_DsRGetDCNameEx2 *r)
    1395 {
    1396         const char * const attrs[] = { "objectGUID", NULL };
     1698static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
     1699                                          TALLOC_CTX *mem_ctx,
     1700                                          struct netr_DsRGetDCNameEx2 *r)
     1701{
    13971702        struct ldb_context *sam_ctx;
    1398         struct ldb_message **res;
    1399         struct ldb_dn *domain_dn;
    1400         int ret;
    14011703        struct netr_DsRGetDCNameInfo *info;
     1704        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     1705        const struct tsocket_address *remote_address;
     1706        char *addr = NULL;
     1707        const char *server_site_name;
     1708        char *guid_str;
     1709        struct netlogon_samlogon_response response;
     1710        NTSTATUS status;
     1711        const char *dc_name = NULL;
     1712        const char *domain_name = NULL;
    14021713
    14031714        ZERO_STRUCTP(r->out.info);
    14041715
    1405         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
     1716        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
     1717                                dce_call->conn->auth_state.session_info, 0);
    14061718        if (sam_ctx == NULL) {
    14071719                return WERR_DS_UNAVAILABLE;
    14081720        }
    14091721
    1410         /* Win7-beta will send the domain name in the form the user typed, so we have to cope
    1411            with both the short and long form here */
    1412         if (r->in.domain_name != NULL && !lp_is_my_domain_or_realm(dce_call->conn->dce_ctx->lp_ctx,
    1413                                                                 r->in.domain_name)) {
     1722        remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
     1723        if (tsocket_address_is_inet(remote_address, "ip")) {
     1724                addr = tsocket_address_inet_addr_string(remote_address, mem_ctx);
     1725                W_ERROR_HAVE_NO_MEMORY(addr);
     1726        }
     1727
     1728        /* "server_unc" is ignored by w2k3 */
     1729
     1730        if (r->in.flags & ~(DSGETDC_VALID_FLAGS)) {
     1731                return WERR_INVALID_FLAGS;
     1732        }
     1733
     1734        if (r->in.flags & DS_GC_SERVER_REQUIRED &&
     1735            r->in.flags & DS_PDC_REQUIRED &&
     1736            r->in.flags & DS_KDC_REQUIRED) {
     1737                return WERR_INVALID_FLAGS;
     1738        }
     1739        if (r->in.flags & DS_IS_FLAT_NAME &&
     1740            r->in.flags & DS_IS_DNS_NAME) {
     1741                return WERR_INVALID_FLAGS;
     1742        }
     1743        if (r->in.flags & DS_RETURN_DNS_NAME &&
     1744            r->in.flags & DS_RETURN_FLAT_NAME) {
     1745                return WERR_INVALID_FLAGS;
     1746        }
     1747        if (r->in.flags & DS_DIRECTORY_SERVICE_REQUIRED &&
     1748            r->in.flags & DS_DIRECTORY_SERVICE_6_REQUIRED) {
     1749                return WERR_INVALID_FLAGS;
     1750        }
     1751
     1752        if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
     1753            r->in.flags &
     1754            (DS_DIRECTORY_SERVICE_REQUIRED |
     1755             DS_DIRECTORY_SERVICE_PREFERRED |
     1756             DS_GC_SERVER_REQUIRED |
     1757             DS_PDC_REQUIRED |
     1758             DS_KDC_REQUIRED)) {
     1759                return WERR_INVALID_FLAGS;
     1760        }
     1761
     1762        if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
     1763            r->in.site_name) {
     1764                return WERR_INVALID_FLAGS;
     1765        }
     1766
     1767        /* Proof server site parameter "site_name" if it was specified */
     1768        server_site_name = samdb_server_site_name(sam_ctx, mem_ctx);
     1769        W_ERROR_HAVE_NO_MEMORY(server_site_name);
     1770        if ((r->in.site_name != NULL) && (strcasecmp(r->in.site_name,
     1771                                                     server_site_name) != 0)) {
    14141772                return WERR_NO_SUCH_DOMAIN;
    14151773        }
    14161774
    1417         domain_dn = ldb_get_default_basedn(sam_ctx);
    1418         if (domain_dn == NULL) {
    1419                 return WERR_DS_UNAVAILABLE;
    1420         }
    1421 
    1422         ret = gendb_search_dn(sam_ctx, mem_ctx,
    1423                               domain_dn, &res, attrs);
    1424         if (ret != 1) {
     1775        guid_str = r->in.domain_guid != NULL ?
     1776                 GUID_string(mem_ctx, r->in.domain_guid) : NULL;
     1777
     1778        status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
     1779                                                 r->in.domain_name,
     1780                                                 r->in.domain_name,
     1781                                                 NULL, guid_str,
     1782                                                 r->in.client_account,
     1783                                                 r->in.mask, addr,
     1784                                                 NETLOGON_NT_VERSION_5EX_WITH_IP,
     1785                                                 lp_ctx, &response, true);
     1786        if (!NT_STATUS_IS_OK(status)) {
     1787                return ntstatus_to_werror(status);
     1788        }
     1789
     1790        if (r->in.flags & DS_RETURN_DNS_NAME) {
     1791                dc_name = response.data.nt5_ex.pdc_dns_name;
     1792                domain_name = response.data.nt5_ex.dns_domain;
     1793        } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
     1794                dc_name = response.data.nt5_ex.pdc_name;
     1795                domain_name = response.data.nt5_ex.domain_name;
     1796        } else {
     1797
     1798                /*
     1799                 * TODO: autodetect what we need to return
     1800                 * based on the given arguments
     1801                 */
     1802                dc_name = response.data.nt5_ex.pdc_name;
     1803                domain_name = response.data.nt5_ex.domain_name;
     1804        }
     1805
     1806        if (!dc_name || !dc_name[0]) {
     1807                return WERR_NO_SUCH_DOMAIN;
     1808        }
     1809
     1810        if (!domain_name || !domain_name[0]) {
     1811                return WERR_NO_SUCH_DOMAIN;
    14251812        }
    14261813
    14271814        info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
    14281815        W_ERROR_HAVE_NO_MEMORY(info);
    1429 
    1430         /* TODO: - return real IP address
    1431          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
    1432          */
    1433         info->dc_unc                    = talloc_asprintf(mem_ctx, "\\\\%s.%s",
    1434                                                           lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx),
    1435                                                           lp_realm(dce_call->conn->dce_ctx->lp_ctx));
     1816        info->dc_unc           = talloc_asprintf(mem_ctx, "\\\\%s", dc_name);
    14361817        W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
    1437         info->dc_address                = talloc_strdup(mem_ctx, "\\\\0.0.0.0");
     1818        info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
     1819                                           response.data.nt5_ex.sockaddr.pdc_ip);
    14381820        W_ERROR_HAVE_NO_MEMORY(info->dc_address);
    1439         info->dc_address_type           = DS_ADDRESS_TYPE_INET;
    1440         info->domain_guid               = samdb_result_guid(res[0], "objectGUID");
    1441         info->domain_name               = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
    1442         info->forest_name               = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
    1443         info->dc_flags                  = DS_DNS_FOREST |
    1444                                           DS_DNS_DOMAIN |
    1445                                           DS_DNS_CONTROLLER |
    1446                                           DS_SERVER_WRITABLE |
    1447                                           DS_SERVER_CLOSEST |
    1448                                           DS_SERVER_TIMESERV |
    1449                                           DS_SERVER_KDC |
    1450                                           DS_SERVER_DS |
    1451                                           DS_SERVER_LDAP |
    1452                                           DS_SERVER_GC |
    1453                                           DS_SERVER_PDC;
    1454         info->dc_site_name      = talloc_strdup(mem_ctx, "Default-First-Site-Name");
    1455         W_ERROR_HAVE_NO_MEMORY(info->dc_site_name);
    1456         info->client_site_name  = talloc_strdup(mem_ctx, "Default-First-Site-Name");
    1457         W_ERROR_HAVE_NO_MEMORY(info->client_site_name);
     1821        info->dc_address_type  = DS_ADDRESS_TYPE_INET; /* TODO: make this dynamic? for ipv6 */
     1822        info->domain_guid      = response.data.nt5_ex.domain_uuid;
     1823        info->domain_name      = domain_name;
     1824        info->forest_name      = response.data.nt5_ex.forest;
     1825        info->dc_flags         = response.data.nt5_ex.server_type;
     1826        info->dc_site_name     = response.data.nt5_ex.server_site;
     1827        info->client_site_name = response.data.nt5_ex.client_site;
    14581828
    14591829        *r->out.info = info;
     
    14621832}
    14631833
    1464 /* 
     1834/*
    14651835  netr_DsRGetDCNameEx
    14661836*/
     
    14871857}
    14881858
    1489 /* 
     1859/*
    14901860  netr_DsRGetDCName
    14911861*/
     
    15031873        r2.in.domain_name = r->in.domain_name;
    15041874        r2.in.domain_guid = r->in.domain_guid;
    1505        
    1506         r2.in.site_name = NULL; /* should fill in from site GUID */
     1875
     1876        r2.in.site_name = NULL; /* this is correct, we should ignore site GUID */
    15071877        r2.in.flags = r->in.flags;
    15081878        r2.out.info = r->out.info;
     
    15121882        return werr;
    15131883}
    1514 /* 
    1515   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN 
     1884/*
     1885  netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
    15161886*/
    15171887static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     
    15321902
    15331903
    1534 /* 
    1535   netr_DsRAddressToSitenamesExW 
     1904/*
     1905  netr_DsRAddressToSitenamesExW
    15361906*/
    15371907static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    15381908                                                   struct netr_DsRAddressToSitenamesExW *r)
    15391909{
     1910        struct ldb_context *sam_ctx;
    15401911        struct netr_DsRAddressToSitenamesExWCtr *ctr;
    1541         int i;
    1542 
    1543         /* we should map the provided IPs to site names, once we have
    1544          * sites support
    1545          */
     1912        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     1913        sa_family_t sin_family;
     1914        struct sockaddr_in *addr;
     1915#ifdef HAVE_IPV6
     1916        struct sockaddr_in6 *addr6;
     1917        char addr_str[INET6_ADDRSTRLEN];
     1918#else
     1919        char addr_str[INET_ADDRSTRLEN];
     1920#endif
     1921        char *subnet_name;
     1922        const char *res;
     1923        uint32_t i;
     1924
     1925        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
     1926                                dce_call->conn->auth_state.session_info, 0);
     1927        if (sam_ctx == NULL) {
     1928                return WERR_DS_UNAVAILABLE;
     1929        }
     1930
    15461931        ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
    15471932        W_ERROR_HAVE_NO_MEMORY(ctr);
     
    15561941
    15571942        for (i=0; i<ctr->count; i++) {
    1558                 ctr->sitename[i].string   = "Default-First-Site-Name";
     1943                ctr->sitename[i].string = NULL;
    15591944                ctr->subnetname[i].string = NULL;
     1945
     1946                if (r->in.addresses[i].size < sizeof(sa_family_t)) {
     1947                        continue;
     1948                }
     1949                /* The first two byte of the buffer are reserved for the
     1950                 * "sin_family" but for now only the first one is used. */
     1951                sin_family = r->in.addresses[i].buffer[0];
     1952
     1953                switch (sin_family) {
     1954                case AF_INET:
     1955                        if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
     1956                                continue;
     1957                        }
     1958                        addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
     1959                        res = inet_ntop(AF_INET, &addr->sin_addr,
     1960                                        addr_str, sizeof(addr_str));
     1961                        break;
     1962#ifdef HAVE_IPV6
     1963                case AF_INET6:
     1964                        if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
     1965                                continue;
     1966                        }
     1967                        addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
     1968                        res = inet_ntop(AF_INET6, &addr6->sin6_addr,
     1969                                        addr_str, sizeof(addr_str));
     1970                        break;
     1971#endif
     1972                default:
     1973                        continue;
     1974                }
     1975
     1976                if (res == NULL) {
     1977                        continue;
     1978                }
     1979
     1980                ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
     1981                                                                   mem_ctx,
     1982                                                                   addr_str,
     1983                                                                   &subnet_name);
     1984                W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
     1985                ctr->subnetname[i].string = subnet_name;
    15601986        }
    15611987
     
    15641990
    15651991
    1566 /*
     1992/*
     1993  netr_DsRAddressToSitenamesW
     1994*/
     1995static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     1996                       struct netr_DsRAddressToSitenamesW *r)
     1997{
     1998        struct netr_DsRAddressToSitenamesExW r2;
     1999        struct netr_DsRAddressToSitenamesWCtr *ctr;
     2000        uint32_t i;
     2001        WERROR werr;
     2002
     2003        ZERO_STRUCT(r2);
     2004
     2005        r2.in.server_name = r->in.server_name;
     2006        r2.in.count = r->in.count;
     2007        r2.in.addresses = r->in.addresses;
     2008
     2009        r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
     2010        W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
     2011
     2012        ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
     2013        W_ERROR_HAVE_NO_MEMORY(ctr);
     2014
     2015        *r->out.ctr = ctr;
     2016
     2017        ctr->count = r->in.count;
     2018        ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
     2019        W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
     2020
     2021        werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
     2022
     2023        for (i=0; i<ctr->count; i++) {
     2024                ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
     2025        }
     2026
     2027        return werr;
     2028}
     2029
     2030
     2031/*
    15672032  netr_DsrGetDcSiteCoverageW
    15682033*/
     
    15702035                       struct netr_DsrGetDcSiteCoverageW *r)
    15712036{
    1572         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1573 }
    1574 
    1575 
    1576 /*
    1577   netr_DsrEnumerateDomainTrusts
    1578 */
    1579 static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1580                                               struct netr_DsrEnumerateDomainTrusts *r)
     2037        struct ldb_context *sam_ctx;
     2038        struct DcSitesCtr *ctr;
     2039        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     2040
     2041        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
     2042                                dce_call->conn->auth_state.session_info, 0);
     2043        if (sam_ctx == NULL) {
     2044                return WERR_DS_UNAVAILABLE;
     2045        }
     2046
     2047        ctr = talloc(mem_ctx, struct DcSitesCtr);
     2048        W_ERROR_HAVE_NO_MEMORY(ctr);
     2049
     2050        *r->out.ctr = ctr;
     2051
     2052        /* For now only return our default site */
     2053        ctr->num_sites = 1;
     2054        ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
     2055        W_ERROR_HAVE_NO_MEMORY(ctr->sites);
     2056        ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
     2057        W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
     2058
     2059        return WERR_OK;
     2060}
     2061
     2062
     2063#define GET_CHECK_STR(dest, mem, msg, attr) \
     2064do {\
     2065        const char *s; \
     2066        s = ldb_msg_find_attr_as_string(msg, attr, NULL); \
     2067        if (!s) { \
     2068                DEBUG(0, ("DB Error, TustedDomain entry (%s) " \
     2069                          "without flatname\n", \
     2070                          ldb_dn_get_linearized(msg->dn))); \
     2071                continue; \
     2072        } \
     2073        dest = talloc_strdup(mem, s); \
     2074        W_ERROR_HAVE_NO_MEMORY(dest); \
     2075} while(0)
     2076
     2077
     2078static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
     2079                                         struct ldb_context *sam_ctx,
     2080                                         struct netr_DomainTrustList *trusts,
     2081                                         uint32_t trust_flags)
     2082{
     2083        struct ldb_dn *system_dn;
     2084        struct ldb_message **dom_res = NULL;
     2085        const char *trust_attrs[] = { "flatname", "trustPartner",
     2086                                      "securityIdentifier", "trustDirection",
     2087                                      "trustType", "trustAttributes", NULL };
     2088        uint32_t n;
     2089        int i;
     2090        int ret;
     2091
     2092        if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
     2093                             NETR_TRUST_FLAG_OUTBOUND))) {
     2094                return WERR_INVALID_FLAGS;
     2095        }
     2096
     2097        system_dn = samdb_search_dn(sam_ctx, mem_ctx,
     2098                                    ldb_get_default_basedn(sam_ctx),
     2099                                    "(&(objectClass=container)(cn=System))");
     2100        if (!system_dn) {
     2101                return WERR_GENERAL_FAILURE;
     2102        }
     2103
     2104        ret = gendb_search(sam_ctx, mem_ctx, system_dn,
     2105                           &dom_res, trust_attrs,
     2106                           "(objectclass=trustedDomain)");
     2107
     2108        for (i = 0; i < ret; i++) {
     2109                unsigned int trust_dir;
     2110                uint32_t flags = 0;
     2111
     2112                trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
     2113                                                      "trustDirection", 0);
     2114
     2115                if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
     2116                        flags |= NETR_TRUST_FLAG_INBOUND;
     2117                }
     2118                if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
     2119                        flags |= NETR_TRUST_FLAG_OUTBOUND;
     2120                }
     2121
     2122                if (!(flags & trust_flags)) {
     2123                        /* this trust direction was not requested */
     2124                        continue;
     2125                }
     2126
     2127                n = trusts->count;
     2128                trusts->array = talloc_realloc(trusts, trusts->array,
     2129                                               struct netr_DomainTrust,
     2130                                               n + 1);
     2131                W_ERROR_HAVE_NO_MEMORY(trusts->array);
     2132
     2133                GET_CHECK_STR(trusts->array[n].netbios_name, trusts,
     2134                              dom_res[i], "flatname");
     2135                GET_CHECK_STR(trusts->array[n].dns_name, trusts,
     2136                              dom_res[i], "trustPartner");
     2137
     2138                trusts->array[n].trust_flags = flags;
     2139                if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
     2140                    !(flags & NETR_TRUST_FLAG_TREEROOT)) {
     2141                        /* TODO: find if we have parent in the list */
     2142                        trusts->array[n].parent_index = 0;
     2143                }
     2144
     2145                trusts->array[n].trust_type =
     2146                                ldb_msg_find_attr_as_uint(dom_res[i],
     2147                                                  "trustType", 0);
     2148                trusts->array[n].trust_attributes =
     2149                                ldb_msg_find_attr_as_uint(dom_res[i],
     2150                                                  "trustAttributes", 0);
     2151
     2152                if ((trusts->array[n].trust_type == NETR_TRUST_TYPE_MIT) ||
     2153                    (trusts->array[n].trust_type == NETR_TRUST_TYPE_DCE)) {
     2154                        struct dom_sid zero_sid;
     2155                        ZERO_STRUCT(zero_sid);
     2156                        trusts->array[n].sid =
     2157                                dom_sid_dup(trusts, &zero_sid);
     2158                } else {
     2159                        trusts->array[n].sid =
     2160                                samdb_result_dom_sid(trusts, dom_res[i],
     2161                                                     "securityIdentifier");
     2162                }
     2163                trusts->array[n].guid = GUID_zero();
     2164
     2165                trusts->count = n + 1;
     2166        }
     2167
     2168        talloc_free(dom_res);
     2169        return WERR_OK;
     2170}
     2171
     2172/*
     2173  netr_DsrEnumerateDomainTrusts
     2174*/
     2175static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
     2176                                                   TALLOC_CTX *mem_ctx,
     2177                                                   struct netr_DsrEnumerateDomainTrusts *r)
    15812178{
    15822179        struct netr_DomainTrustList *trusts;
     
    15852182        struct ldb_message **dom_res;
    15862183        const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
    1587 
    1588         ZERO_STRUCT(r->out);
    1589 
    1590         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info);
     2184        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     2185        const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
     2186        const char *p;
     2187        WERROR werr;
     2188
     2189        if (r->in.trust_flags & 0xFFFFFE00) {
     2190                return WERR_INVALID_FLAGS;
     2191        }
     2192
     2193        /* TODO: turn to hard check once we are sure this is 100% correct */
     2194        if (!r->in.server_name) {
     2195                DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
     2196                          "But received NULL!\n", dnsdomain));
     2197        } else {
     2198                p = strchr(r->in.server_name, '.');
     2199                if (!p) {
     2200                        DEBUG(3, ("Invalid domain! Expected name in domain "
     2201                                  "[%s]. But received [%s]!\n",
     2202                                  dnsdomain, r->in.server_name));
     2203                        p = r->in.server_name;
     2204                } else {
     2205                        p++;
     2206                }
     2207                if (strcasecmp(p, dnsdomain)) {
     2208                        DEBUG(3, ("Invalid domain! Expected name in domain "
     2209                                  "[%s]. But received [%s]!\n",
     2210                                  dnsdomain, r->in.server_name));
     2211                }
     2212        }
     2213
     2214        trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
     2215        W_ERROR_HAVE_NO_MEMORY(trusts);
     2216
     2217        trusts->count = 0;
     2218        r->out.trusts = trusts;
     2219
     2220        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
     2221                                dce_call->conn->auth_state.session_info, 0);
    15912222        if (sam_ctx == NULL) {
    15922223                return WERR_GENERAL_FAILURE;
    15932224        }
    15942225
    1595         ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
    1596                               &dom_res, dom_attrs);
    1597         if (ret == -1) {
    1598                 return WERR_GENERAL_FAILURE;           
    1599         }
     2226        if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
     2227            (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
     2228
     2229                werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
     2230                                                  trusts, r->in.trust_flags);
     2231                W_ERROR_NOT_OK_RETURN(werr);
     2232        }
     2233
     2234        /* NOTE: we currently are always the root of the forest */
     2235        if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
     2236                uint32_t n = trusts->count;
     2237
     2238                ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
     2239                                      &dom_res, dom_attrs);
     2240                if (ret != 1) {
     2241                        return WERR_GENERAL_FAILURE;
     2242                }
     2243
     2244                trusts->count = n + 1;
     2245                trusts->array = talloc_realloc(trusts, trusts->array,
     2246                                               struct netr_DomainTrust,
     2247                                               trusts->count);
     2248                W_ERROR_HAVE_NO_MEMORY(trusts->array);
     2249
     2250                trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
     2251                trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
     2252                trusts->array[n].trust_flags =
     2253                        NETR_TRUST_FLAG_NATIVE |
     2254                        NETR_TRUST_FLAG_TREEROOT |
     2255                        NETR_TRUST_FLAG_IN_FOREST |
     2256                        NETR_TRUST_FLAG_PRIMARY;
     2257                /* we are always the root domain for now */
     2258                trusts->array[n].parent_index = 0;
     2259                trusts->array[n].trust_type = NETR_TRUST_TYPE_UPLEVEL;
     2260                trusts->array[n].trust_attributes = 0;
     2261                trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
     2262                                                            dom_res[0],
     2263                                                            "objectSid");
     2264                trusts->array[n].guid = samdb_result_guid(dom_res[0],
     2265                                                          "objectGUID");
     2266                talloc_free(dom_res);
     2267        }
     2268
     2269        return WERR_OK;
     2270}
     2271
     2272
     2273/*
     2274  netr_DsrDeregisterDNSHostRecords
     2275*/
     2276static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     2277                       struct netr_DsrDeregisterDNSHostRecords *r)
     2278{
     2279        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     2280}
     2281
     2282
     2283/*
     2284  netr_ServerTrustPasswordsGet
     2285*/
     2286static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     2287                       struct netr_ServerTrustPasswordsGet *r)
     2288{
     2289        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     2290}
     2291
     2292
     2293static WERROR fill_forest_trust_array(TALLOC_CTX *mem_ctx,
     2294                                      struct ldb_context *sam_ctx,
     2295                                      struct loadparm_context *lp_ctx,
     2296                                      struct lsa_ForestTrustInformation *info)
     2297{
     2298        struct lsa_ForestTrustDomainInfo *domain_info;
     2299        struct lsa_ForestTrustRecord *e;
     2300        struct ldb_message **dom_res;
     2301        const char * const dom_attrs[] = { "objectSid", NULL };
     2302        int ret;
     2303
     2304        /* we need to provide 2 entries:
     2305         * 1. the Root Forest name
     2306         * 2. the Domain Information
     2307         */
     2308
     2309        info->count = 2;
     2310        info->entries = talloc_array(info, struct lsa_ForestTrustRecord *, 2);
     2311        W_ERROR_HAVE_NO_MEMORY(info->entries);
     2312
     2313        /* Forest root info */
     2314        e = talloc(info, struct lsa_ForestTrustRecord);
     2315        W_ERROR_HAVE_NO_MEMORY(e);
     2316
     2317        e->flags = 0;
     2318        e->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
     2319        e->time = 0; /* so far always 0 in trces. */
     2320        e->forest_trust_data.top_level_name.string = samdb_forest_name(sam_ctx,
     2321                                                                       mem_ctx);
     2322        W_ERROR_HAVE_NO_MEMORY(e->forest_trust_data.top_level_name.string);
     2323
     2324        info->entries[0] = e;
     2325
     2326        /* Domain info */
     2327        e = talloc(info, struct lsa_ForestTrustRecord);
     2328        W_ERROR_HAVE_NO_MEMORY(e);
     2329
     2330        /* get our own domain info */
     2331        ret = gendb_search_dn(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs);
    16002332        if (ret != 1) {
    16012333                return WERR_GENERAL_FAILURE;
    16022334        }
    16032335
    1604         trusts = talloc(mem_ctx, struct netr_DomainTrustList);
    1605         W_ERROR_HAVE_NO_MEMORY(trusts);
    1606 
    1607         trusts->array = talloc_array(trusts, struct netr_DomainTrust, ret);
    1608         W_ERROR_HAVE_NO_MEMORY(trusts->array);
    1609 
    1610         trusts->count = 1; /* ?? */
    1611 
    1612         r->out.trusts = trusts;
    1613 
    1614         /* TODO: add filtering by trust_flags, and correct trust_type
    1615            and attributes */
    1616         trusts->array[0].netbios_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx);
    1617         trusts->array[0].dns_name     = lp_realm(dce_call->conn->dce_ctx->lp_ctx);
    1618         trusts->array[0].trust_flags =
    1619                 NETR_TRUST_FLAG_TREEROOT |
    1620                 NETR_TRUST_FLAG_IN_FOREST |
    1621                 NETR_TRUST_FLAG_PRIMARY;
    1622         trusts->array[0].parent_index = 0;
    1623         trusts->array[0].trust_type = 2;
    1624         trusts->array[0].trust_attributes = 0;
    1625         trusts->array[0].sid  = samdb_result_dom_sid(mem_ctx, dom_res[0], "objectSid");
    1626         trusts->array[0].guid = samdb_result_guid(dom_res[0], "objectGUID");
     2336        /* TODO: check if disabled and set flags accordingly */
     2337        e->flags = 0;
     2338        e->type = LSA_FOREST_TRUST_DOMAIN_INFO;
     2339        e->time = 0; /* so far always 0 in traces. */
     2340
     2341        domain_info = &e->forest_trust_data.domain_info;
     2342        domain_info->domain_sid = samdb_result_dom_sid(info, dom_res[0],
     2343                                                       "objectSid");
     2344        domain_info->dns_domain_name.string = lpcfg_dnsdomain(lp_ctx);
     2345        domain_info->netbios_domain_name.string = lpcfg_workgroup(lp_ctx);
     2346
     2347        info->entries[1] = e;
     2348
     2349        talloc_free(dom_res);
    16272350
    16282351        return WERR_OK;
    16292352}
    16302353
    1631 
    1632 /*
    1633   netr_DsrDeregisterDNSHostRecords
    1634 */
    1635 static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1636                        struct netr_DsrDeregisterDNSHostRecords *r)
    1637 {
    1638         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1639 }
    1640 
    1641 
    1642 /*
    1643   netr_ServerTrustPasswordsGet
    1644 */
    1645 static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1646                        struct netr_ServerTrustPasswordsGet *r)
    1647 {
    1648         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1649 }
    1650 
    1651 
    1652 /*
    1653   netr_DsRGetForestTrustInformation
    1654 */
    1655 static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1656                        struct netr_DsRGetForestTrustInformation *r)
    1657 {
    1658         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     2354/*
     2355  netr_DsRGetForestTrustInformation
     2356*/
     2357static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
     2358                                                       TALLOC_CTX *mem_ctx,
     2359                                                       struct netr_DsRGetForestTrustInformation *r)
     2360{
     2361        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     2362        struct lsa_ForestTrustInformation *info, **info_ptr;
     2363        struct ldb_context *sam_ctx;
     2364        WERROR werr;
     2365
     2366        if (r->in.flags & 0xFFFFFFFE) {
     2367                return WERR_INVALID_FLAGS;
     2368        }
     2369
     2370        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
     2371                                dce_call->conn->auth_state.session_info, 0);
     2372        if (sam_ctx == NULL) {
     2373                return WERR_GENERAL_FAILURE;
     2374        }
     2375
     2376        if (r->in.flags & DS_GFTI_UPDATE_TDO) {
     2377                if (!samdb_is_pdc(sam_ctx)) {
     2378                        return WERR_NERR_NOTPRIMARY;
     2379                }
     2380
     2381                if (r->in.trusted_domain_name == NULL) {
     2382                        return WERR_INVALID_FLAGS;
     2383                }
     2384
     2385                /* TODO: establish an schannel connection with
     2386                 * r->in.trusted_domain_name and perform a
     2387                 * netr_GetForestTrustInformation call against it */
     2388
     2389                /* for now return not implementd */
     2390                return WERR_CALL_NOT_IMPLEMENTED;
     2391        }
     2392
     2393        /* TODO: check r->in.server_name is our name */
     2394
     2395        info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
     2396        W_ERROR_HAVE_NO_MEMORY(info_ptr);
     2397
     2398        info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
     2399        W_ERROR_HAVE_NO_MEMORY(info);
     2400
     2401        werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
     2402        W_ERROR_NOT_OK_RETURN(werr);
     2403
     2404        *info_ptr = info;
     2405        r->out.forest_trust_info = info_ptr;
     2406
     2407        return WERR_OK;
    16592408}
    16602409
     
    16632412  netr_GetForestTrustInformation
    16642413*/
    1665 static WERROR dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1666                        struct netr_GetForestTrustInformation *r)
    1667 {
    1668         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     2414static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
     2415                                                      TALLOC_CTX *mem_ctx,
     2416                                                      struct netr_GetForestTrustInformation *r)
     2417{
     2418        struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     2419        struct netlogon_creds_CredentialState *creds;
     2420        struct lsa_ForestTrustInformation *info, **info_ptr;
     2421        struct ldb_context *sam_ctx;
     2422        NTSTATUS status;
     2423        WERROR werr;
     2424
     2425        status = dcesrv_netr_creds_server_step_check(dce_call,
     2426                                                     mem_ctx,
     2427                                                     r->in.computer_name,
     2428                                                     r->in.credential,
     2429                                                     r->out.return_authenticator,
     2430                                                     &creds);
     2431        if (!NT_STATUS_IS_OK(status)) {
     2432                return status;
     2433        }
     2434
     2435        if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
     2436            (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
     2437                return NT_STATUS_NOT_IMPLEMENTED;
     2438        }
     2439
     2440        sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, lp_ctx,
     2441                                dce_call->conn->auth_state.session_info, 0);
     2442        if (sam_ctx == NULL) {
     2443                return NT_STATUS_UNSUCCESSFUL;
     2444        }
     2445
     2446        /* TODO: check r->in.server_name is our name */
     2447
     2448        info_ptr = talloc(mem_ctx, struct lsa_ForestTrustInformation *);
     2449        if (!info_ptr) {
     2450                return NT_STATUS_NO_MEMORY;
     2451        }
     2452        info = talloc_zero(info_ptr, struct lsa_ForestTrustInformation);
     2453        if (!info) {
     2454                return NT_STATUS_NO_MEMORY;
     2455        }
     2456
     2457        werr = fill_forest_trust_array(mem_ctx, sam_ctx, lp_ctx, info);
     2458        if (!W_ERROR_IS_OK(werr)) {
     2459                return werror_to_ntstatus(werr);
     2460        }
     2461
     2462        *info_ptr = info;
     2463        r->out.forest_trust_info = info_ptr;
     2464
     2465        return NT_STATUS_OK;
    16692466}
    16702467
     
    16792476}
    16802477
     2478/*
     2479  netr_Unused47
     2480*/
     2481static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     2482                                     struct netr_Unused47 *r)
     2483{
     2484        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     2485}
     2486
     2487
     2488struct netr_dnsupdate_RODC_state {
     2489        struct dcesrv_call_state *dce_call;
     2490        struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
     2491        struct dnsupdate_RODC *r2;
     2492};
     2493
     2494/*
     2495  called when the forwarded RODC dns update request is finished
     2496 */
     2497static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
     2498{
     2499        struct netr_dnsupdate_RODC_state *st =
     2500                tevent_req_callback_data(subreq,
     2501                                         struct netr_dnsupdate_RODC_state);
     2502        NTSTATUS status;
     2503
     2504        status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
     2505        TALLOC_FREE(subreq);
     2506        if (!NT_STATUS_IS_OK(status)) {
     2507                DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
     2508                st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
     2509        }
     2510
     2511        st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
     2512
     2513        status = dcesrv_reply(st->dce_call);
     2514        if (!NT_STATUS_IS_OK(status)) {
     2515                DEBUG(0,(__location__ ": dcesrv_reply() failed - %s\n", nt_errstr(status)));
     2516        }
     2517}
     2518
     2519/*
     2520  netr_DsrUpdateReadOnlyServerDnsRecords
     2521*/
     2522static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
     2523                                                              TALLOC_CTX *mem_ctx,
     2524                                                              struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
     2525{
     2526        struct netlogon_creds_CredentialState *creds;
     2527        NTSTATUS nt_status;
     2528        struct dcerpc_binding_handle *binding_handle;
     2529        struct netr_dnsupdate_RODC_state *st;
     2530        struct tevent_req *subreq;
     2531
     2532        nt_status = dcesrv_netr_creds_server_step_check(dce_call,
     2533                                                        mem_ctx,
     2534                                                        r->in.computer_name,
     2535                                                        r->in.credential,
     2536                                                        r->out.return_authenticator,
     2537                                                        &creds);
     2538        NT_STATUS_NOT_OK_RETURN(nt_status);
     2539
     2540        if (creds->secure_channel_type != SEC_CHAN_RODC) {
     2541                return NT_STATUS_ACCESS_DENIED;
     2542        }
     2543
     2544        st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
     2545        NT_STATUS_HAVE_NO_MEMORY(st);
     2546
     2547        st->dce_call = dce_call;
     2548        st->r = r;
     2549        st->r2 = talloc_zero(st, struct dnsupdate_RODC);
     2550        NT_STATUS_HAVE_NO_MEMORY(st->r2);
     2551
     2552        st->r2->in.dom_sid = creds->sid;
     2553        st->r2->in.site_name = r->in.site_name;
     2554        st->r2->in.dns_ttl = r->in.dns_ttl;
     2555        st->r2->in.dns_names = r->in.dns_names;
     2556        st->r2->out.dns_names = r->out.dns_names;
     2557
     2558        binding_handle = irpc_binding_handle_by_name(st, dce_call->msg_ctx,
     2559                                                     "dnsupdate", &ndr_table_irpc);
     2560        if (binding_handle == NULL) {
     2561                DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
     2562                dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
     2563                return NT_STATUS_INTERNAL_DB_CORRUPTION;
     2564        }
     2565
     2566        /* forward the call */
     2567        subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
     2568                                              binding_handle, st->r2);
     2569        NT_STATUS_HAVE_NO_MEMORY(subreq);
     2570
     2571        dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
     2572
     2573        /* setup the callback */
     2574        tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
     2575
     2576        return NT_STATUS_OK;
     2577}
     2578
    16812579
    16822580/* include the generated boilerplate */
  • trunk/server/source4/rpc_server/remote/dcesrv_remote.c

    r414 r745  
    44
    55   Copyright (C) Stefan (metze) Metzmacher 2004
    6    
     6   Copyright (C) Julien Kerihuel 2008-2009
     7   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2010
     8
    79   This program is free software; you can redistribute it and/or modify
    810   it under the terms of the GNU General Public License as published by
     
    2022
    2123#include "includes.h"
     24#include <tevent.h>
    2225#include "rpc_server/dcerpc_server.h"
    2326#include "auth/auth.h"
     
    3639}
    3740
    38 static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
     41static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
    3942{
    4043        NTSTATUS status;
    4144        const struct ndr_interface_table *table;
    4245        struct dcesrv_remote_private *priv;
    43         const char *binding = lp_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "binding");
     46        const char *binding = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "binding");
    4447        const char *user, *pass, *domain;
    4548        struct cli_credentials *credentials;
     49        bool must_free_credentials = true;
    4650        bool machine_account;
    47 
    48         machine_account = lp_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "use_machine_account", false);
     51        struct dcerpc_binding           *b;
     52        struct composite_context        *pipe_conn_req;
     53
     54        machine_account = lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "use_machine_account", false);
    4955
    5056        priv = talloc(dce_call->conn, struct dcesrv_remote_private);
     
    6167        }
    6268
    63         user = lp_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "user");
    64         pass = lp_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "password");
    65         domain = lp_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dceprc_remote", "domain");
     69        user = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "user");
     70        pass = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dcerpc_remote", "password");
     71        domain = lpcfg_parm_string(dce_call->conn->dce_ctx->lp_ctx, NULL, "dceprc_remote", "domain");
    6672
    6773        table = ndr_table_by_uuid(&iface->syntax_id.uuid); /* FIXME: What about if_version ? */
     
    97103                DEBUG(5, ("dcerpc_remote: RPC Proxy: Using delegated credentials\n"));
    98104                credentials = dce_call->conn->auth_state.session_info->credentials;
     105                must_free_credentials = false;
    99106        } else {
    100107                DEBUG(1,("dcerpc_remote: RPC Proxy: You must supply binding, user and password or have delegated credentials\n"));
     
    102109        }
    103110
    104         status = dcerpc_pipe_connect(priv,
    105                                      &(priv->c_pipe), binding, table,
    106                                      credentials, dce_call->event_ctx,
    107                                      dce_call->conn->dce_ctx->lp_ctx);
    108 
    109         talloc_free(credentials);
     111        /* parse binding string to the structure */
     112        status = dcerpc_parse_binding(dce_call->context, binding, &b);
     113        if (!NT_STATUS_IS_OK(status)) {
     114                DEBUG(0, ("Failed to parse dcerpc binding '%s'\n", binding));
     115                return status;
     116        }
     117       
     118        DEBUG(3, ("Using binding %s\n", dcerpc_binding_string(dce_call->context, b)));
     119       
     120        /* If we already have a remote association group ID, then use that */
     121        if (dce_call->context->assoc_group->proxied_id != 0) {
     122                b->assoc_group_id = dce_call->context->assoc_group->proxied_id;
     123        }
     124
     125        b->object.if_version = if_version;
     126
     127        pipe_conn_req = dcerpc_pipe_connect_b_send(dce_call->context, b, table,
     128                                                   credentials, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx);
     129        status = dcerpc_pipe_connect_b_recv(pipe_conn_req, dce_call->context, &(priv->c_pipe));
     130       
     131        if (must_free_credentials) {
     132                talloc_free(credentials);
     133        }
     134
    110135        if (!NT_STATUS_IS_OK(status)) {
    111136                return status;
    112137        }
    113138
     139        if (dce_call->context->assoc_group->proxied_id == 0) {
     140                dce_call->context->assoc_group->proxied_id = priv->c_pipe->assoc_group_id;
     141        }
     142
     143        if (!NT_STATUS_IS_OK(status)) {
     144                return status;
     145        }
     146
    114147        return NT_STATUS_OK;   
    115 }
    116 
    117 static void remote_op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
    118 {
    119         struct dcesrv_remote_private *priv = (struct dcesrv_remote_private *)context->private_data;
    120 
    121         talloc_free(priv->c_pipe);
    122 
    123         return;
    124148}
    125149
     
    155179}
    156180
     181static void remote_op_dispatch_done(struct tevent_req *subreq);
     182
    157183static NTSTATUS remote_op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
    158184{
    159         struct dcesrv_remote_private *priv = dce_call->context->private_data;
     185        struct dcesrv_remote_private *priv = talloc_get_type_abort(dce_call->context->private_data,
     186                                                                   struct dcesrv_remote_private);
    160187        uint16_t opnum = dce_call->pkt.u.request.opnum;
    161188        const struct ndr_interface_table *table = dce_call->context->iface->private_data;
    162189        const struct ndr_interface_call *call;
    163190        const char *name;
     191        struct tevent_req *subreq;
    164192
    165193        name = table->calls[opnum].name;
     
    173201
    174202        /* we didn't use the return code of this function as we only check the last_fault_code */
    175         dcerpc_ndr_request(priv->c_pipe, NULL, table, opnum, mem_ctx,r);
     203        subreq = dcerpc_binding_handle_call_send(dce_call, dce_call->event_ctx,
     204                                                 priv->c_pipe->binding_handle,
     205                                                 NULL, table,
     206                                                 opnum, mem_ctx, r);
     207        if (subreq == NULL) {
     208                DEBUG(0,("dcesrv_remote: call[%s] dcerpc_binding_handle_call_send() failed!\n", name));
     209                return NT_STATUS_NO_MEMORY;
     210        }
     211        tevent_req_set_callback(subreq, remote_op_dispatch_done, dce_call);
     212
     213        dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
     214        return NT_STATUS_OK;
     215}
     216
     217static void remote_op_dispatch_done(struct tevent_req *subreq)
     218{
     219        struct dcesrv_call_state *dce_call = tevent_req_callback_data(subreq,
     220                                             struct dcesrv_call_state);
     221        struct dcesrv_remote_private *priv = talloc_get_type_abort(dce_call->context->private_data,
     222                                                                   struct dcesrv_remote_private);
     223        uint16_t opnum = dce_call->pkt.u.request.opnum;
     224        const struct ndr_interface_table *table = dce_call->context->iface->private_data;
     225        const struct ndr_interface_call *call;
     226        const char *name;
     227        NTSTATUS status;
     228
     229        name = table->calls[opnum].name;
     230        call = &table->calls[opnum];
     231
     232        /* we didn't use the return code of this function as we only check the last_fault_code */
     233        status = dcerpc_binding_handle_call_recv(subreq);
     234        TALLOC_FREE(subreq);
    176235
    177236        dce_call->fault_code = priv->c_pipe->last_fault_code;
    178237        if (dce_call->fault_code != 0) {
    179                 DEBUG(0,("dcesrv_remote: call[%s] failed with: %s!\n",name, dcerpc_errstr(mem_ctx, dce_call->fault_code)));
    180                 return NT_STATUS_NET_WRITE_FAULT;
    181         }
    182 
    183         if ((dce_call->fault_code == 0) &&
     238                DEBUG(0,("dcesrv_remote: call[%s] failed with: %s!\n",
     239                        name, dcerpc_errstr(dce_call, dce_call->fault_code)));
     240                goto reply;
     241        }
     242
     243        if (NT_STATUS_IS_OK(status) &&
    184244            (priv->c_pipe->conn->flags & DCERPC_DEBUG_PRINT_OUT)) {
    185                 ndr_print_function_debug(call->ndr_print, name, NDR_OUT, r);           
    186         }
    187 
    188         return NT_STATUS_OK;
     245                ndr_print_function_debug(call->ndr_print, name, NDR_OUT, dce_call->r);
     246        }
     247
     248reply:
     249        status = dcesrv_reply(dce_call);
     250        if (!NT_STATUS_IS_OK(status)) {
     251                DEBUG(0,("dcesrv_remote: call[%s]: dcesrv_reply() failed - %s\n",
     252                        name, nt_errstr(status)));
     253        }
    189254}
    190255
     
    207272static NTSTATUS remote_register_one_iface(struct dcesrv_context *dce_ctx, const struct dcesrv_interface *iface)
    208273{
    209         int i;
     274        unsigned int i;
    210275        const struct ndr_interface_table *table = iface->private_data;
    211276
     
    226291static NTSTATUS remote_op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
    227292{
    228         int i;
    229         const char **ifaces = (const char **)str_list_make(dce_ctx, lp_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_remote", "interfaces"),NULL);
     293        unsigned int i;
     294        const char **ifaces = (const char **)str_list_make(dce_ctx, lpcfg_parm_string(dce_ctx->lp_ctx, NULL, "dcerpc_remote", "interfaces"),NULL);
    230295
    231296        if (!ifaces) {
     
    262327       
    263328        iface->bind = remote_op_bind;
    264         iface->unbind = remote_op_unbind;
     329        iface->unbind = NULL;
    265330
    266331        iface->ndr_pull = remote_op_ndr_pull;
  • 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}
  • trunk/server/source4/rpc_server/service_rpc.c

    r414 r745  
    2828#include "rpc_server/dcerpc_server.h"
    2929#include "rpc_server/dcerpc_server_proto.h"
    30 #include "smbd/service.h"
    3130#include "system/filesys.h"
    32 #include "lib/socket/socket.h"
    3331#include "lib/messaging/irpc.h"
    3432#include "system/network.h"
     
    4240#include "smbd/process_model.h"
    4341
    44 struct dcesrv_socket_context {
    45         const struct dcesrv_endpoint *endpoint;
    46         struct dcesrv_context *dcesrv_ctx;
    47 };
    48 
    49 static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
    50 {
    51         struct stream_connection *srv_conn;
    52         srv_conn = talloc_get_type(dce_conn->transport.private_data,
    53                                    struct stream_connection);
    54 
    55         stream_terminate_connection(srv_conn, reason);
    56 }
    57 
    58 static void dcesrv_sock_reply_done(struct tevent_req *subreq);
    59 
    60 struct dcesrv_sock_reply_state {
    61         struct dcesrv_connection *dce_conn;
    62         struct dcesrv_call_state *call;
    63         struct iovec iov;
    64 };
    65 
    66 static void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
    67 {
    68         struct dcesrv_call_state *call;
    69 
    70         call = dce_conn->call_list;
    71         if (!call || !call->replies) {
    72                 return;
    73         }
    74 
    75         while (call->replies) {
    76                 struct data_blob_list_item *rep = call->replies;
    77                 struct dcesrv_sock_reply_state *substate;
    78                 struct tevent_req *subreq;
    79 
    80                 substate = talloc(call, struct dcesrv_sock_reply_state);
    81                 if (!substate) {
    82                         dcesrv_terminate_connection(dce_conn, "no memory");
    83                         return;
    84                 }
    85 
    86                 substate->dce_conn = dce_conn;
    87                 substate->call = NULL;
    88 
    89                 DLIST_REMOVE(call->replies, rep);
    90 
    91                 if (call->replies == NULL) {
    92                         substate->call = call;
    93                 }
    94 
    95                 substate->iov.iov_base = rep->blob.data;
    96                 substate->iov.iov_len = rep->blob.length;
    97 
    98                 subreq = tstream_writev_queue_send(substate,
    99                                                    dce_conn->event_ctx,
    100                                                    dce_conn->stream,
    101                                                    dce_conn->send_queue,
    102                                                    &substate->iov, 1);
    103                 if (!subreq) {
    104                         dcesrv_terminate_connection(dce_conn, "no memory");
    105                         return;
    106                 }
    107                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
    108                                         substate);
    109         }
    110 
    111         DLIST_REMOVE(call->conn->call_list, call);
    112         call->list = DCESRV_LIST_NONE;
    113 }
    114 
    115 static void dcesrv_sock_reply_done(struct tevent_req *subreq)
    116 {
    117         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
    118                                                 struct dcesrv_sock_reply_state);
    119         int ret;
    120         int sys_errno;
    121         NTSTATUS status;
    122         struct dcesrv_call_state *call = substate->call;
    123 
    124         ret = tstream_writev_queue_recv(subreq, &sys_errno);
    125         TALLOC_FREE(subreq);
    126         if (ret == -1) {
    127                 status = map_nt_error_from_unix(sys_errno);
    128                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
    129                 return;
    130         }
    131 
    132         talloc_free(substate);
    133         if (call) {
    134                 talloc_free(call);
    135         }
    136 }
    137 
    138 static struct socket_address *dcesrv_sock_get_my_addr(struct dcesrv_connection *dcesrv_conn, TALLOC_CTX *mem_ctx)
    139 {
    140         struct stream_connection *srv_conn;
    141         srv_conn = talloc_get_type(dcesrv_conn->transport.private_data,
    142                                    struct stream_connection);
    143 
    144         return socket_get_my_addr(srv_conn->socket, mem_ctx);
    145 }
    146 
    147 static struct socket_address *dcesrv_sock_get_peer_addr(struct dcesrv_connection *dcesrv_conn, TALLOC_CTX *mem_ctx)
    148 {
    149         struct stream_connection *srv_conn;
    150         srv_conn = talloc_get_type(dcesrv_conn->transport.private_data,
    151                                    struct stream_connection);
    152 
    153         return socket_get_peer_addr(srv_conn->socket, mem_ctx);
    154 }
    155 
    156 struct dcerpc_read_ncacn_packet_state {
    157         struct {
    158                 struct smb_iconv_convenience *smb_iconv_c;
    159         } caller;
    160         DATA_BLOB buffer;
    161         struct ncacn_packet *pkt;
    162 };
    163 
    164 static int dcerpc_read_ncacn_packet_next_vector(struct tstream_context *stream,
    165                                                 void *private_data,
    166                                                 TALLOC_CTX *mem_ctx,
    167                                                 struct iovec **_vector,
    168                                                 size_t *_count);
    169 static void dcerpc_read_ncacn_packet_done(struct tevent_req *subreq);
    170 
    171 static struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx,
    172                                                  struct tevent_context *ev,
    173                                                  struct tstream_context *stream,
    174                                                  struct smb_iconv_convenience *ic)
    175 {
    176         struct tevent_req *req;
    177         struct dcerpc_read_ncacn_packet_state *state;
    178         struct tevent_req *subreq;
    179 
    180         req = tevent_req_create(mem_ctx, &state,
    181                                 struct dcerpc_read_ncacn_packet_state);
    182         if (req == NULL) {
    183                 return NULL;
    184         }
    185 
    186         state->caller.smb_iconv_c = ic;
    187         state->buffer = data_blob_const(NULL, 0);
    188         state->pkt = talloc(state, struct ncacn_packet);
    189         if (tevent_req_nomem(state->pkt, req)) {
    190                 goto post;
    191         }
    192 
    193         subreq = tstream_readv_pdu_send(state, ev,
    194                                         stream,
    195                                         dcerpc_read_ncacn_packet_next_vector,
    196                                         state);
    197         if (tevent_req_nomem(subreq, req)) {
    198                 goto post;
    199         }
    200         tevent_req_set_callback(subreq, dcerpc_read_ncacn_packet_done, req);
    201 
    202         return req;
    203  post:
    204         tevent_req_post(req, ev);
    205         return req;
    206 }
    207 
    208 static int dcerpc_read_ncacn_packet_next_vector(struct tstream_context *stream,
    209                                                 void *private_data,
    210                                                 TALLOC_CTX *mem_ctx,
    211                                                 struct iovec **_vector,
    212                                                 size_t *_count)
    213 {
    214         struct dcerpc_read_ncacn_packet_state *state =
    215                 talloc_get_type_abort(private_data,
    216                 struct dcerpc_read_ncacn_packet_state);
    217         struct iovec *vector;
    218         off_t ofs = 0;
    219 
    220         if (state->buffer.length == 0) {
    221                 /* first get enough to read the fragment length */
    222                 ofs = 0;
    223                 state->buffer.length = DCERPC_FRAG_LEN_OFFSET + 2;
    224                 state->buffer.data = talloc_array(state, uint8_t,
    225                                                   state->buffer.length);
    226                 if (!state->buffer.data) {
    227                         return -1;
    228                 }
    229         } else if (state->buffer.length == (DCERPC_FRAG_LEN_OFFSET + 2)) {
    230                 /* now read the fragment length and allocate the full buffer */
    231                 size_t frag_len = dcerpc_get_frag_length(&state->buffer);
    232 
    233                 ofs = state->buffer.length;
    234 
    235                 state->buffer.data = talloc_realloc(state,
    236                                                     state->buffer.data,
    237                                                     uint8_t, frag_len);
    238                 if (!state->buffer.data) {
    239                         return -1;
    240                 }
    241                 state->buffer.length = frag_len;
    242         } else {
    243                 /* if we reach this we have a full fragment */
    244                 *_vector = NULL;
    245                 *_count = 0;
    246                 return 0;
    247         }
    248 
    249         /* now create the vector that we want to be filled */
    250         vector = talloc_array(mem_ctx, struct iovec, 1);
    251         if (!vector) {
    252                 return -1;
    253         }
    254 
    255         vector[0].iov_base = state->buffer.data + ofs;
    256         vector[0].iov_len = state->buffer.length - ofs;
    257 
    258         *_vector = vector;
    259         *_count = 1;
    260         return 0;
    261 }
    262 
    263 static void dcerpc_read_ncacn_packet_done(struct tevent_req *subreq)
    264 {
    265         struct tevent_req *req = tevent_req_callback_data(subreq,
    266                                  struct tevent_req);
    267         struct dcerpc_read_ncacn_packet_state *state = tevent_req_data(req,
    268                                         struct dcerpc_read_ncacn_packet_state);
    269         int ret;
    270         int sys_errno;
    271         struct ndr_pull *ndr;
    272         enum ndr_err_code ndr_err;
    273         NTSTATUS status;
    274 
    275         ret = tstream_readv_pdu_recv(subreq, &sys_errno);
    276         TALLOC_FREE(subreq);
    277         if (ret == -1) {
    278                 status = map_nt_error_from_unix(sys_errno);
    279                 tevent_req_nterror(req, status);
    280                 return;
    281         }
    282 
    283         ndr = ndr_pull_init_blob(&state->buffer,
    284                                  state->pkt,
    285                                  state->caller.smb_iconv_c);
    286         if (tevent_req_nomem(ndr, req)) {
    287                 return;
    288         }
    289 
    290         if (!(CVAL(ndr->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) {
    291                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
    292         }
    293 
    294         if (CVAL(ndr->data, DCERPC_PFC_OFFSET) & DCERPC_PFC_FLAG_OBJECT_UUID) {
    295                 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
    296         }
    297 
    298         ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, state->pkt);
    299         TALLOC_FREE(ndr);
    300         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    301                 status = ndr_map_error2ntstatus(ndr_err);
    302                 tevent_req_nterror(req, status);
    303                 return;
    304         }
    305 
    306         tevent_req_done(req);
    307 }
    308 
    309 static NTSTATUS dcerpc_read_ncacn_packet_recv(struct tevent_req *req,
    310                                        TALLOC_CTX *mem_ctx,
    311                                        struct ncacn_packet **pkt,
    312                                        DATA_BLOB *buffer)
    313 {
    314         struct dcerpc_read_ncacn_packet_state *state = tevent_req_data(req,
    315                                         struct dcerpc_read_ncacn_packet_state);
    316         NTSTATUS status;
    317 
    318         if (tevent_req_is_nterror(req, &status)) {
    319                 tevent_req_received(req);
    320                 return status;
    321         }
    322 
    323         *pkt = talloc_move(mem_ctx, &state->pkt);
    324         if (buffer) {
    325                 buffer->data = talloc_move(mem_ctx, &state->buffer.data);
    326                 buffer->length = state->buffer.length;
    327         }
    328 
    329         tevent_req_received(req);
    330         return NT_STATUS_OK;
    331 }
    332 
    333 static void dcesrv_read_fragment_done(struct tevent_req *subreq);
    334 
    335 static void dcesrv_sock_accept(struct stream_connection *srv_conn)
    336 {
    337         NTSTATUS status;
    338         struct dcesrv_socket_context *dcesrv_sock =
    339                 talloc_get_type(srv_conn->private_data, struct dcesrv_socket_context);
    340         struct dcesrv_connection *dcesrv_conn = NULL;
    341         int ret;
    342         struct tevent_req *subreq;
    343         struct loadparm_context *lp_ctx = dcesrv_sock->dcesrv_ctx->lp_ctx;
    344 
    345         if (!srv_conn->session_info) {
    346                 status = auth_anonymous_session_info(srv_conn,
    347                                                      srv_conn->event.ctx,
    348                                                      lp_ctx,
    349                                                      &srv_conn->session_info);
    350                 if (!NT_STATUS_IS_OK(status)) {
    351                         DEBUG(0,("dcesrv_sock_accept: auth_anonymous_session_info failed: %s\n",
    352                                 nt_errstr(status)));
    353                         stream_terminate_connection(srv_conn, nt_errstr(status));
    354                         return;
    355                 }
    356         }
    357 
    358         status = dcesrv_endpoint_connect(dcesrv_sock->dcesrv_ctx,
    359                                          srv_conn,
    360                                          dcesrv_sock->endpoint,
    361                                          srv_conn->session_info,
    362                                          srv_conn->event.ctx,
    363                                          srv_conn->msg_ctx,
    364                                          srv_conn->server_id,
    365                                          DCESRV_CALL_STATE_FLAG_MAY_ASYNC,
    366                                          &dcesrv_conn);
    367         if (!NT_STATUS_IS_OK(status)) {
    368                 DEBUG(0,("dcesrv_sock_accept: dcesrv_endpoint_connect failed: %s\n",
    369                         nt_errstr(status)));
    370                 stream_terminate_connection(srv_conn, nt_errstr(status));
    371                 return;
    372         }
    373 
    374         dcesrv_conn->transport.private_data             = srv_conn;
    375         dcesrv_conn->transport.report_output_data       = dcesrv_sock_report_output_data;
    376         dcesrv_conn->transport.get_my_addr              = dcesrv_sock_get_my_addr;
    377         dcesrv_conn->transport.get_peer_addr            = dcesrv_sock_get_peer_addr;
    378 
    379         TALLOC_FREE(srv_conn->event.fde);
    380 
    381         dcesrv_conn->send_queue = tevent_queue_create(dcesrv_conn, "dcesrv send queue");
    382         if (!dcesrv_conn->send_queue) {
    383                 status = NT_STATUS_NO_MEMORY;
    384                 DEBUG(0,("dcesrv_sock_accept: tevent_queue_create(%s)\n",
    385                         nt_errstr(status)));
    386                 stream_terminate_connection(srv_conn, nt_errstr(status));
    387                 return;
    388         }
    389 
    390         if (dcesrv_sock->endpoint->ep_description->transport == NCACN_NP) {
    391                 dcesrv_conn->auth_state.session_key = dcesrv_inherited_session_key;
    392                 ret = tstream_npa_existing_socket(dcesrv_conn,
    393                                                   socket_get_fd(srv_conn->socket),
    394                                                   FILE_TYPE_MESSAGE_MODE_PIPE,
    395                                                   &dcesrv_conn->stream);
    396         } else {
    397                 ret = tstream_bsd_existing_socket(dcesrv_conn,
    398                                                   socket_get_fd(srv_conn->socket),
    399                                                   &dcesrv_conn->stream);
    400         }
    401         if (ret == -1) {
    402                 status = map_nt_error_from_unix(errno);
    403                 DEBUG(0,("dcesrv_sock_accept: failed to setup tstream: %s\n",
    404                         nt_errstr(status)));
    405                 stream_terminate_connection(srv_conn, nt_errstr(status));
    406                 return;
    407         }
    408 
    409         srv_conn->private_data = dcesrv_conn;
    410 
    411         irpc_add_name(srv_conn->msg_ctx, "rpc_server");
    412 
    413         subreq = dcerpc_read_ncacn_packet_send(dcesrv_conn,
    414                                                dcesrv_conn->event_ctx,
    415                                                dcesrv_conn->stream,
    416                                                lp_iconv_convenience(lp_ctx));
    417         if (!subreq) {
    418                 status = NT_STATUS_NO_MEMORY;
    419                 DEBUG(0,("dcesrv_sock_accept: dcerpc_read_fragment_buffer_send(%s)\n",
    420                         nt_errstr(status)));
    421                 stream_terminate_connection(srv_conn, nt_errstr(status));
    422                 return;
    423         }
    424         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dcesrv_conn);
    425 
    426         return;
    427 }
    428 
    429 static void dcesrv_read_fragment_done(struct tevent_req *subreq)
    430 {
    431         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
    432                                              struct dcesrv_connection);
    433         struct ncacn_packet *pkt;
    434         DATA_BLOB buffer;
    435         NTSTATUS status;
    436         struct loadparm_context *lp_ctx = dce_conn->dce_ctx->lp_ctx;
    437 
    438         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
    439                                                &pkt, &buffer);
    440         TALLOC_FREE(subreq);
    441         if (!NT_STATUS_IS_OK(status)) {
    442                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
    443                 return;
    444         }
    445 
    446         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
    447         if (!NT_STATUS_IS_OK(status)) {
    448                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
    449                 return;
    450         }
    451 
    452         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
    453                                                dce_conn->event_ctx,
    454                                                dce_conn->stream,
    455                                                lp_iconv_convenience(lp_ctx));
    456         if (!subreq) {
    457                 status = NT_STATUS_NO_MEMORY;
    458                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
    459                 return;
    460         }
    461         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
    462 }
    463 
    464 static void dcesrv_sock_recv(struct stream_connection *conn, uint16_t flags)
    465 {
    466         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
    467                                              struct dcesrv_connection);
    468         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_recv triggered");
    469 }
    470 
    471 static void dcesrv_sock_send(struct stream_connection *conn, uint16_t flags)
    472 {
    473         struct dcesrv_connection *dce_conn = talloc_get_type(conn->private_data,
    474                                              struct dcesrv_connection);
    475         dcesrv_terminate_connection(dce_conn, "dcesrv_sock_send triggered");
    476 }
    477 
    478 
    479 static const struct stream_server_ops dcesrv_stream_ops = {
    480         .name                   = "rpc",
    481         .accept_connection      = dcesrv_sock_accept,
    482         .recv_handler           = dcesrv_sock_recv,
    483         .send_handler           = dcesrv_sock_send,
    484 };
    485 
    486 
    487 
    488 static NTSTATUS dcesrv_add_ep_unix(struct dcesrv_context *dce_ctx,
    489                                    struct loadparm_context *lp_ctx,
    490                                    struct dcesrv_endpoint *e,
    491                             struct tevent_context *event_ctx, const struct model_ops *model_ops)
    492 {
    493         struct dcesrv_socket_context *dcesrv_sock;
    494         uint16_t port = 1;
    495         NTSTATUS status;
    496 
    497         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
    498         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
    499 
    500         /* remember the endpoint of this socket */
    501         dcesrv_sock->endpoint           = e;
    502         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
    503 
    504         status = stream_setup_socket(event_ctx, lp_ctx,
    505                                      model_ops, &dcesrv_stream_ops,
    506                                      "unix", e->ep_description->endpoint, &port,
    507                                      lp_socket_options(lp_ctx),
    508                                      dcesrv_sock);
    509         if (!NT_STATUS_IS_OK(status)) {
    510                 DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
    511                          e->ep_description->endpoint, nt_errstr(status)));
    512         }
    513 
    514         return status;
    515 }
    516 
    517 static NTSTATUS dcesrv_add_ep_ncalrpc(struct dcesrv_context *dce_ctx,
    518                                       struct loadparm_context *lp_ctx,
    519                                       struct dcesrv_endpoint *e,
    520                                       struct tevent_context *event_ctx, const struct model_ops *model_ops)
    521 {
    522         struct dcesrv_socket_context *dcesrv_sock;
    523         uint16_t port = 1;
    524         char *full_path;
    525         NTSTATUS status;
    526 
    527         if (!e->ep_description->endpoint) {
    528                 /* No identifier specified: use DEFAULT.
    529                  * DO NOT hardcode this value anywhere else. Rather, specify
    530                  * no endpoint and let the epmapper worry about it. */
    531                 e->ep_description->endpoint = talloc_strdup(dce_ctx, "DEFAULT");
    532         }
    533 
    534         full_path = talloc_asprintf(dce_ctx, "%s/%s", lp_ncalrpc_dir(lp_ctx),
    535                                     e->ep_description->endpoint);
    536 
    537         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
    538         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
    539 
    540         /* remember the endpoint of this socket */
    541         dcesrv_sock->endpoint           = e;
    542         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
    543 
    544         status = stream_setup_socket(event_ctx, lp_ctx,
    545                                      model_ops, &dcesrv_stream_ops,
    546                                      "unix", full_path, &port,
    547                                      lp_socket_options(lp_ctx),
    548                                      dcesrv_sock);
    549         if (!NT_STATUS_IS_OK(status)) {
    550                 DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed - %s\n",
    551                          e->ep_description->endpoint, full_path, nt_errstr(status)));
    552         }
    553         return status;
    554 }
    555 
    556 static NTSTATUS dcesrv_add_ep_np(struct dcesrv_context *dce_ctx,
    557                                  struct loadparm_context *lp_ctx,
    558                                  struct dcesrv_endpoint *e,
    559                                  struct tevent_context *event_ctx, const struct model_ops *model_ops)
    560 {
    561         struct dcesrv_socket_context *dcesrv_sock;
    562         NTSTATUS status;
    563                        
    564         if (e->ep_description->endpoint == NULL) {
    565                 DEBUG(0, ("Endpoint mandatory for named pipes\n"));
    566                 return NT_STATUS_INVALID_PARAMETER;
    567         }
    568 
    569         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
    570         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
    571 
    572         /* remember the endpoint of this socket */
    573         dcesrv_sock->endpoint           = e;
    574         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
    575 
    576         status = stream_setup_named_pipe(event_ctx, lp_ctx,
    577                                          model_ops, &dcesrv_stream_ops,
    578                                          e->ep_description->endpoint, dcesrv_sock);
    579         if (!NT_STATUS_IS_OK(status)) {
    580                 DEBUG(0,("stream_setup_named_pipe(pipe=%s) failed - %s\n",
    581                          e->ep_description->endpoint, nt_errstr(status)));
    582                 return status;
    583         }
    584 
    585         return NT_STATUS_OK;
    586 }
    587 
    588 /*
    589   add a socket address to the list of events, one event per dcerpc endpoint
    590 */
    591 static NTSTATUS add_socket_rpc_tcp_iface(struct dcesrv_context *dce_ctx, struct dcesrv_endpoint *e,
    592                                          struct tevent_context *event_ctx, const struct model_ops *model_ops,
    593                                          const char *address)
    594 {
    595         struct dcesrv_socket_context *dcesrv_sock;
    596         uint16_t port = 0;
    597         NTSTATUS status;
    598                        
    599         if (e->ep_description->endpoint) {
    600                 port = atoi(e->ep_description->endpoint);
    601         }
    602 
    603         dcesrv_sock = talloc(event_ctx, struct dcesrv_socket_context);
    604         NT_STATUS_HAVE_NO_MEMORY(dcesrv_sock);
    605 
    606         /* remember the endpoint of this socket */
    607         dcesrv_sock->endpoint           = e;
    608         dcesrv_sock->dcesrv_ctx         = talloc_reference(dcesrv_sock, dce_ctx);
    609 
    610         status = stream_setup_socket(event_ctx, dce_ctx->lp_ctx,
    611                                      model_ops, &dcesrv_stream_ops,
    612                                      "ipv4", address, &port,
    613                                      lp_socket_options(dce_ctx->lp_ctx),
    614                                      dcesrv_sock);
    615         if (!NT_STATUS_IS_OK(status)) {
    616                 DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
    617                          address, port, nt_errstr(status)));
    618         }
    619 
    620         if (e->ep_description->endpoint == NULL) {
    621                 e->ep_description->endpoint = talloc_asprintf(dce_ctx, "%d", port);
    622         }
    623 
    624         return status;
    625 }
    626 
    627 static NTSTATUS dcesrv_add_ep_tcp(struct dcesrv_context *dce_ctx,
    628                                   struct loadparm_context *lp_ctx,
    629                                   struct dcesrv_endpoint *e,
    630                                   struct tevent_context *event_ctx, const struct model_ops *model_ops)
    631 {
    632         NTSTATUS status;
    633 
    634         /* Add TCP/IP sockets */
    635         if (lp_interfaces(lp_ctx) && lp_bind_interfaces_only(lp_ctx)) {
    636                 int num_interfaces;
    637                 int i;
    638                 struct interface *ifaces;
    639 
    640                 load_interfaces(dce_ctx, lp_interfaces(lp_ctx), &ifaces);
    641 
    642                 num_interfaces = iface_count(ifaces);
    643                 for(i = 0; i < num_interfaces; i++) {
    644                         const char *address = iface_n_ip(ifaces, i);
    645                         status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops, address);
    646                         NT_STATUS_NOT_OK_RETURN(status);
    647                 }
    648         } else {
    649                 status = add_socket_rpc_tcp_iface(dce_ctx, e, event_ctx, model_ops,
    650                                                   lp_socket_address(lp_ctx));
    651                 NT_STATUS_NOT_OK_RETURN(status);
    652         }
    653 
    654         return NT_STATUS_OK;
    655 }
    656 
    657 NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
    658                        struct loadparm_context *lp_ctx,
    659                        struct dcesrv_endpoint *e,
    660                        struct tevent_context *event_ctx,
    661                        const struct model_ops *model_ops)
    662 {
    663         switch (e->ep_description->transport) {
    664         case NCACN_UNIX_STREAM:
    665                 return dcesrv_add_ep_unix(dce_ctx, lp_ctx, e, event_ctx, model_ops);
    666 
    667         case NCALRPC:
    668                 return dcesrv_add_ep_ncalrpc(dce_ctx, lp_ctx, e, event_ctx, model_ops);
    669 
    670         case NCACN_IP_TCP:
    671                 return dcesrv_add_ep_tcp(dce_ctx, lp_ctx, e, event_ctx, model_ops);
    672 
    673         case NCACN_NP:
    674                 return dcesrv_add_ep_np(dce_ctx, lp_ctx, e, event_ctx, model_ops);
    675 
    676         default:
    677                 return NT_STATUS_NOT_SUPPORTED;
    678         }
    679 }
    68042
    68143/*
     
    69557        /* run the rpc server as a single process to allow for shard
    69658         * handles, and sharing of ldb contexts */
    697         model_ops = process_model_startup(task->event_ctx, "single");
     59        model_ops = process_model_startup("single");
    69860        if (!model_ops) goto failed;
    69961
    70062        status = dcesrv_init_context(task->event_ctx,
    70163                                     task->lp_ctx,
    702                                      lp_dcerpc_endpoint_servers(task->lp_ctx),
     64                                     lpcfg_dcerpc_endpoint_servers(task->lp_ctx),
    70365                                     &dce_ctx);
    70466        if (!NT_STATUS_IS_OK(status)) goto failed;
    70567
    70668        /* Make sure the directory for NCALRPC exists */
    707         if (!directory_exist(lp_ncalrpc_dir(task->lp_ctx))) {
    708                 mkdir(lp_ncalrpc_dir(task->lp_ctx), 0755);
     69        if (!directory_exist(lpcfg_ncalrpc_dir(task->lp_ctx))) {
     70                mkdir(lpcfg_ncalrpc_dir(task->lp_ctx), 0755);
    70971        }
    71072
     
    72183NTSTATUS server_service_rpc_init(void)
    72284{
    723 
    72485        return register_server_service("rpc", dcesrv_task_init);
    72586}
  • trunk/server/source4/rpc_server/spoolss/dcesrv_spoolss.c

    r429 r745  
    2525#include "librpc/gen_ndr/ndr_spoolss.h"
    2626#include "ntptr/ntptr.h"
    27 #include "lib/socket/socket.h"
     27#include "lib/tsocket/tsocket.h"
    2828#include "librpc/gen_ndr/ndr_spoolss_c.h"
    2929#include "auth/credentials/credentials.h"
     
    3434};
    3535
    36 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
    37         ((info)?ndr_size_##fn(info, level, ic, 0):0)
    38 
    39 #define SPOOLSS_BUFFER_UNION_ARRAY(fn,ic,info,level,count) \
    40         ((info)?ndr_size_##fn##_info(dce_call, ic, level, count, info):0)
     36#define SPOOLSS_BUFFER_UNION(fn,info,level) \
     37        ((info)?ndr_size_##fn(info, level, 0):0)
     38
     39#define SPOOLSS_BUFFER_UNION_ARRAY(fn,info,level,count) \
     40        ((info)?ndr_size_##fn##_info(dce_call, level, count, info):0)
    4141
    4242#define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
     
    149149{
    150150        bool ret;
    151         struct socket_address *myaddr;
     151        const struct tsocket_address *local_address;
     152        char *myaddr;
    152153        const char **aliases;
    153         int i;
     154        const char *dnsdomain;
     155        unsigned int i;
    154156
    155157        /* NULL is ok */
     
    173175
    174176        /* NETBIOS NAME is ok */
    175         ret = strequal(lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx), server_name);
     177        ret = strequal(lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx), server_name);
    176178        if (ret) return WERR_OK;
    177179
    178         aliases = lp_netbios_aliases(dce_call->conn->dce_ctx->lp_ctx);
     180        aliases = lpcfg_netbios_aliases(dce_call->conn->dce_ctx->lp_ctx);
    179181
    180182        for (i=0; aliases && aliases[i]; i++) {
     
    187189         * TODO: we need to check if aliases are also ok
    188190         */
    189         if (lp_realm(dce_call->conn->dce_ctx->lp_ctx)) {
     191        dnsdomain = lpcfg_dnsdomain(dce_call->conn->dce_ctx->lp_ctx);
     192        if (dnsdomain != NULL) {
    190193                char *str;
    191194
    192195                str = talloc_asprintf(mem_ctx, "%s.%s",
    193                                                 lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx),
    194                                                 lp_realm(dce_call->conn->dce_ctx->lp_ctx));
     196                                                lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx),
     197                                                dnsdomain);
    195198                W_ERROR_HAVE_NO_MEMORY(str);
    196199
     
    200203        }
    201204
    202         myaddr = dcesrv_connection_get_my_addr(dce_call->conn, mem_ctx);
     205        local_address = dcesrv_connection_get_local_address(dce_call->conn);
     206
     207        myaddr = tsocket_address_inet_addr_string(local_address, mem_ctx);
    203208        W_ERROR_HAVE_NO_MEMORY(myaddr);
    204209
    205         ret = strequal(myaddr->addr, server_name);
     210        ret = strequal(myaddr, server_name);
    206211        talloc_free(myaddr);
    207212        if (ret) return WERR_OK;
     
    216221
    217222        status = ntptr_init_context(dce_call->context, dce_call->conn->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
    218                                     lp_ntptr_providor(dce_call->conn->dce_ctx->lp_ctx), &ntptr);
     223                                    lpcfg_ntptr_providor(dce_call->conn->dce_ctx->lp_ctx), &ntptr);
    219224        NT_STATUS_NOT_OK_RETURN(status);
    220225
     
    234239        struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private_data, struct ntptr_context);
    235240        WERROR status;
    236         struct smb_iconv_convenience *ic = lp_iconv_convenience(ntptr->lp_ctx);
    237241
    238242        status = dcesrv_spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
     
    242246        W_ERROR_NOT_OK_RETURN(status);
    243247
    244         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinters, ic, *r->out.info, r->in.level, *r->out.count);
     248        *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinters, *r->out.info, r->in.level, *r->out.count);
    245249        *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    246250        *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
     
    370374        struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private_data, struct ntptr_context);
    371375        WERROR status;
    372         struct smb_iconv_convenience *ic = lp_iconv_convenience(ntptr->lp_ctx);
    373376
    374377        status = dcesrv_spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
     
    378381        W_ERROR_NOT_OK_RETURN(status);
    379382
    380         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinterDrivers, ic, *r->out.info, r->in.level, *r->out.count);
     383        *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinterDrivers, *r->out.info, r->in.level, *r->out.count);
    381384        *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    382385        *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
     
    403406        struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private_data, struct ntptr_context);
    404407        WERROR status;
    405         struct smb_iconv_convenience *ic = lp_iconv_convenience(ntptr->lp_ctx);
    406408
    407409        status = dcesrv_spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
     
    411413        W_ERROR_NOT_OK_RETURN(status);
    412414
    413         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, ic, r->out.info, r->in.level);
     415        *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, r->out.info, r->in.level);
    414416        r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    415417        return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
     
    455457        struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private_data, struct ntptr_context);
    456458        WERROR status;
    457         struct smb_iconv_convenience *ic = lp_iconv_convenience(ntptr->lp_ctx);
    458459
    459460        status = dcesrv_spoolss_check_server_name(dce_call, mem_ctx, r->in.server);
     
    463464        W_ERROR_NOT_OK_RETURN(status);
    464465
    465         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, ic, r->out.info, r->in.level);
     466        *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, r->out.info, r->in.level);
    466467        r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    467468        return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
     
    572573        struct dcesrv_handle *h;
    573574        WERROR status;
    574         struct smb_iconv_convenience *ic = lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx);
    575575
    576576        r->out.type = talloc_zero(mem_ctx, enum winreg_Type);
     
    718718        struct dcesrv_handle *h;
    719719        WERROR status;
    720         struct smb_iconv_convenience *ic = lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx);
    721720
    722721        DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
     
    739738        }
    740739
    741         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, ic, r->out.info, r->in.level);
     740        *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, r->out.info, r->in.level);
    742741        r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
    743742        return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
     
    786785        struct dcesrv_handle *h;
    787786        WERROR status;
    788         struct smb_iconv_convenience *ic = lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx);
    789787
    790788        DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY);
     
    806804        }
    807805
    808         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumForms, ic, *r->out.info, r->in.level, *r->out.count);
     806        *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumForms, *r->out.info, r->in.level, *r->out.count);
    809807        *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    810808        *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
     
    821819        struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private_data, struct ntptr_context);
    822820        WERROR status;
    823         struct smb_iconv_convenience *ic = lp_iconv_convenience(ntptr->lp_ctx);
    824821
    825822        status = dcesrv_spoolss_check_server_name(dce_call, mem_ctx, r->in.servername);
     
    829826        W_ERROR_NOT_OK_RETURN(status);
    830827
    831         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPorts, ic, *r->out.info, r->in.level, *r->out.count);
     828        *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPorts, *r->out.info, r->in.level, *r->out.count);
    832829        *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    833830        *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
     
    844841        struct ntptr_context *ntptr = talloc_get_type(dce_call->context->private_data, struct ntptr_context);
    845842        WERROR status;
    846         struct smb_iconv_convenience *ic = lp_iconv_convenience(ntptr->lp_ctx);
    847843
    848844        status = dcesrv_spoolss_check_server_name(dce_call, mem_ctx, r->in.servername);
     
    852848        W_ERROR_NOT_OK_RETURN(status);
    853849
    854         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumMonitors, ic, *r->out.info, r->in.level, *r->out.count);
     850        *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumMonitors, *r->out.info, r->in.level, *r->out.count);
    855851        *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
    856852        *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
     
    11961192
    11971193        ZERO_STRUCT(rop);
    1198         rop.in.server_name = lp_netbios_name(dce_call->conn->dce_ctx->lp_ctx);
     1194        rop.in.server_name = lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx);
    11991195        W_ERROR_HAVE_NO_MEMORY(rop.in.server_name);
    12001196        rop.in.printer_local = 0;
     
    12041200        rop.out.handle = &notify_handle;
    12051201
    1206         status = dcerpc_spoolss_ReplyOpenPrinter(p, mem_ctx, &rop);
     1202        status = dcerpc_spoolss_ReplyOpenPrinter_r(p->binding_handle, mem_ctx, &rop);
    12071203        if (NT_STATUS_IS_ERR(status)) {
    12081204                DEBUG(0, ("unable to open remote printer %s\n",
     
    13101306
    13111307/*
    1312   spoolss_47
    1313 */
    1314 static WERROR dcesrv_spoolss_47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1315                        struct spoolss_47 *r)
     1308  spoolss_SetPort
     1309*/
     1310static WERROR dcesrv_spoolss_SetPort(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     1311                       struct spoolss_SetPort *r)
    13161312{
    13171313        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     
    14501446
    14511447/*
    1452   spoolss_55
    1453 */
    1454 static WERROR dcesrv_spoolss_55(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1455                        struct spoolss_55 *r)
    1456 {
    1457         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1458 }
    1459 
    1460 
    1461 /*
    1462   spoolss_56
    1463 */
    1464 static WERROR dcesrv_spoolss_56(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1465                        struct spoolss_56 *r)
    1466 {
    1467         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1468 }
    1469 
    1470 
    1471 /*
    1472   spoolss_57
    1473 */
    1474 static WERROR dcesrv_spoolss_57(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1475                        struct spoolss_57 *r)
     1448  spoolss_AddPerMachineConnection
     1449*/
     1450static WERROR dcesrv_spoolss_AddPerMachineConnection(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     1451                       struct spoolss_AddPerMachineConnection *r)
     1452{
     1453        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     1454}
     1455
     1456
     1457/*
     1458  spoolss_DeletePerMachineConnection
     1459*/
     1460static WERROR dcesrv_spoolss_DeletePerMachineConnection(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     1461                       struct spoolss_DeletePerMachineConnection *r)
     1462{
     1463        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     1464}
     1465
     1466
     1467/*
     1468  spoolss_EnumPerMachineConnections
     1469*/
     1470static WERROR dcesrv_spoolss_EnumPerMachineConnections(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     1471                       struct spoolss_EnumPerMachineConnections *r)
    14761472{
    14771473        DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
  • trunk/server/source4/rpc_server/srvsvc/dcesrv_srvsvc.c

    r414 r745  
    2525#include "librpc/gen_ndr/ndr_srvsvc.h"
    2626#include "rpc_server/common/common.h"
     27#include "rpc_server/common/share.h"
    2728#include "auth/auth.h"
    2829#include "libcli/security/security.h"
     
    3435        struct security_token *t = dce_call->conn->auth_state.session_info->security_token; \
    3536        if (!security_token_has_builtin_administrators(t) && \
    36             !security_token_has_sid_string(t, SID_BUILTIN_SERVER_OPERATORS)) { \
     37            !security_token_has_sid(t, &global_sid_Builtin_Server_Operators)) { \
    3738                return WERR_ACCESS_DENIED; \
    3839        } \
     
    6970                return WERR_UNKNOWN_LEVEL;
    7071        }
    71 
    72         return WERR_OK;
    7372}
    7473
     
    9493                return WERR_UNKNOWN_LEVEL;
    9594        }
    96 
    97         return WERR_UNKNOWN_LEVEL;
    9895}
    9996
     
    141138                return WERR_UNKNOWN_LEVEL;
    142139        }
    143 
    144         return WERR_UNKNOWN_LEVEL;
    145140}
    146141
     
    166161                return WERR_UNKNOWN_LEVEL;
    167162        }
    168 
    169         return WERR_UNKNOWN_LEVEL;
    170163}
    171164
     
    195188                return WERR_UNKNOWN_LEVEL;
    196189        }
    197 
    198         return WERR_UNKNOWN_LEVEL;
    199190}
    200191
     
    252243                return WERR_UNKNOWN_LEVEL;
    253244        }
    254 
    255         return WERR_UNKNOWN_LEVEL;
    256245}
    257246
     
    289278                return WERR_UNKNOWN_LEVEL;
    290279        }
    291 
    292         return WERR_UNKNOWN_LEVEL;
    293280}
    294281
     
    314301                return WERR_UNKNOWN_LEVEL;
    315302        }
    316 
    317         return WERR_UNKNOWN_LEVEL;
    318303}
    319304
     
    391376                return WERR_UNKNOWN_LEVEL;
    392377        }
    393 
    394         return WERR_UNKNOWN_LEVEL;
    395378}
    396379
     
    432415                struct share_info *info;
    433416                struct share_context *sctx;
    434                 int count = 8;
    435                 int i;
    436 
    437                 nterr = share_get_context_by_name(mem_ctx, lp_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
     417                unsigned int count = 8;
     418                unsigned int i;
     419
     420                nterr = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
    438421                if (!NT_STATUS_IS_OK(nterr)) {
    439422                        return ntstatus_to_werror(nterr);
     
    449432                info[i].type = SHARE_INFO_STRING;
    450433                switch (r->in.info->info2->type) {
    451                 case 0x00:
     434                case STYPE_DISKTREE:
    452435                        info[i].value = talloc_strdup(info, "DISK");
    453436                        break;
    454                 case 0x01:
     437                case STYPE_PRINTQ:
    455438                        info[i].value = talloc_strdup(info, "PRINTER");
    456439                        break;
    457                 case 0x03:
     440                case STYPE_IPC:
    458441                        info[i].value = talloc_strdup(info, "IPC");
    459442                        break;
     
    530513                struct share_info *info;
    531514                struct share_context *sctx;
    532                 int count = 10;
    533                 int i;
    534 
    535                 nterr = share_get_context_by_name(mem_ctx, lp_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
     515                unsigned int count = 10;
     516                unsigned int i;
     517
     518                nterr = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
    536519                if (!NT_STATUS_IS_OK(nterr)) {
    537520                        return ntstatus_to_werror(nterr);
     
    619602                return WERR_UNKNOWN_LEVEL;
    620603        }
    621 
    622         return WERR_UNKNOWN_LEVEL;
    623604}
    624605
     
    700681                return WERR_UNKNOWN_LEVEL;
    701682        }
    702 
    703         return WERR_UNKNOWN_LEVEL;
    704683}
    705684
     
    721700         */
    722701
    723         nterr = share_get_context_by_name(mem_ctx, lp_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
     702        nterr = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
    724703        if (!NT_STATUS_IS_OK(nterr)) {
    725704                return ntstatus_to_werror(nterr);
     
    734713        case 0:
    735714        {
    736                 int i;
     715                unsigned int i;
    737716                struct srvsvc_NetShareCtr0 *ctr0;
    738717
     
    775754        case 1:
    776755        {
    777                 int i;
     756                unsigned int i;
    778757                struct srvsvc_NetShareCtr1 *ctr1;
    779758
     
    817796        case 2:
    818797        {
    819                 int i;
     798                unsigned int i;
    820799                struct srvsvc_NetShareCtr2 *ctr2;
    821800
     
    861840        case 501:
    862841        {
    863                 int i;
     842                unsigned int i;
    864843                struct srvsvc_NetShareCtr501 *ctr501;
    865844
     
    905884        case 502:
    906885        {
    907                 int i;
     886                unsigned int i;
    908887                struct srvsvc_NetShareCtr502 *ctr502;
    909888
     
    950929                return WERR_UNKNOWN_LEVEL;
    951930        }
    952 
    953         return WERR_UNKNOWN_LEVEL;
    954931}
    955932
     
    974951        }
    975952
    976         nterr = share_get_context_by_name(mem_ctx, lp_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
     953        nterr = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
    977954        if (!NT_STATUS_IS_OK(nterr)) {
    978955                return ntstatus_to_werror(nterr);
     
    10881065                return WERR_UNKNOWN_LEVEL;
    10891066        }
    1090 
    1091         return WERR_UNKNOWN_LEVEL;
    10921067}
    10931068
     
    11031078                                        struct security_descriptor *sd)
    11041079{
    1105         int i = 0;
     1080        unsigned int i = 0;
    11061081
    11071082        if (level == 501) {
     
    12221197        W_ERROR_HAVE_NO_MEMORY(info);
    12231198
    1224         ZERO_STRUCT(r->out);
    1225 
    12261199        if (strcmp("", r->in.share_name) == 0) {
    12271200                return WERR_INVALID_PARAM;
    12281201        }
    12291202
    1230         nterr = share_get_context_by_name(mem_ctx, lp_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
     1203        nterr = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
    12311204        if (!NT_STATUS_IS_OK(nterr)) {
    12321205                return ntstatus_to_werror(nterr);
     
    13841357        char *device;
    13851358        const char **names;
    1386         int count, i;
     1359        int count;
     1360        int i;
    13871361
    13881362        *r->out.type = 0;
     
    14051379        all_string_sub(device, "\\", "/", 0);
    14061380
    1407         nterr = share_get_context_by_name(mem_ctx, lp_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
     1381        nterr = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
    14081382        if (!NT_STATUS_IS_OK(nterr)) {
    14091383                return ntstatus_to_werror(nterr);
     
    14581432{
    14591433        struct dcesrv_context *dce_ctx = dce_call->conn->dce_ctx;
    1460         struct dcerpc_server_info *server_info = lp_dcerpc_server_info(mem_ctx, dce_ctx->lp_ctx);
     1434        struct dcerpc_server_info *server_info = lpcfg_dcerpc_server_info(mem_ctx, dce_ctx->lp_ctx);
    14611435
    14621436        ZERO_STRUCTP(r->out.info);
     
    14911465                info101->version_minor  = server_info->version_minor;
    14921466                info101->server_type    = dcesrv_common_get_server_type(mem_ctx, dce_call->event_ctx, dce_ctx);
    1493                 info101->comment        = talloc_strdup(mem_ctx, lp_serverstring(dce_ctx->lp_ctx));
     1467                info101->comment        = talloc_strdup(mem_ctx, lpcfg_serverstring(dce_ctx->lp_ctx));
    14941468                W_ERROR_HAVE_NO_MEMORY(info101->comment);
    14951469
     
    15111485                info102->version_minor  = server_info->version_minor;
    15121486                info102->server_type    = dcesrv_common_get_server_type(mem_ctx, dce_call->event_ctx, dce_ctx);
    1513                 info102->comment        = talloc_strdup(mem_ctx, lp_serverstring(dce_ctx->lp_ctx));
     1487                info102->comment        = talloc_strdup(mem_ctx, lpcfg_serverstring(dce_ctx->lp_ctx));
    15141488                W_ERROR_HAVE_NO_MEMORY(info102->comment);
    15151489
     
    15291503                return WERR_UNKNOWN_LEVEL;
    15301504        }
    1531 
    1532         return WERR_UNKNOWN_LEVEL;
    15331505}
    15341506
     
    15771549                return WERR_UNKNOWN_LEVEL;
    15781550        }
    1579 
    1580         return WERR_UNKNOWN_LEVEL;
    15811551}
    15821552
     
    16581628                return WERR_UNKNOWN_LEVEL;
    16591629        }
    1660 
    1661         return WERR_UNKNOWN_LEVEL;
    16621630}
    16631631
     
    17881756                return WERR_INVALID_PARAM;
    17891757        }
    1790 
    1791         return WERR_INVALID_PARAM;
    17921758}
    17931759
     
    18211787         */
    18221788
    1823         nterr = share_get_context_by_name(mem_ctx, lp_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
     1789        nterr = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
    18241790        if (!NT_STATUS_IS_OK(nterr)) {
    18251791                return ntstatus_to_werror(nterr);
     
    18341800        case 0:
    18351801        {
    1836                 int i, y = 0;
    1837                 int count;
     1802                unsigned int i, y = 0;
     1803                unsigned int count;
    18381804                struct srvsvc_NetShareCtr0 *ctr0;
    18391805
     
    18861852        case 1:
    18871853        {
    1888                 int i, y = 0;
    1889                 int count;
     1854                unsigned int i, y = 0;
     1855                unsigned int count;
    18901856                struct srvsvc_NetShareCtr1 *ctr1;
    18911857
     
    19381904        case 2:
    19391905        {
    1940                 int i, y = 0;
    1941                 int count;
     1906                unsigned int i, y = 0;
     1907                unsigned int count;
    19421908                struct srvsvc_NetShareCtr2 *ctr2;
    19431909
     
    19921958        case 502:
    19931959        {
    1994                 int i, y = 0;
    1995                 int count;
     1960                unsigned int i, y = 0;
     1961                unsigned int count;
    19961962                struct srvsvc_NetShareCtr502 *ctr502;
    19971963
     
    20472013                return WERR_UNKNOWN_LEVEL;
    20482014        }
    2049 
    2050         return WERR_UNKNOWN_LEVEL;
    20512015}
    20522016
     
    22882252        struct share_context *sctx;
    22892253               
    2290         nterr = share_get_context_by_name(mem_ctx, lp_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
     2254        nterr = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
    22912255        if (!NT_STATUS_IS_OK(nterr)) {
    22922256                return ntstatus_to_werror(nterr);
  • trunk/server/source4/rpc_server/srvsvc/srvsvc_ntvfs.c

    r414 r745  
    2222#include "ntvfs/ntvfs.h"
    2323#include "rpc_server/dcerpc_server.h"
    24 #include "librpc/gen_ndr/ndr_srvsvc.h"
    25 #include "rpc_server/common/common.h"
    26 #include "rpc_server/srvsvc/proto.h"
    27 #include "lib/socket/socket.h"
    2824#include "param/param.h"
    29 
    30 struct socket_address *srvsvc_get_my_addr(void *p, TALLOC_CTX *mem_ctx)
    31 {
    32         struct dcesrv_connection *conn = talloc_get_type(p, struct dcesrv_connection);
    33         return dcesrv_connection_get_my_addr(conn, mem_ctx);
    34 }
    35 
    36 struct socket_address *srvsvc_get_peer_addr(void *p, TALLOC_CTX *mem_ctx)
    37 {
    38         struct dcesrv_connection *conn = talloc_get_type(p, struct dcesrv_connection);
    39         return dcesrv_connection_get_peer_addr(conn, mem_ctx);
    40 }
    4125
    4226struct srvsvc_ntvfs_ctx {
     
    6246        struct share_config *scfg;
    6347        const char *sharetype;
     48        union smb_tcon tcon;
     49        const struct tsocket_address *local_address;
     50        const struct tsocket_address *remote_address;
    6451
    65         status = share_get_context_by_name(mem_ctx, lp_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
     52        status = share_get_context_by_name(mem_ctx, lpcfg_share_backend(dce_call->conn->dce_ctx->lp_ctx), dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, &sctx);
    6653        if (!NT_STATUS_IS_OK(status)) {
    6754                return status;
     
    115102         * NOTE: we only set the addr callbacks as we're not interesseted in oplocks or in getting file handles
    116103         */
    117         status = ntvfs_set_addr_callbacks(c->ntvfs, srvsvc_get_my_addr, srvsvc_get_peer_addr, dce_call->conn);
     104        local_address = dcesrv_connection_get_local_address(dce_call->conn);
     105        remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
     106        status = ntvfs_set_addresses(c->ntvfs, local_address, remote_address);
    118107        if (!NT_STATUS_IS_OK(status)) {
    119108                DEBUG(0,("srvsvc_create_ntvfs_context: NTVFS failed to set the addr callbacks!\n"));
     
    129118
    130119        /* Invoke NTVFS connection hook */
    131         status = ntvfs_connect(ntvfs_req, scfg->name);
     120        tcon.tcon.level = RAW_TCON_TCON;
     121        ZERO_STRUCT(tcon.tcon.in);
     122        tcon.tcon.in.service = scfg->name;
     123        status = ntvfs_connect(ntvfs_req, &tcon);
    132124        if (!NT_STATUS_IS_OK(status)) {
    133125                DEBUG(0,("srvsvc_create_ntvfs_context: NTVFS ntvfs_connect() failed!\n"));
  • trunk/server/source4/rpc_server/unixinfo/dcesrv_unixinfo.c

    r414 r745  
    5050                                                dce_call->context->private_data,
    5151                                                struct wbc_context);
    52         struct id_mapping *ids;
     52        struct id_map *ids;
    5353        struct composite_context *ctx;
    5454
    5555        DEBUG(5, ("dcesrv_unixinfo_SidToUid called\n"));
    5656
    57         ids = talloc(mem_ctx, struct  id_mapping);
     57        ids = talloc(mem_ctx, struct id_map);
    5858        NT_STATUS_HAVE_NO_MEMORY(ids);
    5959
    6060        ids->sid = &r->in.sid;
    61         ids->status = NT_STATUS_NONE_MAPPED;
    62         ids->unixid = NULL;
     61        ids->status = ID_UNKNOWN;
     62        ZERO_STRUCT(ids->xid);
    6363        ctx = wbc_sids_to_xids_send(wbc_ctx, ids, 1, ids);
    6464        NT_STATUS_HAVE_NO_MEMORY(ctx);
     
    6767        NT_STATUS_NOT_OK_RETURN(status);
    6868
    69         if (ids->unixid->type == ID_TYPE_BOTH ||
    70             ids->unixid->type == ID_TYPE_UID) {
    71                 *r->out.uid = ids->unixid->id;
     69        if (ids->xid.type == ID_TYPE_BOTH ||
     70            ids->xid.type == ID_TYPE_UID) {
     71                *r->out.uid = ids->xid.id;
    7272                return NT_STATUS_OK;
    7373        } else {
     
    8383                                                dce_call->context->private_data,
    8484                                                struct wbc_context);
    85         struct id_mapping *ids;
     85        struct id_map *ids;
    8686        struct composite_context *ctx;
    8787        uint32_t uid;
     
    9696        }
    9797
    98         ids = talloc(mem_ctx, struct id_mapping);
     98        ids = talloc(mem_ctx, struct id_map);
    9999        NT_STATUS_HAVE_NO_MEMORY(ids);
    100100
    101101        ids->sid = NULL;
    102         ids->status = NT_STATUS_NONE_MAPPED;
    103         ids->unixid = talloc(ids, struct unixid);
    104         NT_STATUS_HAVE_NO_MEMORY(ids->unixid);
    105 
    106         ids->unixid->id = uid;
    107         ids->unixid->type = ID_TYPE_UID;
     102        ids->status = ID_UNKNOWN;
     103
     104        ids->xid.id = uid;
     105        ids->xid.type = ID_TYPE_UID;
    108106
    109107        ctx = wbc_xids_to_sids_send(wbc_ctx, ids, 1, ids);
     
    125123                                                dce_call->context->private_data,
    126124                                                struct wbc_context);
    127         struct id_mapping *ids;
     125        struct id_map *ids;
    128126        struct composite_context *ctx;
    129127
    130128        DEBUG(5, ("dcesrv_unixinfo_SidToGid called\n"));
    131129
    132         ids = talloc(mem_ctx, struct  id_mapping);
     130        ids = talloc(mem_ctx, struct id_map);
    133131        NT_STATUS_HAVE_NO_MEMORY(ids);
    134132
    135133        ids->sid = &r->in.sid;
    136         ids->status = NT_STATUS_NONE_MAPPED;
    137         ids->unixid = NULL;
     134        ids->status = ID_UNKNOWN;
     135        ZERO_STRUCT(ids->xid);
    138136        ctx = wbc_sids_to_xids_send(wbc_ctx, ids, 1, ids);
    139137        NT_STATUS_HAVE_NO_MEMORY(ctx);
     
    142140        NT_STATUS_NOT_OK_RETURN(status);
    143141
    144         if (ids->unixid->type == ID_TYPE_BOTH ||
    145             ids->unixid->type == ID_TYPE_GID) {
    146                 *r->out.gid = ids->unixid->id;
     142        if (ids->xid.type == ID_TYPE_BOTH ||
     143            ids->xid.type == ID_TYPE_GID) {
     144                *r->out.gid = ids->xid.id;
    147145                return NT_STATUS_OK;
    148146        } else {
     
    158156                                                dce_call->context->private_data,
    159157                                                struct wbc_context);
    160         struct id_mapping *ids;
     158        struct id_map *ids;
    161159        struct composite_context *ctx;
    162160        uint32_t gid;
     
    171169        }
    172170
    173         ids = talloc(mem_ctx, struct id_mapping);
     171        ids = talloc(mem_ctx, struct id_map);
    174172        NT_STATUS_HAVE_NO_MEMORY(ids);
    175173
    176174        ids->sid = NULL;
    177         ids->status = NT_STATUS_NONE_MAPPED;
    178         ids->unixid = talloc(ids, struct unixid);
    179         NT_STATUS_HAVE_NO_MEMORY(ids->unixid);
    180 
    181         ids->unixid->id = gid;
    182         ids->unixid->type = ID_TYPE_GID;
     175        ids->status = ID_UNKNOWN;
     176
     177        ids->xid.id = gid;
     178        ids->xid.type = ID_TYPE_GID;
    183179
    184180        ctx = wbc_xids_to_sids_send(wbc_ctx, ids, 1, ids);
     
    196192                                  struct unixinfo_GetPWUid *r)
    197193{
    198         int i;
     194        unsigned int i;
    199195
    200196        *r->out.count = 0;
  • trunk/server/source4/rpc_server/winreg/rpc_winreg.c

    r414 r745  
    2626#include "librpc/gen_ndr/ndr_winreg.h"
    2727#include "librpc/gen_ndr/ndr_security.h"
    28 #include "libcli/security/security.h"
     28#include "libcli/security/session.h"
    2929
    3030enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
     
    3737
    3838        err = reg_open_samba(dce_call->context,
    39                              &ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info,
     39                             &ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
     40                             dce_call->conn->auth_state.session_info,
    4041                             NULL);
    4142
     
    6162
    6263        h = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
     64        W_ERROR_HAVE_NO_MEMORY(h);
    6365
    6466        result = reg_get_predefined_key(ctx, hkey,
     
    98100        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
    99101
    100         talloc_free(h);
     102        talloc_unlink(dce_call->context, h);
    101103
    102104        ZERO_STRUCTP(r->out.handle);
     
    122124        newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
    123125
    124         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     126        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    125127        {
    126128        case SECURITY_SYSTEM:
    127129        case SECURITY_ADMINISTRATOR:
     130                /* we support only non volatile keys */
     131                if (r->in.options != REG_OPTION_NON_VOLATILE) {
     132                        return WERR_NOT_SUPPORTED;
     133                }
     134
    128135                /* the security descriptor is optional */
    129136                if (r->in.secdesc != NULL) {
     
    135142                                return WERR_INVALID_PARAM;
    136143                        }
    137                         ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd,
     144                        ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, &sd,
    138145                                                           (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
    139146                        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     
    144151                result = reg_key_add_name(newh, key, r->in.name.name, NULL,
    145152                        r->in.secdesc?&sd:NULL, (struct registry_key **)&newh->data);
     153
     154                r->out.action_taken = talloc(mem_ctx, enum winreg_CreateAction);
     155                if (r->out.action_taken == NULL) {
     156                        talloc_free(newh);
     157                        return WERR_NOMEM;
     158                }
     159                *r->out.action_taken = REG_ACTION_NONE;
     160
    146161                if (W_ERROR_IS_OK(result)) {
    147162                        r->out.new_handle = &newh->wire_handle;
     163                        *r->out.action_taken = REG_CREATED_NEW_KEY;
    148164                } else {
    149165                        talloc_free(newh);
    150166                }
    151                
     167
    152168                return result;
    153169        default:
     
    166182        struct dcesrv_handle *h;
    167183        struct registry_key *key;
    168 
    169         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
    170         key = h->data;
    171 
    172         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     184        WERROR result;
     185
     186        DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
     187        key = h->data;
     188
     189        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    173190        {
    174191        case SECURITY_SYSTEM:
    175192        case SECURITY_ADMINISTRATOR:
    176                 return reg_key_del(key, r->in.key.name);
     193                result = reg_key_del(mem_ctx, key, r->in.key.name);
     194                talloc_unlink(dce_call->context, h);
     195
     196                return result;
    177197        default:
    178198                return WERR_ACCESS_DENIED;
     
    194214        key = h->data;
    195215
    196         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     216        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    197217        {
    198218        case SECURITY_SYSTEM:
    199219        case SECURITY_ADMINISTRATOR:
    200                 return reg_del_value(key, r->in.value.name);
     220                return reg_del_value(mem_ctx, key, r->in.value.name);
    201221        default:
    202222                return WERR_ACCESS_DENIED;
     
    282302        }
    283303
    284         /* check if there is enough room for the name */
    285         if (r->in.name->size < 2*strlen_m_term(data_name)) {
    286                 return WERR_MORE_DATA;
    287         }
    288 
    289304        /* "data_name" is NULL when we query the default attribute */
    290305        if (data_name != NULL) {
     
    297312        r->out.name->size = r->in.name->size;
    298313
    299         r->out.type = talloc(mem_ctx, uint32_t);
     314        r->out.type = talloc(mem_ctx, enum winreg_Type);
    300315        if (!r->out.type) {
    301316                return WERR_NOMEM;
    302317        }
    303         *r->out.type = data_type;
     318        *r->out.type = (enum winreg_Type) data_type;
    304319
    305320        /* check the client has enough room for the value */
     
    337352        key = h->data;
    338353
    339         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     354        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    340355        {
    341356        case SECURITY_SYSTEM:
     
    399414        key = h->data;
    400415
    401         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     416        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    402417        {
    403418        case SECURITY_SYSTEM:
     
    422437                return WERR_ACCESS_DENIED;
    423438        }
    424 
    425439}
    426440
     
    441455        key = h->data;
    442456
    443         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     457        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    444458        {
    445459        case SECURITY_SYSTEM:
     
    451465                        r->out.max_valnamelen, r->out.max_valbufsize);
    452466
     467                if (r->out.max_subkeylen != NULL) {
     468                        /* for UTF16 encoding */
     469                        *r->out.max_subkeylen *= 2;
     470                }
     471                if (r->out.max_valnamelen != NULL) {
     472                        /* for UTF16 encoding */
     473                        *r->out.max_valnamelen *= 2;
     474                }
     475
    453476                if (classname != NULL) {
    454477                        r->out.classname->name = classname;
     
    483506        key = h->data;
    484507
    485         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     508        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    486509        {
    487510        case SECURITY_SYSTEM:
    488511        case SECURITY_ADMINISTRATOR:
    489512        case SECURITY_USER:
     513                if ((r->in.type == NULL) || (r->in.data_length == NULL) ||
     514                    (r->in.data_size == NULL)) {
     515                        return WERR_INVALID_PARAM;
     516                }
     517
    490518                result = reg_key_get_value_by_name(mem_ctx, key,
    491519                         r->in.value_name->name, &value_type, &value_data);
     
    496524                        value_data.data = r->in.data;
    497525                        value_data.length = *r->in.data_length;
    498                 }
    499 
    500                 r->out.type = talloc(mem_ctx, uint32_t);
     526                } else {
     527                        if ((r->in.data != NULL)
     528                            && (*r->in.data_size < value_data.length)) {
     529                                result = WERR_MORE_DATA;
     530                        }
     531                }
     532
     533                r->out.type = talloc(mem_ctx, enum winreg_Type);
    501534                if (!r->out.type) {
    502535                        return WERR_NOMEM;
    503536                }
    504                 *r->out.type = value_type;
     537                *r->out.type = (enum winreg_Type) value_type;
    505538                r->out.data_length = talloc(mem_ctx, uint32_t);
    506539                if (!r->out.data_length) {
     
    581614        key = h->data;
    582615
    583         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
     616        switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
    584617        {
    585618        case SECURITY_SYSTEM:
     
    691724}
    692725
     726/*
     727  winreg_DeleteKeyEx
     728*/
     729static WERROR dcesrv_winreg_DeleteKeyEx(struct dcesrv_call_state *dce_call,
     730                                        TALLOC_CTX *mem_ctx,
     731                                        struct winreg_DeleteKeyEx *r)
     732{
     733        return WERR_NOT_SUPPORTED;
     734}
    693735
    694736/* include the generated boilerplate */
  • trunk/server/source4/rpc_server/wkssvc/dcesrv_wkssvc.c

    r414 r745  
    2323#include "rpc_server/dcerpc_server.h"
    2424#include "librpc/gen_ndr/ndr_wkssvc.h"
     25#include "librpc/gen_ndr/ndr_srvsvc.h"
    2526#include "rpc_server/common/common.h"
     27#include "rpc_server/common/share.h"
    2628#include "param/param.h"
    2729
     
    3335{
    3436        struct dcesrv_context *dce_ctx = dce_call->conn->dce_ctx;
    35         struct dcerpc_server_info *server_info = lp_dcerpc_server_info(mem_ctx, dce_ctx->lp_ctx);
    36 
    37         ZERO_STRUCT(r->out);
    38         r->out.info = talloc_zero(mem_ctx, union wkssvc_NetWkstaInfo);
    39         W_ERROR_HAVE_NO_MEMORY(r->out.info);
     37        struct dcerpc_server_info *server_info = lpcfg_dcerpc_server_info(mem_ctx, dce_ctx->lp_ctx);
    4038
    4139        /* NOTE: win2k3 ignores r->in.server_name completly so we do --metze */
     
    5250                info100->server_name    = dcesrv_common_get_server_name(mem_ctx, dce_ctx, NULL);
    5351                W_ERROR_HAVE_NO_MEMORY(info100->server_name);
    54                 info100->domain_name    = talloc_reference(mem_ctx, server_info->domain_name);
    55                 W_ERROR_HAVE_NO_MEMORY(info100->domain_name);
     52                info100->domain_name    = server_info->domain_name;
    5653                info100->version_major  = server_info->version_major;
    5754                info100->version_minor  = server_info->version_minor;
     
    7067                info101->server_name    = dcesrv_common_get_server_name(mem_ctx, dce_ctx, NULL);
    7168                W_ERROR_HAVE_NO_MEMORY(info101->server_name);
    72                 info101->domain_name    = talloc_reference(mem_ctx, server_info->domain_name);
    73                 W_ERROR_HAVE_NO_MEMORY(info101->domain_name);
     69                info101->domain_name    = server_info->domain_name;
    7470                info101->version_major  = server_info->version_major;
    7571                info101->version_minor  = server_info->version_minor;
     
    9086                return WERR_UNKNOWN_LEVEL;
    9187        }
    92 
    93         return WERR_UNKNOWN_LEVEL;
    9488}
    9589
     
    141135                       struct wkssvc_NetWkstaTransportEnum *r)
    142136{
    143         r->out.total_entries = 0;
    144         r->out.resume_handle = NULL;
    145 
    146137        switch (r->in.info->level) {
    147138        case 0:
    148                 r->out.info = talloc(mem_ctx, struct wkssvc_NetWkstaTransportInfo);
    149                 W_ERROR_HAVE_NO_MEMORY(r->out.info);
    150                 r->out.info->level = r->in.info->level;
    151139                r->out.info->ctr.ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaTransportCtr0);
    152140                W_ERROR_HAVE_NO_MEMORY(r->out.info->ctr.ctr0);
     
    160148                return WERR_UNKNOWN_LEVEL;
    161149        }
    162 
    163         return WERR_UNKNOWN_LEVEL;
    164150}
    165151
Note: See TracChangeset for help on using the changeset viewer.