1
0
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:
Stefan Metzmacher 2005-10-06 14:38:07 +00:00 committed by Gerald (Jerry) Carter
parent 093a30d7ed
commit 6799fde75d
4 changed files with 137 additions and 18 deletions

View File

@ -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;

View File

@ -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;
}
DLIST_REMOVE(wrepl_socket->send_queue, req);
DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *);
req->state = WREPL_REQUEST_RECV;
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;
@ -429,8 +452,12 @@ struct wrepl_request *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
DLIST_ADD(wrepl_socket->recv_queue, req);
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;

View File

@ -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
*/

View File

@ -53,18 +53,20 @@ 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");
wrepl_socket1 = wrepl_socket_init(mem_ctx, NULL);
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");