r11289: Fix comment.
[bbaumbach/samba-autobuild/.git] / source4 / rpc_server / dcerpc_server.c
index 87f8c9a42100e5b97ac7ae78bbb9b5e9893e274b..17a097a4cc63a0203fae48ce7f22542402185c52 100644 (file)
 
 #include "includes.h"
 #include "librpc/gen_ndr/ndr_epmapper.h"
+#include "librpc/gen_ndr/ndr_dcerpc.h"
 #include "librpc/gen_ndr/ndr_oxidresolver.h"
 #include "auth/auth.h"
 #include "dlinklist.h"
 #include "rpc_server/dcerpc_server.h"
 #include "lib/events/events.h"
 #include "smbd/service_stream.h"
+#include "system/filesys.h"
 
 /*
   see if two endpoints match
@@ -384,7 +386,7 @@ static void dcesrv_init_hdr(struct ncacn_packet *pkt)
 static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code)
 {
        struct ncacn_packet pkt;
-       struct dcesrv_call_reply *rep;
+       struct data_blob_list_item *rep;
        NTSTATUS status;
 
        /* setup a bind_ack */
@@ -398,19 +400,19 @@ static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code
        pkt.u.fault.cancel_count = 0;
        pkt.u.fault.status = fault_code;
 
-       rep = talloc(call, struct dcesrv_call_reply);
+       rep = talloc(call, struct data_blob_list_item);
        if (!rep) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = ncacn_push_auth(&rep->data, call, &pkt, NULL);
+       status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       dcerpc_set_frag_length(&rep->data, rep->data.length);
+       dcerpc_set_frag_length(&rep->blob, rep->blob.length);
 
-       DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
+       DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
        DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
 
        return NT_STATUS_OK;    
@@ -423,7 +425,7 @@ static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code
 static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
 {
        struct ncacn_packet pkt;
-       struct dcesrv_call_reply *rep;
+       struct data_blob_list_item *rep;
        NTSTATUS status;
 
        /* setup a bind_nak */
@@ -435,19 +437,19 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
        pkt.u.bind_nak.reject_reason = reason;
        pkt.u.bind_nak.num_versions = 0;
 
-       rep = talloc(call, struct dcesrv_call_reply);
+       rep = talloc(call, struct data_blob_list_item);
        if (!rep) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = ncacn_push_auth(&rep->data, call, &pkt, NULL);
+       status = ncacn_push_auth(&rep->blob, call, &pkt, NULL);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       dcerpc_set_frag_length(&rep->data, rep->data.length);
+       dcerpc_set_frag_length(&rep->blob, rep->blob.length);
 
-       DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
+       DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
        DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
 
        return NT_STATUS_OK;    
@@ -462,7 +464,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        const char *uuid, *transfer_syntax;
        uint32_t if_version, transfer_syntax_version;
        struct ncacn_packet pkt;
-       struct dcesrv_call_reply *rep;
+       struct data_blob_list_item *rep;
        NTSTATUS status;
        uint32_t result=0, reason=0;
        uint32_t context_id;
@@ -570,20 +572,20 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
                }
        }
 
