r4618: - tidied up the alter_context client code a bit
authorAndrew Tridgell <tridge@samba.org>
Sun, 9 Jan 2005 11:32:12 +0000 (11:32 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:08:34 +0000 (13:08 -0500)
- there is no alter_nak or alter_ack packet, its all done in an
  alter_response

- auto-allocated the contex_ids

- tried to fix up the dcom code to work again with
  alter_context. Jelmer, please take a look :)
(This used to be commit dd1c54add8884376601f2f8a56c01bfb8add030c)

source4/include/nterr.h
source4/lib/dcom/common/main.c
source4/libcli/util/nterr.c
source4/librpc/idl/dcerpc.idl
source4/librpc/rpc/dcerpc.c
source4/librpc/rpc/dcerpc.h
source4/librpc/rpc/dcerpc_auth.c
source4/librpc/rpc/dcerpc_spnego.c
source4/librpc/rpc/dcerpc_util.c
source4/rpc_server/dcerpc_server.c
source4/torture/rpc/alter_context.c

index 9cf9e0f086e980774bd478b198913a7e3b33e46c..6680b7ecec27168d949b2a2bcbf55138063379eb 100644 (file)
 #define NT_STATUS_NOT_A_REPARSE_POINT NT_STATUS(0xC0000000 | 0x0275)
 #define NT_STATUS_NO_SUCH_JOB NT_STATUS(0xC0000000 | 0xEDE) /* scheduler */
 #define NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED NT_STATUS(0xC0000000 | 0x20004)
