mirror of
https://github.com/samba-team/samba.git
synced 2025-02-03 13:47:25 +03:00
r10766: - make it possible to mark a wrepl_request as send only,
used for WREPL_REPL_INFORM* messsages - make it possible to close the connection after a request was send used for WREPL_ASSOCIATION_STOP - fix the torture test that tests the assoc context handling between connections, you can issue a request and get the reply on another connection, I think we should not implement that in our server code, as I think it's a security hole, you can cause a windows server to send the replies to someone another client, that doesn't wait for data, and as there're no massage_id in the protocol the client would be confused by a replies that doesn't belong to a query metze (This used to be commit dfc95de8fa7ded8ea92cafe58cf86efcc7920156)
This commit is contained in:
parent
093a30d7ed
commit
6799fde75d
@ -268,6 +268,7 @@ struct ads_struct;
|
|||||||
|
|
||||||
struct wrepl_packet;
|
struct wrepl_packet;
|
||||||
struct wrepl_associate;
|
struct wrepl_associate;
|
||||||
|
struct wrepl_associate_stop;
|
||||||
struct wrepl_pull_table;
|
struct wrepl_pull_table;
|
||||||
struct wrepl_pull_names;
|
struct wrepl_pull_names;
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
static void wrepl_socket_dead(struct wrepl_socket *wrepl_socket, NTSTATUS status)
|
static void wrepl_socket_dead(struct wrepl_socket *wrepl_socket, NTSTATUS status)
|
||||||
{
|
{
|
||||||
|
talloc_set_destructor(wrepl_socket, NULL);
|
||||||
wrepl_socket->dead = True;
|
wrepl_socket->dead = True;
|
||||||
|
|
||||||
if (wrepl_socket->fde) {
|
if (wrepl_socket->fde) {
|
||||||
@ -96,9 +97,31 @@ static void wrepl_handler_send(struct wrepl_socket *wrepl_socket)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req->disconnect_after_send) {
|
||||||
|
DLIST_REMOVE(wrepl_socket->send_queue, req);
|
||||||
|
req->status = NT_STATUS_OK;
|
||||||
|
req->state = WREPL_REQUEST_DONE;
|
||||||
|
wrepl_socket_dead(wrepl_socket, NT_STATUS_LOCAL_DISCONNECT);
|
||||||
|
if (req->async.fn) {
|
||||||
|
req->async.fn(req);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->send_only) {
|
||||||
|
DLIST_REMOVE(wrepl_socket->send_queue, req);
|
||||||
|
req->status = NT_STATUS_OK;
|
||||||
|
req->state = WREPL_REQUEST_DONE;
|
||||||
|
if (req->async.fn) {
|
||||||
|
EVENT_FD_READABLE(wrepl_socket->fde);
|
||||||
|
req->async.fn(req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
DLIST_REMOVE(wrepl_socket->send_queue, req);
|
DLIST_REMOVE(wrepl_socket->send_queue, req);
|
||||||
DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *);
|
DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *);
|
||||||
req->state = WREPL_REQUEST_RECV;
|
req->state = WREPL_REQUEST_RECV;
|
||||||
|
}
|
||||||
|
|
||||||
EVENT_FD_READABLE(wrepl_socket->fde);
|
EVENT_FD_READABLE(wrepl_socket->fde);
|
||||||
}
|
}
|
||||||
@ -289,7 +312,7 @@ failed:
|
|||||||
static int wrepl_socket_destructor(void *ptr)
|
static int wrepl_socket_destructor(void *ptr)
|
||||||
{
|
{
|
||||||
struct wrepl_socket *sock = talloc_get_type(ptr, struct wrepl_socket);
|
struct wrepl_socket *sock = talloc_get_type(ptr, struct wrepl_socket);
|
||||||
wrepl_socket_dead(sock, NT_STATUS_CONNECTION_DISCONNECTED);
|
wrepl_socket_dead(sock, NT_STATUS_LOCAL_DISCONNECT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +438,7 @@ static NTSTATUS wrepl_request_wait(struct wrepl_request *req)
|
|||||||
connect a wrepl_socket to a WINS server
|
connect a wrepl_socket to a WINS server
|
||||||
*/
|
*/
|
||||||
struct wrepl_request *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
|
struct wrepl_request *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
|
||||||
const char *address)
|
const char *our_ip, const char *peer_ip)
|
||||||
{
|
{
|
||||||
struct wrepl_request *req;
|
struct wrepl_request *req;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
@ -430,7 +453,11 @@ struct wrepl_request *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
|
|||||||
|
|
||||||
talloc_set_destructor(req, wrepl_request_destructor);
|
talloc_set_destructor(req, wrepl_request_destructor);
|
||||||
|
|
||||||
status = socket_connect(wrepl_socket->sock, iface_best_ip(address), 0, address,
|
if (!our_ip) {
|
||||||
|
our_ip = iface_best_ip(peer_ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = socket_connect(wrepl_socket->sock, our_ip, 0, peer_ip,
|
||||||
WINS_REPLICATION_PORT, 0);
|
WINS_REPLICATION_PORT, 0);
|
||||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) goto failed;
|
if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) goto failed;
|
||||||
|
|
||||||
@ -453,9 +480,9 @@ NTSTATUS wrepl_connect_recv(struct wrepl_request *req)
|
|||||||
/*
|
/*
|
||||||
connect a wrepl_socket to a WINS server - sync API
|
connect a wrepl_socket to a WINS server - sync API
|
||||||
*/
|
*/
|
||||||
NTSTATUS wrepl_connect(struct wrepl_socket *wrepl_socket, const char *address)
|
NTSTATUS wrepl_connect(struct wrepl_socket *wrepl_socket, const char *our_ip, const char *peer_ip)
|
||||||
{
|
{
|
||||||
struct wrepl_request *req = wrepl_connect_send(wrepl_socket, address);
|
struct wrepl_request *req = wrepl_connect_send(wrepl_socket, our_ip, peer_ip);
|
||||||
return wrepl_connect_recv(req);
|
return wrepl_connect_recv(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,6 +645,59 @@ NTSTATUS wrepl_associate(struct wrepl_socket *wrepl_socket,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
stop an association - send
|
||||||
|
*/
|
||||||
|
struct wrepl_request *wrepl_associate_stop_send(struct wrepl_socket *wrepl_socket,
|
||||||
|
struct wrepl_associate_stop *io)
|
||||||
|
{
|
||||||
|
struct wrepl_packet *packet;
|
||||||
|
struct wrepl_request *req;
|
||||||
|
|
||||||
|
packet = talloc_zero(wrepl_socket, struct wrepl_packet);
|
||||||
|
if (packet == NULL) return NULL;
|
||||||
|
|
||||||
|
packet->opcode = WREPL_OPCODE_BITS;
|
||||||
|
packet->assoc_ctx = io->in.assoc_ctx;
|
||||||
|
packet->mess_type = WREPL_STOP_ASSOCIATION;
|
||||||
|
packet->message.stop.reason = io->in.reason;
|
||||||
|
|
||||||
|
req = wrepl_request_send(wrepl_socket, packet);
|
||||||
|
|
||||||
|
if (req && io->in.reason == 0) {
|
||||||
|
req->send_only = True;
|
||||||
|
req->disconnect_after_send = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
talloc_free(packet);
|
||||||
|
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
stop an association - recv
|
||||||
|
*/
|
||||||
|
NTSTATUS wrepl_associate_stop_recv(struct wrepl_request *req,
|
||||||
|
struct wrepl_associate_stop *io)
|
||||||
|
{
|
||||||
|
struct wrepl_packet *packet=NULL;
|
||||||
|
NTSTATUS status;
|
||||||
|
status = wrepl_request_recv(req, req->wrepl_socket, &packet);
|
||||||
|
NT_STATUS_NOT_OK_RETURN(status);
|
||||||
|
talloc_free(packet);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
setup an association - sync api
|
||||||
|
*/
|
||||||
|
NTSTATUS wrepl_associate_stop(struct wrepl_socket *wrepl_socket,
|
||||||
|
struct wrepl_associate_stop *io)
|
||||||
|
{
|
||||||
|
struct wrepl_request *req = wrepl_associate_stop_send(wrepl_socket, io);
|
||||||
|
return wrepl_associate_stop_recv(req, io);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fetch the partner tables - send
|
fetch the partner tables - send
|
||||||
*/
|
*/
|
||||||
@ -735,8 +815,6 @@ NTSTATUS wrepl_pull_names_recv(struct wrepl_request *req,
|
|||||||
|
|
||||||
io->out.num_names = packet->message.replication.info.reply.num_names;
|
io->out.num_names = packet->message.replication.info.reply.num_names;
|
||||||
|
|
||||||
status = NT_STATUS_NO_MEMORY;
|
|
||||||
|
|
||||||
io->out.names = talloc_array(packet, struct wrepl_name, io->out.num_names);
|
io->out.names = talloc_array(packet, struct wrepl_name, io->out.num_names);
|
||||||
if (io->out.names == NULL) goto nomem;
|
if (io->out.names == NULL) goto nomem;
|
||||||
|
|
||||||
|
@ -69,6 +69,10 @@ struct wrepl_request {
|
|||||||
|
|
||||||
DATA_BLOB buffer;
|
DATA_BLOB buffer;
|
||||||
|
|
||||||
|
BOOL disconnect_after_send;
|
||||||
|
|
||||||
|
BOOL send_only;
|
||||||
|
|
||||||
size_t num_read;
|
size_t num_read;
|
||||||
|
|
||||||
struct timed_event *te;
|
struct timed_event *te;
|
||||||
@ -91,6 +95,16 @@ struct wrepl_associate {
|
|||||||
} out;
|
} out;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
setup an association
|
||||||
|
*/
|
||||||
|
struct wrepl_associate_stop {
|
||||||
|
struct {
|
||||||
|
uint32_t assoc_ctx;
|
||||||
|
uint32_t reason;
|
||||||
|
} in;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pull the partner table
|
pull the partner table
|
||||||
*/
|
*/
|
||||||
|
@ -53,6 +53,8 @@ static BOOL test_assoc_ctx1(TALLOC_CTX *mem_ctx, const char *address)
|
|||||||
struct wrepl_socket *wrepl_socket2;
|
struct wrepl_socket *wrepl_socket2;
|
||||||
struct wrepl_associate associate2;
|
struct wrepl_associate associate2;
|
||||||
struct wrepl_pull_table pull_table;
|
struct wrepl_pull_table pull_table;
|
||||||
|
struct wrepl_packet *rep_packet;
|
||||||
|
struct wrepl_associate_stop assoc_stop;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
printf("Test if assoc_ctx is only valid on the conection it was created on\n");
|
printf("Test if assoc_ctx is only valid on the conection it was created on\n");
|
||||||
@ -61,10 +63,10 @@ static BOOL test_assoc_ctx1(TALLOC_CTX *mem_ctx, const char *address)
|
|||||||
wrepl_socket2 = wrepl_socket_init(mem_ctx, NULL);
|
wrepl_socket2 = wrepl_socket_init(mem_ctx, NULL);
|
||||||
|
|
||||||
printf("Setup 2 wrepl connections\n");
|
printf("Setup 2 wrepl connections\n");
|
||||||
status = wrepl_connect(wrepl_socket1, address);
|
status = wrepl_connect(wrepl_socket1, NULL, address);
|
||||||
CHECK_STATUS(status, NT_STATUS_OK);
|
CHECK_STATUS(status, NT_STATUS_OK);
|
||||||
|
|
||||||
status = wrepl_connect(wrepl_socket2, address);
|
status = wrepl_connect(wrepl_socket2, NULL, address);
|
||||||
CHECK_STATUS(status, NT_STATUS_OK);
|
CHECK_STATUS(status, NT_STATUS_OK);
|
||||||
|
|
||||||
printf("Send a start association request (conn1)\n");
|
printf("Send a start association request (conn1)\n");
|
||||||
@ -79,15 +81,39 @@ static BOOL test_assoc_ctx1(TALLOC_CTX *mem_ctx, const char *address)
|
|||||||
|
|
||||||
printf("association context (conn2): 0x%x\n", associate2.out.assoc_ctx);
|
printf("association context (conn2): 0x%x\n", associate2.out.assoc_ctx);
|
||||||
|
|
||||||
printf("Send a replication table query, with assoc 1 (conn2), should be ignored\n");
|
printf("Send a replication table query, with assoc 1 (conn2), the anwser should be on conn1\n");
|
||||||
pull_table.in.assoc_ctx = associate1.out.assoc_ctx;
|
pull_table.in.assoc_ctx = associate1.out.assoc_ctx;
|
||||||
req = wrepl_pull_table_send(wrepl_socket2, &pull_table);
|
req = wrepl_pull_table_send(wrepl_socket2, &pull_table);
|
||||||
talloc_free(req);
|
req->send_only = True;
|
||||||
|
status = wrepl_request_recv(req, mem_ctx, &rep_packet);
|
||||||
|
CHECK_STATUS(status, NT_STATUS_OK);
|
||||||
|
|
||||||
printf("Send a association request (conn2), to make sure the last request was ignored\n");
|
printf("Send a association request (conn2), to make sure the last request was ignored\n");
|
||||||
status = wrepl_associate(wrepl_socket2, &associate2);
|
status = wrepl_associate(wrepl_socket2, &associate2);
|
||||||
CHECK_STATUS(status, NT_STATUS_OK);
|
CHECK_STATUS(status, NT_STATUS_OK);
|
||||||
|
|
||||||
|
printf("Send a replication table query, with invalid assoc (conn1), receive answer from conn2\n");
|
||||||
|
pull_table.in.assoc_ctx = 0;
|
||||||
|
req = wrepl_pull_table_send(wrepl_socket1, &pull_table);
|
||||||
|
status = wrepl_request_recv(req, mem_ctx, &rep_packet);
|
||||||
|
CHECK_STATUS(status, NT_STATUS_OK);
|
||||||
|
|
||||||
|
printf("Send a association request (conn1), to make sure the last request was handled correct\n");
|
||||||
|
status = wrepl_associate(wrepl_socket1, &associate2);
|
||||||
|
CHECK_STATUS(status, NT_STATUS_OK);
|
||||||
|
|
||||||
|
assoc_stop.in.assoc_ctx = associate1.out.assoc_ctx;
|
||||||
|
assoc_stop.in.reason = 4;
|
||||||
|
printf("Send a association stop request (conn1), reson: %u\n", assoc_stop.in.reason);
|
||||||
|
status = wrepl_associate_stop(wrepl_socket1, &assoc_stop);
|
||||||
|
CHECK_STATUS(status, NT_STATUS_END_OF_FILE);
|
||||||
|
|
||||||
|
assoc_stop.in.assoc_ctx = associate2.out.assoc_ctx;
|
||||||
|
assoc_stop.in.reason = 0;
|
||||||
|
printf("Send a association stop request (conn2), reson: %u\n", assoc_stop.in.reason);
|
||||||
|
status = wrepl_associate_stop(wrepl_socket2, &assoc_stop);
|
||||||
|
CHECK_STATUS(status, NT_STATUS_OK);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
printf("Close 2 wrepl connections\n");
|
printf("Close 2 wrepl connections\n");
|
||||||
talloc_free(wrepl_socket1);
|
talloc_free(wrepl_socket1);
|
||||||
@ -111,7 +137,7 @@ static BOOL test_assoc_ctx2(TALLOC_CTX *mem_ctx, const char *address)
|
|||||||
wrepl_socket = wrepl_socket_init(mem_ctx, NULL);
|
wrepl_socket = wrepl_socket_init(mem_ctx, NULL);
|
||||||
|
|
||||||
printf("Setup wrepl connections\n");
|
printf("Setup wrepl connections\n");
|
||||||
status = wrepl_connect(wrepl_socket, address);
|
status = wrepl_connect(wrepl_socket, NULL, address);
|
||||||
CHECK_STATUS(status, NT_STATUS_OK);
|
CHECK_STATUS(status, NT_STATUS_OK);
|
||||||
|
|
||||||
|
|
||||||
@ -175,7 +201,7 @@ static BOOL test_wins_replication(TALLOC_CTX *mem_ctx, const char *address)
|
|||||||
wrepl_socket = wrepl_socket_init(mem_ctx, NULL);
|
wrepl_socket = wrepl_socket_init(mem_ctx, NULL);
|
||||||
|
|
||||||
printf("Setup wrepl connections\n");
|
printf("Setup wrepl connections\n");
|
||||||
status = wrepl_connect(wrepl_socket, address);
|
status = wrepl_connect(wrepl_socket, NULL, address);
|
||||||
CHECK_STATUS(status, NT_STATUS_OK);
|
CHECK_STATUS(status, NT_STATUS_OK);
|
||||||
|
|
||||||
printf("Send a start association request\n");
|
printf("Send a start association request\n");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user