-       rep = talloc(call, struct dcesrv_call_reply);
+       rep = talloc(call, struct data_blob_list_item);
        if (!rep) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = ncacn_push_auth(&rep->data, call, &pkt, 
+       status = ncacn_push_auth(&rep->blob, call, &pkt, 
                                  call->conn->auth_state.auth_info);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       dcerpc_set_frag_length(&rep->data, rep->data.length);
+       dcerpc_set_frag_length(&rep->blob, rep->blob.length);
 
-       DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
+       DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
        DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
 
        return NT_STATUS_OK;
@@ -663,7 +665,7 @@ static NTSTATUS dcesrv_alter_new_context(struct dcesrv_call_state *call, uint32_
 static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
 {
        struct ncacn_packet pkt;
-       struct dcesrv_call_reply *rep;
+       struct data_blob_list_item *rep;
        NTSTATUS status;
        uint32_t result=0, reason=0;
        uint32_t context_id;
@@ -712,20 +714,20 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
                return dcesrv_bind_nak(call, 0);
        }
 
-       rep = talloc(call, struct dcesrv_call_reply);
+       rep = talloc(call, struct data_blob_list_item);
        if (!rep) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       status = ncacn_push_auth(&rep->data, call, &pkt, 
+       status = ncacn_push_auth(&rep->blob, call, &pkt, 
                                  call->conn->auth_state.auth_info);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       dcerpc_set_frag_length(&rep->data, rep->data.length);
+       dcerpc_set_frag_length(&rep->blob, rep->blob.length);
 
-       DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
+       DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
        DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
 
        return NT_STATUS_OK;
@@ -787,6 +789,10 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
        /* call the dispatch function */
        status = context->iface->dispatch(call, call, call->r);
        if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
+                        context->iface->name, 
+                        call->pkt.u.request.opnum,
+                        dcerpc_errstr(pull, call->fault_code)));
                return dcesrv_fault(call, call->fault_code);
        }
 
