p->msg_ctx = msg_ctx;
p->server_id = server_id;
p->state_flags = state_flags;
+ p->allow_bind = true;
p->max_recv_frag = 5840;
p->max_xmit_frag = 5840;
return;
}
+ call->conn->allow_bind = false;
+ call->conn->allow_alter = false;
+ call->conn->allow_auth3 = false;
+ call->conn->allow_request = false;
+
call->terminate_reason = talloc_strdup(call, reason);
if (call->terminate_reason == NULL) {
call->terminate_reason = __location__;
{
NTSTATUS status;
+ if (!call->conn->allow_auth3) {
+ return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+ }
+
status = dcerpc_verify_ncacn_packet_header(&call->pkt,
DCERPC_PKT_AUTH3,
call->pkt.u.auth3.auth_info.length,
NTSTATUS status;
uint32_t context_id;
+ if (!call->conn->allow_alter) {
+ return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+ }
+
status = dcerpc_verify_ncacn_packet_header(&call->pkt,
DCERPC_PKT_ALTER,
call->pkt.u.alter.auth_info.length,
NTSTATUS status;
struct dcesrv_connection_context *context;
+ if (!call->conn->allow_request) {
+ return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
+ }
+
/* if authenticated, and the mech we use can't do async replies, don't use them... */
if (call->conn->auth_state.gensec_security &&
!gensec_have_feature(call->conn->auth_state.gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
talloc_set_destructor(call, dcesrv_call_dequeue);
+ if (call->conn->allow_bind) {
+ /*
+ * Only one bind is possible per connection
+ */
+ call->conn->allow_bind = false;
+ return dcesrv_bind(call);
+ }
+
/* we have to check the signing here, before combining the
pdus */
if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
+ if (!call->conn->allow_request) {
+ return dcesrv_fault_disconnect(call,
+ DCERPC_NCA_S_PROTO_ERROR);
+ }
+
status = dcerpc_verify_ncacn_packet_header(&call->pkt,
DCERPC_PKT_REQUEST,
call->pkt.u.request.stub_and_verifier.length,
switch (call->pkt.ptype) {
case DCERPC_PKT_BIND:
- status = dcesrv_bind(call);
+ status = dcesrv_bind_nak(call,
+ DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
break;
case DCERPC_PKT_AUTH3:
status = dcesrv_auth3(call);
status = dcesrv_request(call);
break;
default:
- status = NT_STATUS_INVALID_PARAMETER;
+ status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
break;
}
srv_conn = talloc_get_type(dce_conn->transport.private_data,
struct stream_connection);
+ dce_conn->allow_bind = false;
+ dce_conn->allow_auth3 = false;
+ dce_conn->allow_alter = false;
+ dce_conn->allow_request = false;
+
if (dce_conn->pending_call_list == NULL) {
char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
NTSTATUS status;
bool want_header_signing = false;
+ dce_conn->allow_alter = true;
+ dce_conn->allow_auth3 = true;
+
if (call->pkt.auth_length == 0) {
+ dce_conn->allow_request = true;
return NT_STATUS_OK;
}
DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));
return status;
}
+ dce_conn->allow_request = true;
if (!gensec_have_feature(dce_conn->auth_state.gensec_security,
GENSEC_FEATURE_SIGN_PKT_HEADER))
DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));
return false;
}
+ dce_conn->allow_request = true;
+
/* Now that we are authenticated, go back to the generic session key... */
dce_conn->auth_state.session_key = dcesrv_generic_session_key;
return true;
DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status)));
return status;
}
+ dce_conn->allow_request = true;
/* Now that we are authenticated, got back to the generic session key... */
dce_conn->auth_state.session_key = dcesrv_generic_session_key;
uint32_t auth_length;
size_t hdr_size = DCERPC_REQUEST_LENGTH;
+ if (!dce_conn->allow_request) {
+ return false;
+ }
+
if (!dce_conn->auth_state.auth_info ||
!dce_conn->auth_state.gensec_security) {
if (pkt->auth_length != 0) {