mirror of
https://github.com/samba-team/samba.git
synced 2025-02-02 09:47:23 +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_associate;
|
||||
struct wrepl_associate_stop;
|
||||
struct wrepl_pull_table;
|
||||
struct wrepl_pull_names;
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
*/
|
||||
static void wrepl_socket_dead(struct wrepl_socket *wrepl_socket, NTSTATUS status)
|
||||
{
|
||||
talloc_set_destructor(wrepl_socket, NULL);
|
||||
wrepl_socket->dead = True;
|
||||
|
||||
if (wrepl_socket->fde) {
|
||||
@ -96,9 +97,31 @@ static void wrepl_handler_send(struct wrepl_socket *wrepl_socket)
|
||||
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_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *);
|
||||
req->state = WREPL_REQUEST_RECV;
|
||||
}
|
||||
|
||||
EVENT_FD_READABLE(wrepl_socket->fde);
|
||||
}
|
||||
@ -289,7 +312,7 @@ failed:
|
||||
static int wrepl_socket_destructor(void *ptr)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -415,7 +438,7 @@ static NTSTATUS wrepl_request_wait(struct wrepl_request *req)
|
||||
connect a wrepl_socket to a WINS server
|
||||
*/
|
||||
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;
|
||||
NTSTATUS status;
|
||||
@ -430,7 +453,11 @@ struct wrepl_request *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
|
||||
|
||||
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);
|
||||
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
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
*/
|
||||
@ -735,8 +815,6 @@ NTSTATUS wrepl_pull_names_recv(struct wrepl_request *req,
|
||||
|
||||
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);
|
||||
if (io->out.names == NULL) goto nomem;
|
||||
|
||||
|
@ -69,6 +69,10 @@ struct wrepl_request {
|
||||
|
||||
DATA_BLOB buffer;
|
||||
|
||||
BOOL disconnect_after_send;
|
||||
|
||||
BOOL send_only;
|
||||
|
||||
size_t num_read;
|
||||
|
||||
struct timed_event *te;
|
||||
@ -91,6 +95,16 @@ struct wrepl_associate {
|
||||
} out;
|
||||
};
|
||||
|
||||
/*
|
||||
setup an association
|
||||
*/
|
||||
struct wrepl_associate_stop {
|
||||
struct {
|
||||
uint32_t assoc_ctx;
|
||||
uint32_t reason;
|
||||
} in;
|
||||
};
|
||||
|
||||
/*
|
||||
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_associate associate2;
|
||||
struct wrepl_pull_table pull_table;
|
||||
struct wrepl_packet *rep_packet;
|
||||
struct wrepl_associate_stop assoc_stop;
|
||||
NTSTATUS status;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
status = wrepl_connect(wrepl_socket2, address);
|
||||
status = wrepl_connect(wrepl_socket2, NULL, address);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
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("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;
|
||||
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");
|
||||
status = wrepl_associate(wrepl_socket2, &associate2);
|
||||
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:
|
||||
printf("Close 2 wrepl connections\n");
|
||||
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);
|
||||
|
||||
printf("Setup wrepl connections\n");
|
||||
status = wrepl_connect(wrepl_socket, address);
|
||||
status = wrepl_connect(wrepl_socket, NULL, address);
|
||||
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);
|
||||
|
||||
printf("Setup wrepl connections\n");
|
||||
status = wrepl_connect(wrepl_socket, address);
|
||||
status = wrepl_connect(wrepl_socket, NULL, address);
|
||||
CHECK_STATUS(status, NT_STATUS_OK);
|
||||
|
||||
printf("Send a start association request\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user