@@ -838,10 +844,10 @@ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
 
        do {
                uint32_t length;
-               struct dcesrv_call_reply *rep;
+               struct data_blob_list_item *rep;
                struct ncacn_packet pkt;
 
-               rep = talloc(call, struct dcesrv_call_reply);
+               rep = talloc(call, struct data_blob_list_item);
                NT_STATUS_HAVE_NO_MEMORY(rep);
 
                length = stub.length;
@@ -869,13 +875,13 @@ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
                pkt.u.response.stub_and_verifier.data = stub.data;
                pkt.u.response.stub_and_verifier.length = length;
 
-               if (!dcesrv_auth_response(call, &rep->data, &pkt)) {
+               if (!dcesrv_auth_response(call, &rep->blob, &pkt)) {
                        return dcesrv_fault(call, DCERPC_FAULT_OTHER);          
                }
 
-               dcerpc_set_frag_length(&rep->data, rep->data.length);
+               dcerpc_set_frag_length(&rep->blob, rep->blob.length);
 
-               DLIST_ADD_END(call->replies, rep, struct dcesrv_call_reply *);
+               DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
                
                stub.data += length;
                stub.length -= length;
@@ -1100,20 +1106,19 @@ NTSTATUS dcesrv_input(struct dcesrv_connection *dce_conn, const DATA_BLOB *data)
 
   The first argument to write_fn() will be 'private', the second will
   be a pointer to a buffer containing the data to be sent and the 3rd
-  will be the number of bytes to be sent.
+  will be a pointer to a size_t variable that will be set to the
+  number of bytes that are consumed from the output.
 
-  write_fn() should return the number of bytes successfully written.
-
-  this will return STATUS_BUFFER_OVERFLOW if there is more to be written
   from the current fragment
 */
 NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn, 
-                      void *private,
-                      ssize_t (*write_fn)(void *, DATA_BLOB *))
+                      void *private_data,
+                      NTSTATUS (*write_fn)(void *private_data, DATA_BLOB *output, size_t *nwritten))
 {
+       NTSTATUS status;
        struct dcesrv_call_state *call;
-       struct dcesrv_call_reply *rep;
-       ssize_t nwritten;
+       struct data_blob_list_item *rep;
+       size_t nwritten;
 
        call = dce_conn->call_list;
        if (!call || !call->replies) {
@@ -1128,21 +1133,15 @@ NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn,
        }
        rep = call->replies;
 
-       nwritten = write_fn(private, &rep->data);
-       if (nwritten == -1) {
-               /* TODO: hmm, how do we cope with this? destroy the
-                  connection perhaps? */
-               return NT_STATUS_UNSUCCESSFUL;
-       }
+       status = write_fn(private_data, &rep->blob, &nwritten);
+       NT_STATUS_IS_ERR_RETURN(status);
 
-       rep->data.length -= nwritten;
-       rep->data.data += nwritten;
+       rep->blob.length -= nwritten;
+       rep->blob.data += nwritten;
 
-       if (rep->data.length == 0) {
+       if (rep->blob.length == 0) {
                /* we're done with this section of the call */
                DLIST_REMOVE(call->replies, rep);
-       } else {
-               return STATUS_BUFFER_OVERFLOW;
        }
 
        if (call->replies == NULL) {
@@ -1151,31 +1150,7 @@ NTSTATUS dcesrv_output(struct dcesrv_connection *dce_conn,
                talloc_free(call);
        }
 
-       return NT_STATUS_OK;
-}
-
-
-/*
-  write_fn() for dcesrv_output_blob()
-*/
-static ssize_t dcesrv_output_blob_write_fn(void *private, DATA_BLOB *out)
-{
-       DATA_BLOB *blob = private;
-       if (out->length < blob->length) {
-               blob->length = out->length;
-       }
-       memcpy(blob->data, out->data, blob->length);
-       return blob->length;
-}
-
-/*
-  a simple wrapper for dcesrv_output() for when we want to output
-  into a data blob
-*/
-NTSTATUS dcesrv_output_blob(struct dcesrv_connection *dce_conn, 
-                           DATA_BLOB *blob)
-{
-       return dcesrv_output(dce_conn, blob, dcesrv_output_blob_write_fn);
+       return status;
 }
 
 static NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, const char **endpoint_servers, uint32_t state_flags, struct dcesrv_context **_dce_ctx)
@@ -1312,12 +1287,13 @@ const struct dcesrv_critical_sizes *dcerpc_module_version(void)
 }
 
 /*
-  initialise the dcerpc server context for socket based services
+  initialise the dcerpc server context 
 */
 static NTSTATUS dcesrv_init(struct event_context *event_context, const struct model_ops *model_ops)
 {
        NTSTATUS status;
        struct dcesrv_context *dce_ctx;
+       struct dcesrv_endpoint *e;
 
        status = dcesrv_init_context(event_context,
                                     lp_dcerpc_endpoint_servers(),
@@ -1325,9 +1301,40 @@ static NTSTATUS dcesrv_init(struct event_context *event_context, const struct mo
                                     &dce_ctx);
        NT_STATUS_NOT_OK_RETURN(status);
 
-       return dcesrv_sock_init(dce_ctx, event_context, model_ops);
-}
+       /* Make sure the directory for NCALRPC exists */
+       if (!directory_exist(lp_ncalrpc_dir())) {
+               mkdir(lp_ncalrpc_dir(), 0755);
+       }
 
+       for (e=dce_ctx->endpoint_list;e;e=e->next) {
+               switch (e->ep_description->transport) {
+               case NCACN_UNIX_STREAM:
+                       status = dcesrv_add_ep_unix(dce_ctx, e, event_context, model_ops);
+                       NT_STATUS_NOT_OK_RETURN(status);
+                       break;
+               
+               case NCALRPC:
+                       status = dcesrv_add_ep_ncalrpc(dce_ctx, e, event_context, model_ops);
+                       NT_STATUS_NOT_OK_RETURN(status);
+                       break;
+
+               case NCACN_IP_TCP:
+                       status = dcesrv_add_ep_tcp(dce_ctx, e, event_context, model_ops);
+                       NT_STATUS_NOT_OK_RETURN(status);
+                       break;
+                       
+               case NCACN_NP:
+/*                     FIXME: status = dcesrv_add_ep_np(dce_ctx, e, event_context, model_ops);
+                       NT_STATUS_NOT_OK_RETURN(status); */
+                       break;
+
+               default:
+                       return NT_STATUS_NOT_SUPPORTED;
+               }
+       }
+
+       return NT_STATUS_OK;    
+}
 
 NTSTATUS server_service_rpc_init(void)
 {