s4:rpc_server: add dcesrv_call_auth_info()
[samba.git] / source4 / rpc_server / dcerpc_server.h
index d273f6eca996fdf632c2fd04c819afeaee4110d0..1ba676fecfa5127bb3c1e9e947c85271f0cff426 100644 (file)
@@ -44,7 +44,7 @@ struct dcesrv_interface {
        struct ndr_syntax_id syntax_id;
 
        /* this function is called when the client binds to this interface  */
-       NTSTATUS (*bind)(struct dcesrv_call_state *, const struct dcesrv_interface *);
+       NTSTATUS (*bind)(struct dcesrv_call_state *, const struct dcesrv_interface *, uint32_t if_version);
 
        /* this function is called when the client disconnects the endpoint */
        void (*unbind)(struct dcesrv_connection_context *, const struct dcesrv_interface *);
@@ -67,8 +67,12 @@ struct dcesrv_interface {
 
        /* for any private use by the interface code */
        const void *private_data;
+
+       uint64_t flags;
 };
 
+#define DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED 0x00000001
+
 enum dcesrv_call_list {
        DCESRV_LIST_NONE,
        DCESRV_LIST_CALL_LIST,
@@ -76,6 +80,11 @@ enum dcesrv_call_list {
        DCESRV_LIST_PENDING_CALL_LIST
 };
 
+struct data_blob_list_item {
+       struct data_blob_list_item *prev,*next;
+       DATA_BLOB blob;
+};
+
 /* the state of an ongoing dcerpc call */
 struct dcesrv_call_state {
        struct dcesrv_call_state *next, *prev;
@@ -83,6 +92,11 @@ struct dcesrv_call_state {
        struct dcesrv_connection_context *context;
        struct ncacn_packet pkt;
 
+       /*
+        * Used during async bind/alter_context.
+        */
+       struct ncacn_packet ack_pkt;
+
        /*
          which list this request is in, if any
         */
@@ -101,7 +115,8 @@ struct dcesrv_call_state {
         */
 #define DCESRV_CALL_STATE_FLAG_ASYNC (1<<0)
 #define DCESRV_CALL_STATE_FLAG_MAY_ASYNC (1<<1)
-#define DCESRV_CALL_STATE_FLAG_HEADER_SIGNING (1<<2)
+#define DCESRV_CALL_STATE_FLAG_MULTIPLEXED (1<<3)
+#define DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL (1<<4)
        uint32_t state_flags;
 
        /* the time the request arrived in the server */
@@ -111,7 +126,7 @@ struct dcesrv_call_state {
        struct tevent_context *event_ctx;
 
        /* the message_context that will be used for async replies */
-       struct messaging_context *msg_ctx;
+       struct imessaging_context *msg_ctx;
 
        /* this is the pointer to the allocated function struct */
        void *r;
@@ -129,8 +144,42 @@ struct dcesrv_call_state {
 
        /* this is used by the boilerplate code to generate DCERPC faults */
        uint32_t fault_code;
+
+       /* the reason why we terminate the connection after sending a response */
+       const char *terminate_reason;
+
+       /* temporary auth_info fields */
+       struct dcerpc_auth in_auth_info;
+       struct dcerpc_auth _out_auth_info;
+       struct dcerpc_auth *out_auth_info;
 };
 
+/*
+* DCERPC Handles
+* --------------
+* The various handles that are used in the RPC servers should be
+* created and fetch using the dcesrv_handle_* functions.
+*
+* Use
+* dcesrv_handle_create(struct dcesrv_call_state \*, uint8 handle_type)
+* to obtain a new handle of the specified type. Handle types are
+* unique within each pipe.
+*
+* The handle can later be fetched again using:
+*
+* struct dcesrv_handle *dcesrv_handle_lookup(
+*         struct dcesrv_call_state *dce_call,
+*         struct policy_handle *p,
+*         uint8 handle_type)
+*
+* and destroyed by:
+*
+*      TALLOC_FREE(struct dcesrv_handle *).
+*
+* User data should be stored in the 'data' member of the dcesrv_handle
+* struct.
+*/
+
 #define DCESRV_HANDLE_ANY 255
 
 /* a dcerpc handle in internal format */
@@ -145,17 +194,21 @@ struct dcesrv_handle {
 
 /* hold the authentication state information */
 struct dcesrv_auth {
-       struct dcerpc_auth *auth_info;
+       enum dcerpc_AuthType auth_type;
+       enum dcerpc_AuthLevel auth_level;
+       uint32_t auth_context_id;
        struct gensec_security *gensec_security;
        struct auth_session_info *session_info;
-       NTSTATUS (*session_key)(struct dcesrv_connection *, DATA_BLOB *session_key);
+       NTSTATUS (*session_key_fn)(struct dcesrv_auth *, DATA_BLOB *session_key);
+       bool client_hdr_signing;
+       bool hdr_signing;
+       bool auth_finished;
+       bool auth_invalid;
 };
 
 struct dcesrv_connection_context {
        struct dcesrv_connection_context *next, *prev;
-       uint32_t context_id;
-
-       struct dcesrv_assoc_group *assoc_group;
+       uint16_t context_id;
 
        /* the connection this is on */
        struct dcesrv_connection *conn;
@@ -165,11 +218,23 @@ struct dcesrv_connection_context {
 
        /* private data for the interface implementation */
        void *private_data;
+
+       /*
+        * the minimum required auth level for this interface
+        */
+       enum dcerpc_AuthLevel min_auth_level;
+       bool allow_connect;
+
+       /* the negotiated transfer syntax */
+       struct ndr_syntax_id transfer_syntax;
 };
 
 
 /* the state associated with a dcerpc server connection */
 struct dcesrv_connection {
+       /* for the broken_connections DLIST */
+       struct dcesrv_connection *prev, *next;
+
        /* the top level context for this server */
        struct dcesrv_context *dce_ctx;
 
@@ -189,26 +254,22 @@ struct dcesrv_connection {
        struct dcesrv_call_state *call_list;
 
        /* the maximum size the client wants to receive */
-       uint32_t cli_max_recv_frag;
+       uint16_t max_recv_frag;
+       uint16_t max_xmit_frag;
 
        DATA_BLOB partial_input;
 
-       /* the current authentication state */
-       struct dcesrv_auth auth_state;
-
        /* the event_context that will be used for this connection */
        struct tevent_context *event_ctx;
 
        /* the message_context that will be used for this connection */
-       struct messaging_context *msg_ctx;
+       struct imessaging_context *msg_ctx;
 
        /* the server_id that will be used for this connection */
        struct server_id server_id;
 
-       /* the transport level session key */
-       DATA_BLOB transport_session_key;
-
-       bool processing;
+       /* is this connection pending termination?  If so, why? */
+       const char *terminate;
 
        const char *packet_log_dir;
 
@@ -218,12 +279,48 @@ struct dcesrv_connection {
        struct {
                void *private_data;
                void (*report_output_data)(struct dcesrv_connection *);
-               struct socket_address *(*get_my_addr)(struct dcesrv_connection *, TALLOC_CTX *mem_ctx);
-               struct socket_address *(*get_peer_addr)(struct dcesrv_connection *, TALLOC_CTX *mem_ctx);
        } transport;
 
        struct tstream_context *stream;
        struct tevent_queue *send_queue;
+
+       const struct tsocket_address *local_address;
+       const struct tsocket_address *remote_address;
+
+       /* the current authentication state */
+       struct dcesrv_auth auth_state;
+
+       /*
+        * remember which pdu types are allowed
+        */
+       bool allow_bind;
+       bool allow_auth3;
+       bool allow_alter;
+       bool allow_request;
+
+       /* the association group the connection belongs to */
+       struct dcesrv_assoc_group *assoc_group;
+
+       /* The maximum total payload of reassembled request pdus */
+       size_t max_total_request_size;
+
+       /*
+        * Our preferred transfer syntax.
+        */
+       const struct ndr_syntax_id *preferred_transfer;
+
+       /* the negotiated bind time features */
+       uint16_t bind_time_features;
+
+       /*
+        * This is used to block the connection during
+        * pending authentication.
+        */
+       struct tevent_req *(*wait_send)(TALLOC_CTX *mem_ctx,
+                                       struct tevent_context *ev,
+                                       void *private_data);
+       NTSTATUS (*wait_recv)(struct tevent_req *req);
+       void *wait_private;
 };
 
 
@@ -260,10 +357,20 @@ struct dcesrv_assoc_group {
 
        /* parent context */
        struct dcesrv_context *dce_ctx;
+
+       /* Remote association group ID (if proxied) */
+       uint32_t proxied_id;
 };
 
 /* server-wide context information for the dcerpc server */
 struct dcesrv_context {
+       /*
+        * The euid at startup time.
+        *
+        * This is required for DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM
+        */
+       uid_t initial_euid;
+
        /* the list of endpoints that have registered 
         * by the configured endpoint servers 
         */
@@ -278,12 +385,20 @@ struct dcesrv_context {
                        struct dcesrv_if_list *next, *prev;
                        struct dcesrv_interface iface;
                } *interface_list;
+
+               /*
+                * Should this service be run in a single process (so far only
+                * NETLOGON is not run in a single process)
+                */
+               bool use_single_process;
        } *endpoint_list;
 
        /* loadparm context to use for this connection */
        struct loadparm_context *lp_ctx;
 
        struct idr_context *assoc_groups_idr;
+
+       struct dcesrv_connection *broken_connections;
 };
 
 /* this structure is used by modules to determine the size of some critical types */
@@ -306,33 +421,39 @@ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
                                   const char *ep_name,
                                   const struct dcesrv_interface *iface,
                                   const struct security_descriptor *sd);
-NTSTATUS dcerpc_register_ep_server(const void *_ep_server);
+NTSTATUS dcerpc_register_ep_server(const struct dcesrv_endpoint_server *ep_server);
 NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx, 
                                      struct loadparm_context *lp_ctx,
                                      const char **endpoint_servers, struct dcesrv_context **_dce_ctx);
-NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
-                                TALLOC_CTX *mem_ctx,
-                                const struct dcesrv_endpoint *ep,
-                                struct auth_session_info *session_info,
-                                struct tevent_context *event_ctx,
-                                struct messaging_context *msg_ctx,
-                                struct server_id server_id,
-                                uint32_t state_flags,
-                                struct dcesrv_connection **_p);
 
 NTSTATUS dcesrv_reply(struct dcesrv_call_state *call);
-struct dcesrv_handle *dcesrv_handle_new(struct dcesrv_connection_context *context, 
-                                       uint8_t handle_type);
+struct dcesrv_handle *dcesrv_handle_create(struct dcesrv_call_state *call,
+                                          uint8_t handle_type);
 
-struct dcesrv_handle *dcesrv_handle_fetch(
-                                         struct dcesrv_connection_context *context, 
-                                         struct policy_handle *p,
-                                         uint8_t handle_type);
-struct socket_address *dcesrv_connection_get_my_addr(struct dcesrv_connection *conn, TALLOC_CTX *mem_ctx);
+struct dcesrv_handle *dcesrv_handle_lookup(struct dcesrv_call_state *call,
+                                          const struct policy_handle *p,
+                                          uint8_t handle_type);
 
-struct socket_address *dcesrv_connection_get_peer_addr(struct dcesrv_connection *conn, TALLOC_CTX *mem_ctx);
+const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn);
+const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn);
 
-NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p, DATA_BLOB *session_key);
+/*
+ * Fetch the authentication session key if available.
+ *
+ * This is the key generated by a gensec authentication.
+ */
+NTSTATUS dcesrv_auth_session_key(struct dcesrv_call_state *call,
+                                DATA_BLOB *session_key);
+
+/*
+ * Fetch the transport session key if available.
+ * Typically this is the SMB session key
+ * or a fixed key for local transports.
+ *
+ * The key is always truncated to 16 bytes.
+*/
+NTSTATUS dcesrv_transport_session_key(struct dcesrv_call_state *call,
+                                     DATA_BLOB *session_key);
 
 /* a useful macro for generating a RPC fault in the backend code */
 #define DCESRV_FAULT(code) do { \
@@ -354,7 +475,7 @@ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p, DATA_BLOB *sessio
    invalid handle or retval if the handle is of the
    wrong type */
 #define DCESRV_PULL_HANDLE_RETVAL(h, inhandle, t, retval) do { \
-       (h) = dcesrv_handle_fetch(dce_call->context, (inhandle), DCESRV_HANDLE_ANY); \
+       (h) = dcesrv_handle_lookup(dce_call, (inhandle), DCESRV_HANDLE_ANY); \
        DCESRV_CHECK_HANDLE(h); \
        if ((t) != DCESRV_HANDLE_ANY && (h)->wire_handle.handle_type != (t)) { \
                return retval; \
@@ -364,13 +485,54 @@ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p, DATA_BLOB *sessio
 /* this checks for a valid policy handle and gives a dcerpc fault 
    if its the wrong type of handle */
 #define DCESRV_PULL_HANDLE_FAULT(h, inhandle, t) do { \
-       (h) = dcesrv_handle_fetch(dce_call->context, (inhandle), t); \
+       (h) = dcesrv_handle_lookup(dce_call, (inhandle), t); \
        DCESRV_CHECK_HANDLE(h); \
 } while (0)
 
 #define DCESRV_PULL_HANDLE(h, inhandle, t) DCESRV_PULL_HANDLE_RETVAL(h, inhandle, t, NT_STATUS_INVALID_HANDLE)
-#define DCESRV_PULL_HANDLE_WERR(h, inhandle, t) DCESRV_PULL_HANDLE_RETVAL(h, inhandle, t, WERR_BADFID)
+#define DCESRV_PULL_HANDLE_WERR(h, inhandle, t) DCESRV_PULL_HANDLE_RETVAL(h, inhandle, t, WERR_INVALID_HANDLE)
+
+NTSTATUS dcesrv_add_ep(struct dcesrv_context *dce_ctx,
+                      struct loadparm_context *lp_ctx,
+                      struct dcesrv_endpoint *e,
+                      struct tevent_context *event_ctx,
+                      const struct model_ops *model_ops,
+                      void *process_context);
+
+/**
+ * retrieve credentials from a dce_call
+ */
+_PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call);
+
+/**
+ * returns true if this is an authenticated call
+ */
+_PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call);
 
+/**
+ * retrieve account_name for a dce_call
+ */
+_PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call);
 
+/**
+ * retrieve session_info from a dce_call
+ */
+_PUBLIC_ struct auth_session_info *dcesrv_call_session_info(struct dcesrv_call_state *dce_call);
+
+/**
+ * retrieve auth type/level from a dce_call
+ */
+_PUBLIC_ void dcesrv_call_auth_info(struct dcesrv_call_state *dce_call,
+                                   enum dcerpc_AuthType *auth_type,
+                                   enum dcerpc_AuthLevel *auth_level);
+
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_call_state *dce_call,
+                                                         const struct dcesrv_interface *iface);
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_call_state *dce_call,
+                                                       const struct dcesrv_interface *iface);
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_call_state *dce_call,
+                                                      const struct dcesrv_interface *iface);
+_PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_call_state *dce_call,
+                                                     const struct dcesrv_interface *iface);
 
 #endif /* SAMBA_DCERPC_SERVER_H */