summaryrefslogtreecommitdiff
path: root/source4/wrepl_server/wrepl_in_call.c
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2005-10-14 12:44:47 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:41:30 -0500
commitd49e67f06f55054f23dbef609b4debb11c157ffa (patch)
treea52ff716f74cd2c2f3efd73e88f9d6465156e1f7 /source4/wrepl_server/wrepl_in_call.c
parentee49ed7a204753e0755f79304a2d4ac32f6e8fdf (diff)
downloadsamba-d49e67f06f55054f23dbef609b4debb11c157ffa.tar.gz
samba-d49e67f06f55054f23dbef609b4debb11c157ffa.tar.bz2
samba-d49e67f06f55054f23dbef609b4debb11c157ffa.zip
r11014: r10139@SERNOX: metze | 2005-09-10 10:32:36 +0200
- w2k just ignores invalid packets, so we do now - w2k only checks the assoc_ctx when the opcode has the sepcific obcode bit's set - terminate the connection, when getting a WREPL_STOP_ASSOCIATION packet - some more special error handling proper torture test for all this cases are following later metze (This used to be commit 42b69461aad3942dde361d61b950445dd39882aa)
Diffstat (limited to 'source4/wrepl_server/wrepl_in_call.c')
-rw-r--r--source4/wrepl_server/wrepl_in_call.c150
1 files changed, 123 insertions, 27 deletions
diff --git a/source4/wrepl_server/wrepl_in_call.c b/source4/wrepl_server/wrepl_in_call.c
index 444fda544b..9158b1a741 100644
--- a/source4/wrepl_server/wrepl_in_call.c
+++ b/source4/wrepl_server/wrepl_in_call.c
@@ -32,21 +32,96 @@
static NTSTATUS wreplsrv_in_start_association(struct wreplsrv_in_call *call)
{
- struct wrepl_stop *stop;
+ struct wrepl_start *start = &call->req_packet.message.start;
+ struct wrepl_start *start_reply = &call->rep_packet.message.start_reply;
+
+ if (call->req_packet.opcode & WREPL_OPCODE_BITS) {
+ /*
+ *if the assoc_ctx doesn't match ignore the packet
+ */
+ if ((call->req_packet.assoc_ctx != call->wreplconn->assoc_ctx.our_ctx)
+ && (call->req_packet.assoc_ctx != 0)) {
+ return ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ call->wreplconn->assoc_ctx.our_ctx = WREPLSRV_INVALID_ASSOC_CTX;
+ return NT_STATUS_OK;
+ }
- call->rep_packet.opcode = WREPL_OPCODE_BITS;
- call->rep_packet.assoc_ctx = 0;
- call->rep_packet.mess_type = WREPL_STOP_ASSOCIATION;
- stop = &call->rep_packet.message.stop;
- stop->reason = 4;
+ if (start->minor_version != 2 || start->major_version != 5) {
+ /* w2k terminate the connection if the versions doesn't match */
+ return NT_STATUS_UNKNOWN_REVISION;
+ }
+
+ call->wreplconn->assoc_ctx.stopped = False;
+ call->wreplconn->assoc_ctx.our_ctx = WREPLSRV_VALID_ASSOC_CTX;
+ call->wreplconn->assoc_ctx.peer_ctx = start->assoc_ctx;
+
+ call->rep_packet.mess_type = WREPL_START_ASSOCIATION_REPLY;
+ start_reply->assoc_ctx = call->wreplconn->assoc_ctx.our_ctx;
+ start_reply->minor_version = 2;
+ start_reply->major_version = 5;
return NT_STATUS_OK;
}
+static NTSTATUS wreplsrv_in_stop_assoc_ctx(struct wreplsrv_in_call *call)
+{
+ struct wrepl_stop *stop_out = &call->rep_packet.message.stop;
+
+ call->wreplconn->assoc_ctx.stopped = True;
+
+ call->rep_packet.mess_type = WREPL_STOP_ASSOCIATION;
+ stop_out->reason = 4;
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS wreplsrv_in_stop_association(struct wreplsrv_in_call *call)
+{
+ /*
+ * w2k only check the assoc_ctx if the opcode has the 0x00007800 bits are set
+ */
+ if (call->req_packet.opcode & WREPL_OPCODE_BITS) {
+ /*
+ *if the assoc_ctx doesn't match ignore the packet
+ */
+ if (call->req_packet.assoc_ctx != call->wreplconn->assoc_ctx.our_ctx) {
+ return ERROR_INVALID_PARAMETER;
+ }
+ /* when the opcode bits are set the connection should be directly terminated */
+ return NT_STATUS_CONNECTION_RESET;
+ }
+
+ if (call->wreplconn->assoc_ctx.stopped) {
+ /* this causes the connection to be directly terminated */
+ return NT_STATUS_CONNECTION_RESET;
+ }
+
+ /* this will cause to not receive packets anymore and terminate the connection if the reply is send */
+ call->wreplconn->terminate = True;
+ return wreplsrv_in_stop_assoc_ctx(call);
+}
+
static NTSTATUS wreplsrv_in_replication(struct wreplsrv_in_call *call)
{
struct wrepl_replication *repl_in = &call->req_packet.message.replication;
- struct wrepl_stop *stop_out;
+
+ /*
+ * w2k only check the assoc_ctx if the opcode has the 0x00007800 bits are set
+ */
+ if (call->req_packet.opcode & WREPL_OPCODE_BITS) {
+ /*
+ *if the assoc_ctx doesn't match ignore the packet
+ */
+ if (call->req_packet.assoc_ctx != call->wreplconn->assoc_ctx.our_ctx) {
+ return ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ if (!call->wreplconn->partner) {
+ return wreplsrv_in_stop_assoc_ctx(call);
+ }
switch (repl_in->command) {
case WREPL_REPL_TABLE_QUERY:
@@ -67,43 +142,64 @@ static NTSTATUS wreplsrv_in_replication(struct wreplsrv_in_call *call)
break;
}
- call->rep_packet.opcode = WREPL_OPCODE_BITS;
+ return ERROR_INVALID_PARAMETER;
+}
+
+static NTSTATUS wreplsrv_in_invalid_assoc_ctx(struct wreplsrv_in_call *call)
+{
+ struct wrepl_start *start = &call->rep_packet.message.start;
+
+ call->rep_packet.opcode = 0x00008583;
call->rep_packet.assoc_ctx = 0;
- call->rep_packet.mess_type = WREPL_STOP_ASSOCIATION;
- stop_out = &call->rep_packet.message.stop;
- stop_out->reason = 4;
+ call->rep_packet.mess_type = WREPL_START_ASSOCIATION;
+
+ start->assoc_ctx = 0x0000000a;
+ start->minor_version = 0x0001;
+ start->major_version = 0x0000;
+
+ call->rep_packet.padding = data_blob_talloc(call, NULL, 4);
+ memset(call->rep_packet.padding.data, '\0', call->rep_packet.padding.length);
return NT_STATUS_OK;
}
NTSTATUS wreplsrv_in_call(struct wreplsrv_in_call *call)
{
- struct wrepl_stop *stop_out;
+ NTSTATUS status;
- /* TODO: check opcode and assoc_ctx */
+ if (!(call->req_packet.opcode & WREPL_OPCODE_BITS)
+ && (call->wreplconn->assoc_ctx.our_ctx == WREPLSRV_INVALID_ASSOC_CTX)) {
+ return wreplsrv_in_invalid_assoc_ctx(call);
+ }
switch (call->req_packet.mess_type) {
case WREPL_START_ASSOCIATION:
- return wreplsrv_in_start_association(call);
-
- case WREPL_START_ASSOCIATION_REPLY:
- /* this is not valid here */
+ status = wreplsrv_in_start_association(call);
break;
+ case WREPL_START_ASSOCIATION_REPLY:
+ /* this is not valid here, so we ignore it */
+ return ERROR_INVALID_PARAMETER;
+
case WREPL_STOP_ASSOCIATION:
- /* this is not valid here */
+ status = wreplsrv_in_stop_association(call);
break;
case WREPL_REPLICATION:
- return wreplsrv_in_replication(call);
+ status = wreplsrv_in_replication(call);
+ break;
+ default:
+ /* everythingelse is also not valid here, so we ignore it */
+ return ERROR_INVALID_PARAMETER;
}
- call->rep_packet.opcode = WREPL_OPCODE_BITS;
- call->rep_packet.assoc_ctx = 0;
- call->rep_packet.mess_type = WREPL_STOP_ASSOCIATION;
- call->rep_packet.padding = data_blob(NULL, 0);
- stop_out = &call->rep_packet.message.stop;
- stop_out->reason = 4;
+ if (call->wreplconn->assoc_ctx.our_ctx == WREPLSRV_INVALID_ASSOC_CTX) {
+ return wreplsrv_in_invalid_assoc_ctx(call);
+ }
- return NT_STATUS_OK;
-}
+ if (NT_STATUS_IS_OK(status)) {
+ call->rep_packet.opcode = WREPL_OPCODE_BITS;
+ call->rep_packet.assoc_ctx = call->wreplconn->assoc_ctx.peer_ctx;
+ }
+ return status;
+}