+#define NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX NT_STATUS(0xC0000000 | 0x20026)
 
 
 /* I use NT_STATUS_FOOBAR when I have no idea what error code to use -
index 02e1dea13980c38c7551a9ebcaf8d5c09b62dbfb..b9f6127c6c708090234f0c9efb73bd3ed0d40fb1 100644 (file)
@@ -341,41 +341,54 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const
        return WERR_OK;
 }
 
-NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p)
+NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **pp)
 {
        struct dcerpc_binding binding;
        struct GUID iid;
        HYPER_T oxid;
        NTSTATUS status;
        int i;
+       struct dcerpc_pipe *p;
+       TALLOC_CTX *tmp_ctx;
+       const char *uuid;
+
+       tmp_ctx = talloc_new(NULL);
 
-       *p = NULL;
+       p = iface->ox->pipe;
        
        oxid = iface->ox->oxid;
        iid = iface->interface->iid;
 
-#warning "dcerpc_alter needed"
-#if 0
-       if (iface->ox->pipe) {
-               if (!GUID_equal(&iface->ox->pipe->syntax.uuid, &iid)) {
+       uuid = GUID_string(tmp_ctx, &iid);
+       
+       if (p) {
+               if (!GUID_equal(&p->syntax.uuid, &iid)) {
+                       struct dcerpc_pipe *p2;
                        iface->ox->pipe->syntax.uuid = iid;
-                       status = dcerpc_alter(iface->ox->pipe, iface->ctx);
-                       if (NT_STATUS_IS_ERR(status)) {
-                               return status;
+                       status = dcerpc_secondary_context(p, &p2, uuid, 0);
+                       if (NT_STATUS_IS_OK(status)) {
+                               p = p2;
                        }
+               } else {
+                       p = talloc_reference(NULL, p);
                }
-               *p = iface->ox->pipe;
-               return NT_STATUS_OK;
+               *pp = p;
+               talloc_free(tmp_ctx);
+               return status;
        }
-#endif
+
        i = 0;
        do {
-               status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->ox->bindings.stringbindings[i]);
-               if (NT_STATUS_IS_ERR(status)) {
+               status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, 
+                                                          iface->ox->bindings.stringbindings[i]);
+               if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(1, ("Error parsing string binding"));
                } else {
                        binding.flags = iface->ctx->dcerpc_flags;
-                       status = dcerpc_pipe_connect_b(&iface->ox->pipe, &binding, GUID_string(iface->ctx, &iid) , 0.0, iface->ctx->domain, iface->ctx->user, iface->ctx->password);
+                       status = dcerpc_pipe_connect_b(&p, &binding, 
+                                                      uuid, 0.0, 
+                                                      iface->ctx->domain, iface->ctx->user, 
+                                                      iface->ctx->password);
                }
 
                i++;
@@ -383,12 +396,15 @@ NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p)
 
        if (NT_STATUS_IS_ERR(status)) {
                DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status)));
+               talloc_free(tmp_ctx);
                return status;
        }
 
        DEBUG(2, ("Successfully connected to OXID %llx\n", oxid));
        
-       *p = iface->ox->pipe;
+       *pp = p;
+       talloc_free(tmp_ctx);
+
        return NT_STATUS_OK;
 }
 
index d2d87eeb1cc73b84cc5fadd745548db30cbcdff8..9317f0e37aebd99d866a5a8a1fc41cd5d2637219 100644 (file)
@@ -537,6 +537,7 @@ static const nt_err_code_struct nt_errs[] =
        { "NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE },
         { "NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES },
        { "NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED", NT_STATUS_RPC_PROTSEQ_NOT_SUPPORTED },
+       { "NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX", NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX },
        { "STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES },
        { "STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED },
        { NULL, NT_STATUS(0) }
index d9ed119abdd3fb6e25074a991238465c77ac620d..d4fb026c8cc91cf41d535f3c05520e7ad5cfaf75 100644 (file)
@@ -160,7 +160,7 @@ interface dcerpc
                DCERPC_PKT_BIND_ACK    = 12,
                DCERPC_PKT_BIND_NAK    = 13,
                DCERPC_PKT_ALTER       = 14,
-               DCERPC_PKT_ALTER_ACK   = 15,
+               DCERPC_PKT_ALTER_RESP  = 15,
                DCERPC_PKT_AUTH3       = 16,
                DCERPC_PKT_SHUTDOWN    = 17,
                DCERPC_PKT_CO_CANCEL   = 18,
@@ -168,15 +168,15 @@ interface dcerpc
        } dcerpc_pkt_type;
 
        typedef [nodiscriminant] union {
-               [case(DCERPC_PKT_REQUEST)]   dcerpc_request  request;
-               [case(DCERPC_PKT_RESPONSE)]  dcerpc_response response;
-               [case(DCERPC_PKT_BIND)]      dcerpc_bind     bind;
-               [case(DCERPC_PKT_BIND_ACK)]  dcerpc_bind_ack bind_ack;
-               [case(DCERPC_PKT_ALTER)]     dcerpc_bind     alter;
-               [case(DCERPC_PKT_ALTER_ACK)] dcerpc_bind_ack alter_ack;
-               [case(DCERPC_PKT_FAULT)]     dcerpc_fault    fault;
-               [case(DCERPC_PKT_AUTH3)]     dcerpc_auth3    auth3;
-               [case(DCERPC_PKT_BIND_NAK)]  dcerpc_bind_nak bind_nak;
+               [case(DCERPC_PKT_REQUEST)]    dcerpc_request  request;
+               [case(DCERPC_PKT_RESPONSE)]   dcerpc_response response;
+               [case(DCERPC_PKT_BIND)]       dcerpc_bind     bind;
+               [case(DCERPC_PKT_BIND_ACK)]   dcerpc_bind_ack bind_ack;
+               [case(DCERPC_PKT_ALTER)]      dcerpc_bind     alter;
+               [case(DCERPC_PKT_ALTER_RESP)] dcerpc_bind_ack alter_resp;
+               [case(DCERPC_PKT_FAULT)]      dcerpc_fault    fault;
+               [case(DCERPC_PKT_AUTH3)]      dcerpc_auth3    auth3;
+               [case(DCERPC_PKT_BIND_NAK)]   dcerpc_bind_nak bind_nak;
        } dcerpc_payload;
 
 
index d75f6db935782e208e5d3eca3a3da982aed48710..e133c77d07f094f1f5d40ea3bb9c947673dd29d0 100644 (file)
@@ -562,6 +562,18 @@ static NTSTATUS full_request(struct dcerpc_connection *c,
        return state->status;
 }
 
+/*
+  map a bind nak reason to a NTSTATUS
+*/
+static NTSTATUS dcerpc_map_reason(uint16_t reason)
+{
+       switch (reason) {
+       case DCERPC_BIND_REASON_ASYNTAX:
+               return NT_STATUS_RPC_UNSUPPORTED_NAME_SYNTAX;
+       }
+       return NT_STATUS_UNSUCCESSFUL;
+}
+
 
 /* 
    perform a bind using the given syntax 
@@ -622,7 +634,7 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p,
 
        if (pkt.ptype == DCERPC_PKT_BIND_NAK) {
                DEBUG(2,("dcerpc: bind_nak reason %d\n", pkt.u.bind_nak.reject_reason));
-               return NT_STATUS_ACCESS_DENIED;
+               return dcerpc_map_reason(pkt.u.bind_nak.reject_reason);
        }
 
        if ((pkt.ptype != DCERPC_PKT_BIND_ACK) ||
@@ -1387,20 +1399,23 @@ NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p,
                return status;
        }
 
-       if (pkt.ptype == DCERPC_PKT_BIND_NAK) {
-               DEBUG(2,("dcerpc: alter_nak reason %d\n", pkt.u.bind_nak.reject_reason));
-               return NT_STATUS_ACCESS_DENIED;
+       if (pkt.ptype == DCERPC_PKT_ALTER_RESP &&
+           pkt.u.alter_resp.num_results == 1 &&
+           pkt.u.alter_resp.ctx_list[0].result != 0) {
+               DEBUG(2,("dcerpc: alter_resp failed - reason %d\n", 
+                        pkt.u.alter_resp.ctx_list[0].reason));
+               return dcerpc_map_reason(pkt.u.alter_resp.ctx_list[0].reason);
        }
 
-       if ((pkt.ptype != DCERPC_PKT_ALTER_ACK) ||
-           pkt.u.alter_ack.num_results == 0 ||
-           pkt.u.alter_ack.ctx_list[0].result != 0) {
+       if (pkt.ptype != DCERPC_PKT_ALTER_RESP ||
+           pkt.u.alter_resp.num_results == 0 ||
+           pkt.u.alter_resp.ctx_list[0].result != 0) {
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       /* the alter_ack might contain a reply set of credentials */
-       if (p->conn->security_state.auth_info && pkt.u.alter_ack.auth_info.length) {
-               status = ndr_pull_struct_blob(&pkt.u.alter_ack.auth_info,
+       /* the alter_resp might contain a reply set of credentials */
+       if (p->conn->security_state.auth_info && pkt.u.alter_resp.auth_info.length) {
+               status = ndr_pull_struct_blob(&pkt.u.alter_resp.auth_info,
                                              mem_ctx,
                                              p->conn->security_state.auth_info,
                                              (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
index 00f1fb6488615fd5b80a14396f86bd3bcdf2e6f2..f5ed637d0b8126892b7a17861685c17f2013b577 100644 (file)
@@ -76,6 +76,9 @@ struct dcerpc_connection {
 
        /* private pointer for pending full requests */
        void *full_request_private;
+
+       /* the next context_id to be assigned */
+       uint32_t next_context_id;
 };
 
 /*
index 9d43218e4b24c746ae22c75fef66d2b03d0b4d85..4ff8fe549eb5821035bef0b4cac7e378d39c13c2 100644 (file)
@@ -123,92 +123,3 @@ done:
 
        return status;
 }
-
-#warning "bind_alter not implemented"
-#if 0
-NTSTATUS dcerpc_bind_alter(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t auth_level,
-                         const char *uuid, uint_t version)
-{
-       NTSTATUS status;
-       TALLOC_CTX *mem_ctx;
-       DATA_BLOB credentials;
-       DATA_BLOB null_data_blob = data_blob(NULL, 0);
-
-       mem_ctx = talloc_init("dcerpc_bind_auth");
-       if (!mem_ctx) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       
-       if (!p->conn->security_state.generic_state) {
-               status = gensec_client_start(p, &p->conn->security_state.generic_state);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
-
-               status = gensec_start_mech_by_authtype(p->conn->security_state.generic_state, 
-                                                      auth_type, auth_level);
-
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
-       }
-
-       p->conn->security_state.auth_info = talloc_p(p, struct dcerpc_auth);
-       if (!p->conn->security_state.auth_info) {
-               status = NT_STATUS_NO_MEMORY;
-               goto done;
-       }
-
-       p->conn->security_state.auth_info->auth_type = auth_type;
-       p->conn->security_state.auth_info->auth_level = auth_level;
-       p->conn->security_state.auth_info->auth_pad_length = 0;
-       p->conn->security_state.auth_info->auth_reserved = 0;
-       p->conn->security_state.auth_info->auth_context_id = random();
-       p->conn->security_state.auth_info->credentials = null_data_blob;
-
-       status = gensec_update(p->conn->security_state.generic_state, mem_ctx,
-                              null_data_blob,
-                              &credentials);
-       
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-               goto done;
-       }
-
-       p->conn->security_state.auth_info->credentials = credentials;
-
-       status = dcerpc_bind_byuuid(p, mem_ctx, uuid, version);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto done;
-       }
-
-       while(1) {
-               status = gensec_update(p->conn->security_state.generic_state, mem_ctx,
-                              p->conn->security_state.auth_info->credentials,
-                              &credentials);
-
-               if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-                       goto done;
-               }
-
-               p->conn->security_state.auth_info->credentials = credentials;
-
-               status = dcerpc_alter(p, mem_ctx);
-               if (!NT_STATUS_IS_OK(status)) {
-                       goto done;
-               }
-       }
-
-done:
-       talloc_destroy(mem_ctx);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               talloc_free(p->conn->security_state.generic_state);
-               ZERO_STRUCT(p->conn->security_state);
-       } else {
-               /* Authenticated connections use the generic session key */
-               p->conn->security_state.session_key = dcerpc_generic_session_key;
-       }
-
-       return status;
-}
-#endif
index cab8865d6b818f74fa04056a165b2fb6c046a2f7..f67dd2c7cb5c7db5bc84176698e38e6cd265ac75 100644 (file)
 
 #include "includes.h"
 
-#warning "this needs dcerpc_alter"
 #if 0
+/*
+  metze, can you tell me what you're trying to do with this?
+*/
+
 /*
   do spnego style authentication on a gensec pipe
 */
index 702a1f6ecfc1d976071fbff1c1179b7846188df4..305c1c7725ba2d58f2478f011386bd8f7c4dc4a1 100644 (file)
@@ -1272,8 +1272,8 @@ void dcerpc_log_packet(const struct dcerpc_interface_table *ndr,
 
   this uses dcerpc_alter_context() to create a new dcerpc context_id
 */
-NTSTATUS dcerpc_secondary_context(struct dcerpc_pipe *p, struct dcerpc_pipe **pp2,
-                                 uint32_t context_id,
+NTSTATUS dcerpc_secondary_context(struct dcerpc_pipe *p, 
+                                 struct dcerpc_pipe **pp2,
                                  const char *pipe_uuid,
                                  uint32_t pipe_version)
 {
@@ -1286,7 +1286,7 @@ NTSTATUS dcerpc_secondary_context(struct dcerpc_pipe *p, struct dcerpc_pipe **pp
        }
        p2->conn = talloc_reference(p2, p->conn);
 
-       p2->context_id = context_id;
+       p2->context_id = ++p->conn->next_context_id;
 
        status = GUID_from_string(pipe_uuid, &p2->syntax.uuid);
        if (!NT_STATUS_IS_OK(status)) {
index f0791e592818f426f1239e67dd540b0ebd79ee07..c86ffb2cd038ca64ac530ce6dd2d46648a3dbf01 100644 (file)
@@ -580,22 +580,22 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
        dcesrv_init_hdr(&pkt);
        pkt.auth_length = 0;
        pkt.call_id = call->pkt.call_id;
-       pkt.ptype = DCERPC_PKT_ALTER_ACK;
+       pkt.ptype = DCERPC_PKT_ALTER_RESP;
        pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
-       pkt.u.alter_ack.max_xmit_frag = 0x2000;
-       pkt.u.alter_ack.max_recv_frag = 0x2000;
-       pkt.u.alter_ack.assoc_group_id = call->pkt.u.bind.assoc_group_id;
-       pkt.u.alter_ack.secondary_address = NULL;
-       pkt.u.alter_ack.num_results = 1;
-       pkt.u.alter_ack.ctx_list = talloc_p(call, struct dcerpc_ack_ctx);
-       if (!pkt.u.alter_ack.ctx_list) {
+       pkt.u.alter_resp.max_xmit_frag = 0x2000;
+       pkt.u.alter_resp.max_recv_frag = 0x2000;
+       pkt.u.alter_resp.assoc_group_id = call->pkt.u.bind.assoc_group_id;
+       pkt.u.alter_resp.secondary_address = NULL;
+       pkt.u.alter_resp.num_results = 1;
+       pkt.u.alter_resp.ctx_list = talloc_p(call, struct dcerpc_ack_ctx);
+       if (!pkt.u.alter_resp.ctx_list) {
                return NT_STATUS_NO_MEMORY;
        }
-       pkt.u.alter_ack.ctx_list[0].result = result;
-       pkt.u.alter_ack.ctx_list[0].reason = reason;
-       GUID_from_string(NDR_GUID, &pkt.u.alter_ack.ctx_list[0].syntax.uuid);
-       pkt.u.alter_ack.ctx_list[0].syntax.if_version = NDR_GUID_VERSION;
-       pkt.u.alter_ack.auth_info = data_blob(NULL, 0);
+       pkt.u.alter_resp.ctx_list[0].result = result;
+       pkt.u.alter_resp.ctx_list[0].reason = reason;
+       GUID_from_string(NDR_GUID, &pkt.u.alter_resp.ctx_list[0].syntax.uuid);
+       pkt.u.alter_resp.ctx_list[0].syntax.if_version = NDR_GUID_VERSION;
+       pkt.u.alter_resp.auth_info = data_blob(NULL, 0);
 
        if (!dcesrv_auth_alter_ack(call, &pkt)) {
                return dcesrv_bind_nak(call, 0);
index d10604fa04b8155df3de1ed4f6fd807a3f57528e..2c6f209404d44bd4515865cd19758a303876672b 100644 (file)
@@ -49,12 +49,19 @@ BOOL torture_rpc_alter_context(void)
        }
 
        printf("Opening secondary DSSETUP context\n");
-       status = dcerpc_secondary_context(p, &p2, 1, DCERPC_DSSETUP_UUID, DCERPC_DSSETUP_VERSION);
+       status = dcerpc_secondary_context(p, &p2, DCERPC_DSSETUP_UUID, DCERPC_DSSETUP_VERSION);
        if (!NT_STATUS_IS_OK(status)) {
                printf("dcerpc_alter_context failed - %s\n", nt_errstr(status));
                return False;
        }
 
+       printf("Opening bad secondary connection\n");
+       status = dcerpc_secondary_context(p, &p2, DCERPC_DSSETUP_UUID, DCERPC_DSSETUP_VERSION+100);
+       if (NT_STATUS_IS_OK(status)) {
+               printf("dcerpc_alter_context with wrong version should fail\n");
+               return False;
+       }
+
        printf("testing DSSETUP pipe operations\n");
        ret &= test_DsRoleGetPrimaryDomainInformation(p2, mem_ctx);