diff options
author | Stefan Metzmacher <metze@samba.org> | 2005-10-14 12:44:47 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:41:30 -0500 |
commit | d49e67f06f55054f23dbef609b4debb11c157ffa (patch) | |
tree | a52ff716f74cd2c2f3efd73e88f9d6465156e1f7 /source4/wrepl_server/wrepl_in_call.c | |
parent | ee49ed7a204753e0755f79304a2d4ac32f6e8fdf (diff) | |
download | samba-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.c | 150 |
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; +} |