#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
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 */
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;
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 */
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;
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;
}
}
- 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;
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;
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;
/* 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);
}
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;
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;
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) {
}
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) {
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)
}
/*
- 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(),
&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)
{