From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- source4/libcli/dgram/browse.c | 114 +++++++++++++++++ source4/libcli/dgram/dgramsocket.c | 242 +++++++++++++++++++++++++++++++++++++ source4/libcli/dgram/libdgram.h | 153 +++++++++++++++++++++++ source4/libcli/dgram/mailslot.c | 229 +++++++++++++++++++++++++++++++++++ source4/libcli/dgram/netlogon.c | 140 +++++++++++++++++++++ 5 files changed, 878 insertions(+) create mode 100644 source4/libcli/dgram/browse.c create mode 100644 source4/libcli/dgram/dgramsocket.c create mode 100644 source4/libcli/dgram/libdgram.h create mode 100644 source4/libcli/dgram/mailslot.c create mode 100644 source4/libcli/dgram/netlogon.c (limited to 'source4/libcli/dgram') diff --git a/source4/libcli/dgram/browse.c b/source4/libcli/dgram/browse.c new file mode 100644 index 0000000..437b6e1 --- /dev/null +++ b/source4/libcli/dgram/browse.c @@ -0,0 +1,114 @@ +/* + Unix SMB/CIFS implementation. + + handling for browsing dgram requests + + Copyright (C) Jelmer Vernooij 2005 + Heavily based on ntlogon.c + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "libcli/dgram/libdgram.h" +#include "lib/socket/socket.h" +#include "libcli/resolve/resolve.h" +#include "librpc/gen_ndr/ndr_nbt.h" +#include "param/param.h" + +NTSTATUS dgram_mailslot_browse_send(struct nbt_dgram_socket *dgmsock, + struct nbt_name *dest_name, + struct socket_address *dest, + struct nbt_name *src_name, + struct nbt_browse_packet *request) +{ + NTSTATUS status; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + TALLOC_CTX *tmp_ctx = talloc_new(dgmsock); + + ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, request, + (ndr_push_flags_fn_t)ndr_push_nbt_browse_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(tmp_ctx); + return ndr_map_error2ntstatus(ndr_err); + } + + status = dgram_mailslot_send(dgmsock, DGRAM_DIRECT_UNIQUE, + NBT_MAILSLOT_BROWSE, + dest_name, dest, + src_name, &blob); + talloc_free(tmp_ctx); + return status; +} + +NTSTATUS dgram_mailslot_browse_reply(struct nbt_dgram_socket *dgmsock, + struct nbt_dgram_packet *request, + const char *mailslot_name, + const char *my_netbios_name, + struct nbt_browse_packet *reply) +{ + NTSTATUS status; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + TALLOC_CTX *tmp_ctx = talloc_new(dgmsock); + struct nbt_name myname; + struct socket_address *dest; + + ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, reply, + (ndr_push_flags_fn_t)ndr_push_nbt_browse_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(tmp_ctx); + return ndr_map_error2ntstatus(ndr_err); + } + + make_nbt_name_client(&myname, my_netbios_name); + + dest = socket_address_from_strings(tmp_ctx, dgmsock->sock->backend_name, + request->src_addr, request->src_port); + if (!dest) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + status = dgram_mailslot_send(dgmsock, DGRAM_DIRECT_UNIQUE, + mailslot_name, + &request->data.msg.source_name, + dest, + &myname, &blob); + talloc_free(tmp_ctx); + return status; +} + +NTSTATUS dgram_mailslot_browse_parse(struct dgram_mailslot_handler *dgmslot, + TALLOC_CTX *mem_ctx, + struct nbt_dgram_packet *dgram, + struct nbt_browse_packet *pkt) +{ + DATA_BLOB data = dgram_mailslot_data(dgram); + enum ndr_err_code ndr_err; + + ndr_err = ndr_pull_struct_blob(&data, mem_ctx, pkt, + (ndr_pull_flags_fn_t)ndr_pull_nbt_browse_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + DEBUG(0,("Failed to parse browse packet of length %d: %s\n", + (int)data.length, nt_errstr(status))); + if (DEBUGLVL(10)) { + (void)file_save("browse.dat", data.data, data.length); + } + return status; + } + return NT_STATUS_OK; +} diff --git a/source4/libcli/dgram/dgramsocket.c b/source4/libcli/dgram/dgramsocket.c new file mode 100644 index 0000000..154a667 --- /dev/null +++ b/source4/libcli/dgram/dgramsocket.c @@ -0,0 +1,242 @@ +/* + Unix SMB/CIFS implementation. + + low level socket handling for nbt dgram requests (UDP138) + + Copyright (C) Andrew Tridgell 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "../lib/util/dlinklist.h" +#include "libcli/dgram/libdgram.h" +#include "lib/socket/socket.h" +#include "librpc/gen_ndr/ndr_nbt.h" + + +/* + handle recv events on a nbt dgram socket +*/ +static void dgm_socket_recv(struct nbt_dgram_socket *dgmsock) +{ + TALLOC_CTX *tmp_ctx = talloc_new(dgmsock); + NTSTATUS status; + struct socket_address *src; + DATA_BLOB blob; + size_t nread, dsize; + struct nbt_dgram_packet *packet; + const char *mailslot_name; + enum ndr_err_code ndr_err; + + status = socket_pending(dgmsock->sock, &dsize); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return; + } + + blob = data_blob_talloc(tmp_ctx, NULL, dsize); + if ((dsize != 0) && (blob.data == NULL)) { + talloc_free(tmp_ctx); + return; + } + + status = socket_recvfrom(dgmsock->sock, blob.data, blob.length, &nread, + tmp_ctx, &src); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + return; + } + blob.length = nread; + + DEBUG(5,("Received dgram packet of length %d from %s:%d\n", + (int)blob.length, src->addr, src->port)); + + packet = talloc(tmp_ctx, struct nbt_dgram_packet); + if (packet == NULL) { + talloc_free(tmp_ctx); + return; + } + + /* parse the request */ + ndr_err = ndr_pull_struct_blob(&blob, packet, packet, + (ndr_pull_flags_fn_t)ndr_pull_nbt_dgram_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + DEBUG(2,("Failed to parse incoming NBT DGRAM packet - %s\n", + nt_errstr(status))); + talloc_free(tmp_ctx); + return; + } + + /* if this is a mailslot message, then see if we can dispatch it to a handler */ + mailslot_name = dgram_mailslot_name(packet); + if (mailslot_name) { + struct dgram_mailslot_handler *dgmslot; + dgmslot = dgram_mailslot_find(dgmsock, mailslot_name); + if (dgmslot) { + dgmslot->handler(dgmslot, packet, src); + } else { + DEBUG(2,("No mailslot handler for '%s'\n", mailslot_name)); + } + } else { + /* dispatch if there is a general handler */ + if (dgmsock->incoming.handler) { + dgmsock->incoming.handler(dgmsock, packet, src); + } + } + + talloc_free(tmp_ctx); +} + + +/* + handle send events on a nbt dgram socket +*/ +static void dgm_socket_send(struct nbt_dgram_socket *dgmsock) +{ + struct nbt_dgram_request *req; + NTSTATUS status; + + while ((req = dgmsock->send_queue)) { + size_t len; + + len = req->encoded.length; + status = socket_sendto(dgmsock->sock, &req->encoded, &len, + req->dest); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(3,("Failed to send datagram of length %u to %s:%d: %s\n", + (unsigned)req->encoded.length, req->dest->addr, req->dest->port, + nt_errstr(status))); + DLIST_REMOVE(dgmsock->send_queue, req); + talloc_free(req); + continue; + } + + if (!NT_STATUS_IS_OK(status)) return; + + DLIST_REMOVE(dgmsock->send_queue, req); + talloc_free(req); + } + + TEVENT_FD_NOT_WRITEABLE(dgmsock->fde); + return; +} + + +/* + handle fd events on a nbt_dgram_socket +*/ +static void dgm_socket_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data) +{ + struct nbt_dgram_socket *dgmsock = talloc_get_type(private_data, + struct nbt_dgram_socket); + if (flags & TEVENT_FD_WRITE) { + dgm_socket_send(dgmsock); + } + if (flags & TEVENT_FD_READ) { + dgm_socket_recv(dgmsock); + } +} + +/* + initialise a nbt_dgram_socket. The event_ctx is optional, if provided + then operations will use that event context +*/ +struct nbt_dgram_socket *nbt_dgram_socket_init(TALLOC_CTX *mem_ctx, + struct tevent_context *event_ctx) +{ + struct nbt_dgram_socket *dgmsock; + NTSTATUS status; + + dgmsock = talloc(mem_ctx, struct nbt_dgram_socket); + if (dgmsock == NULL) goto failed; + + dgmsock->event_ctx = event_ctx; + if (dgmsock->event_ctx == NULL) goto failed; + + status = socket_create(dgmsock, "ip", SOCKET_TYPE_DGRAM, + &dgmsock->sock, 0); + if (!NT_STATUS_IS_OK(status)) goto failed; + + socket_set_option(dgmsock->sock, "SO_BROADCAST", "1"); + + dgmsock->fde = tevent_add_fd(dgmsock->event_ctx, dgmsock, + socket_get_fd(dgmsock->sock), 0, + dgm_socket_handler, dgmsock); + + dgmsock->send_queue = NULL; + dgmsock->incoming.handler = NULL; + dgmsock->mailslot_handlers = NULL; + + return dgmsock; + +failed: + talloc_free(dgmsock); + return NULL; +} + + +/* + setup a handler for generic incoming requests +*/ +NTSTATUS dgram_set_incoming_handler(struct nbt_dgram_socket *dgmsock, + void (*handler)(struct nbt_dgram_socket *, + struct nbt_dgram_packet *, + struct socket_address *), + void *private_data) +{ + dgmsock->incoming.handler = handler; + dgmsock->incoming.private_data = private_data; + TEVENT_FD_READABLE(dgmsock->fde); + return NT_STATUS_OK; +} + + +/* + queue a datagram for send +*/ +NTSTATUS nbt_dgram_send(struct nbt_dgram_socket *dgmsock, + struct nbt_dgram_packet *packet, + struct socket_address *dest) +{ + struct nbt_dgram_request *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + enum ndr_err_code ndr_err; + + req = talloc(dgmsock, struct nbt_dgram_request); + if (req == NULL) goto failed; + + req->dest = dest; + if (talloc_reference(req, dest) == NULL) goto failed; + + ndr_err = ndr_push_struct_blob(&req->encoded, req, packet, + (ndr_push_flags_fn_t)ndr_push_nbt_dgram_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + goto failed; + } + + DLIST_ADD_END(dgmsock->send_queue, req); + + TEVENT_FD_WRITEABLE(dgmsock->fde); + + return NT_STATUS_OK; + +failed: + talloc_free(req); + return status; +} diff --git a/source4/libcli/dgram/libdgram.h b/source4/libcli/dgram/libdgram.h new file mode 100644 index 0000000..0f313a6 --- /dev/null +++ b/source4/libcli/dgram/libdgram.h @@ -0,0 +1,153 @@ +/* + Unix SMB/CIFS implementation. + + a raw async NBT DGRAM library + + Copyright (C) Andrew Tridgell 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "../libcli/netlogon/netlogon.h" + +/* + a datagram name request +*/ +struct nbt_dgram_request { + struct nbt_dgram_request *next, *prev; + + /* where to send the request */ + struct socket_address *dest; + + /* the encoded request */ + DATA_BLOB encoded; +}; + +/* + context structure for operations on dgram packets +*/ +struct nbt_dgram_socket { + struct socket_context *sock; + struct tevent_context *event_ctx; + + /* the fd event */ + struct tevent_fd *fde; + + /* a queue of outgoing requests */ + struct nbt_dgram_request *send_queue; + + /* a list of mailslot handlers */ + struct dgram_mailslot_handler *mailslot_handlers; + + /* what to do with incoming request packets */ + struct { + void (*handler)(struct nbt_dgram_socket *, struct nbt_dgram_packet *, + struct socket_address *src); + void *private_data; + } incoming; +}; + + +/* + the mailslot code keeps a list of mailslot handlers. A mailslot + handler is a function that receives incoming packets for a specific + mailslot name. When a caller needs to send a mailslot and wants to + get a reply then it needs to register itself as listening for + incoming packets on the reply mailslot +*/ + +typedef void (*dgram_mailslot_handler_t)(struct dgram_mailslot_handler *, + struct nbt_dgram_packet *, + struct socket_address *src); + +struct dgram_mailslot_handler { + struct dgram_mailslot_handler *next, *prev; + + struct nbt_dgram_socket *dgmsock; + const char *mailslot_name; + + dgram_mailslot_handler_t handler; + void *private_data; +}; + + +/* prototypes */ +NTSTATUS nbt_dgram_send(struct nbt_dgram_socket *dgmsock, + struct nbt_dgram_packet *packet, + struct socket_address *dest); +NTSTATUS dgram_set_incoming_handler(struct nbt_dgram_socket *dgmsock, + void (*handler)(struct nbt_dgram_socket *, + struct nbt_dgram_packet *, + struct socket_address *), + void *private_data); +struct nbt_dgram_socket *nbt_dgram_socket_init(TALLOC_CTX *mem_ctx, + struct tevent_context *event_ctx); + +const char *dgram_mailslot_name(struct nbt_dgram_packet *packet); +struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock, + const char *mailslot_name); +struct dgram_mailslot_handler *dgram_mailslot_listen(struct nbt_dgram_socket *dgmsock, + const char *mailslot_name, + dgram_mailslot_handler_t handler, + void *private_data); +struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgmsock, + const char *mailslot_name, + dgram_mailslot_handler_t handler, + void *private_data); +DATA_BLOB dgram_mailslot_data(struct nbt_dgram_packet *dgram); + + +NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock, + enum dgram_msg_type msg_type, + const char *mailslot_name, + struct nbt_name *dest_name, + struct socket_address *dest, + struct nbt_name *src_name, + DATA_BLOB *request); + +NTSTATUS dgram_mailslot_netlogon_send(struct nbt_dgram_socket *dgmsock, + struct nbt_name *dest_name, + struct socket_address *dest, + const char *mailslot_name, + struct nbt_name *src_name, + struct nbt_netlogon_packet *request); +NTSTATUS dgram_mailslot_netlogon_reply(struct nbt_dgram_socket *dgmsock, + struct nbt_dgram_packet *request, + const char *my_netbios_name, + const char *mailslot_name, + struct nbt_netlogon_response *reply); +NTSTATUS dgram_mailslot_netlogon_parse_request(TALLOC_CTX *mem_ctx, + struct nbt_dgram_packet *dgram, + struct nbt_netlogon_packet *netlogon); + +NTSTATUS dgram_mailslot_netlogon_parse_response(TALLOC_CTX *mem_ctx, + struct nbt_dgram_packet *dgram, + struct nbt_netlogon_response *netlogon); + +NTSTATUS dgram_mailslot_browse_send(struct nbt_dgram_socket *dgmsock, + struct nbt_name *dest_name, + struct socket_address *dest, + struct nbt_name *src_name, + struct nbt_browse_packet *request); + +NTSTATUS dgram_mailslot_browse_reply(struct nbt_dgram_socket *dgmsock, + struct nbt_dgram_packet *request, + const char *mailslot_name, + const char *my_netbios_name, + struct nbt_browse_packet *reply); + +NTSTATUS dgram_mailslot_browse_parse(struct dgram_mailslot_handler *dgmslot, + TALLOC_CTX *mem_ctx, + struct nbt_dgram_packet *dgram, + struct nbt_browse_packet *pkt); diff --git a/source4/libcli/dgram/mailslot.c b/source4/libcli/dgram/mailslot.c new file mode 100644 index 0000000..a24800c --- /dev/null +++ b/source4/libcli/dgram/mailslot.c @@ -0,0 +1,229 @@ +/* + Unix SMB/CIFS implementation. + + packet handling for mailslot requests. + + Copyright (C) Andrew Tridgell 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + This implements "Class 2 mailslots", i.e. the communication mechanism + used for all mailslot packets smaller than 425 bytes. + + "Class 1 mailslots" (which use SMB) are used for messages larger + than 426 bytes and are supported on some systems. These are not implemented + in Samba4 yet, as there don't appear to be any core services that use + them. + + 425 and 426-byte sized messages are not supported at all. +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "../lib/util/dlinklist.h" +#include "libcli/dgram/libdgram.h" +#include "lib/socket/socket.h" + +#undef strcasecmp + +/* + destroy a mailslot handler +*/ +static int dgram_mailslot_destructor(struct dgram_mailslot_handler *dgmslot) +{ + DLIST_REMOVE(dgmslot->dgmsock->mailslot_handlers, dgmslot); + return 0; +} + +/* + start listening on a mailslot. talloc_free() the handle to stop listening +*/ +struct dgram_mailslot_handler *dgram_mailslot_listen(struct nbt_dgram_socket *dgmsock, + const char *mailslot_name, + dgram_mailslot_handler_t handler, + void *private_data) +{ + struct dgram_mailslot_handler *dgmslot; + + dgmslot = talloc(dgmsock, struct dgram_mailslot_handler); + if (dgmslot == NULL) return NULL; + + dgmslot->dgmsock = dgmsock; + dgmslot->mailslot_name = talloc_strdup(dgmslot, mailslot_name); + if (dgmslot->mailslot_name == NULL) { + talloc_free(dgmslot); + return NULL; + } + dgmslot->handler = handler; + dgmslot->private_data = private_data; + + DLIST_ADD(dgmsock->mailslot_handlers, dgmslot); + talloc_set_destructor(dgmslot, dgram_mailslot_destructor); + + TEVENT_FD_READABLE(dgmsock->fde); + + return dgmslot; +} + +/* + find the handler for a specific mailslot name +*/ +struct dgram_mailslot_handler *dgram_mailslot_find(struct nbt_dgram_socket *dgmsock, + const char *mailslot_name) +{ + struct dgram_mailslot_handler *h; + for (h=dgmsock->mailslot_handlers;h;h=h->next) { + if (strcasecmp(h->mailslot_name, mailslot_name) == 0) { + return h; + } + } + return NULL; +} + +/* + check that a datagram packet is a valid mailslot request, and return the + mailslot name if it is, otherwise return NULL +*/ +const char *dgram_mailslot_name(struct nbt_dgram_packet *packet) +{ + if (packet->msg_type != DGRAM_DIRECT_UNIQUE && + packet->msg_type != DGRAM_DIRECT_GROUP && + packet->msg_type != DGRAM_BCAST) { + return NULL; + } + if (packet->data.msg.dgram_body_type != DGRAM_SMB) return NULL; + if (packet->data.msg.body.smb.smb_command != SMB_TRANSACTION) return NULL; + return packet->data.msg.body.smb.body.trans.mailslot_name; +} + + +/* + create a temporary mailslot handler for a reply mailslot, allocating + a new mailslot name using the given base name and a random integer extension +*/ +struct dgram_mailslot_handler *dgram_mailslot_temp(struct nbt_dgram_socket *dgmsock, + const char *mailslot_name, + dgram_mailslot_handler_t handler, + void *private_data) +{ + char *name; + int i; + struct dgram_mailslot_handler *dgmslot; + + /* try a 100 times at most */ + for (i=0;i<100;i++) { + name = talloc_asprintf(dgmsock, "%s%03u", + mailslot_name, + generate_random() % 1000); + if (name == NULL) return NULL; + if (dgram_mailslot_find(dgmsock, name)) { + talloc_free(name); + continue; + } + dgmslot = dgram_mailslot_listen(dgmsock, name, handler, private_data); + talloc_free(name); + if (dgmslot != NULL) { + return dgmslot; + } + } + DEBUG(2,("Unable to create temporary mailslot from %s\n", mailslot_name)); + return NULL; +} + + +/* + send a mailslot request +*/ +NTSTATUS dgram_mailslot_send(struct nbt_dgram_socket *dgmsock, + enum dgram_msg_type msg_type, + const char *mailslot_name, + struct nbt_name *dest_name, + struct socket_address *dest, + struct nbt_name *src_name, + DATA_BLOB *request) +{ + TALLOC_CTX *tmp_ctx = talloc_new(dgmsock); + struct nbt_dgram_packet packet; + struct dgram_message *msg; + struct dgram_smb_packet *smb; + struct smb_trans_body *trans; + struct socket_address *src; + NTSTATUS status; + + if (dest->port == 0) { + return NT_STATUS_INVALID_PARAMETER; + } + + ZERO_STRUCT(packet); + packet.msg_type = msg_type; + packet.flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD; + packet.dgram_id = generate_random() % UINT16_MAX; + src = socket_get_my_addr(dgmsock->sock, tmp_ctx); + if (!src) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + packet.src_addr = src->addr; + packet.src_port = src->port; + + msg = &packet.data.msg; + /* this length calculation is very crude - it should be based on gensize + calls */ + msg->length = 138 + strlen(mailslot_name) + request->length; + msg->offset = 0; + + msg->source_name = *src_name; + msg->dest_name = *dest_name; + msg->dgram_body_type = DGRAM_SMB; + + smb = &msg->body.smb; + smb->smb_command = SMB_TRANSACTION; + + trans = &smb->body.trans; + trans->total_data_count = request->length; + trans->timeout = 1000; + trans->data_count = request->length; + trans->data_offset = 70 + strlen(mailslot_name); + trans->opcode = 1; /* write mail slot */ + trans->priority = 1; + trans->_class = 2; + trans->mailslot_name = mailslot_name; + trans->data = *request; + + status = nbt_dgram_send(dgmsock, &packet, dest); + + talloc_free(tmp_ctx); + + return status; +} + +/* + return the mailslot data portion from a mailslot packet +*/ +DATA_BLOB dgram_mailslot_data(struct nbt_dgram_packet *dgram) +{ + struct smb_trans_body *trans = &dgram->data.msg.body.smb.body.trans; + DATA_BLOB ret = trans->data; + int pad = trans->data_offset - (70 + strlen(trans->mailslot_name)); + + if (pad < 0 || pad > ret.length) { + DEBUG(2,("Badly formatted data in mailslot - pad = %d\n", pad)); + return data_blob(NULL, 0); + } + ret.data += pad; + ret.length -= pad; + return ret; +} diff --git a/source4/libcli/dgram/netlogon.c b/source4/libcli/dgram/netlogon.c new file mode 100644 index 0000000..1124a33 --- /dev/null +++ b/source4/libcli/dgram/netlogon.c @@ -0,0 +1,140 @@ +/* + Unix SMB/CIFS implementation. + + handling for netlogon dgram requests + + Copyright (C) Andrew Tridgell 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "libcli/dgram/libdgram.h" +#include "lib/socket/socket.h" +#include "libcli/resolve/resolve.h" +#include "librpc/gen_ndr/ndr_nbt.h" + +/* + send a netlogon mailslot request +*/ +NTSTATUS dgram_mailslot_netlogon_send(struct nbt_dgram_socket *dgmsock, + struct nbt_name *dest_name, + struct socket_address *dest, + const char *mailslot, + struct nbt_name *src_name, + struct nbt_netlogon_packet *request) +{ + NTSTATUS status; + enum ndr_err_code ndr_err; + DATA_BLOB blob; + TALLOC_CTX *tmp_ctx = talloc_new(dgmsock); + + ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, request, + (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(tmp_ctx); + return ndr_map_error2ntstatus(ndr_err); + } + + + status = dgram_mailslot_send(dgmsock, DGRAM_DIRECT_UNIQUE, + mailslot, + dest_name, dest, + src_name, &blob); + talloc_free(tmp_ctx); + return status; +} + + +/* + send a netlogon mailslot reply +*/ +NTSTATUS dgram_mailslot_netlogon_reply(struct nbt_dgram_socket *dgmsock, + struct nbt_dgram_packet *request, + const char *my_netbios_name, + const char *mailslot_name, + struct nbt_netlogon_response *reply) +{ + NTSTATUS status; + DATA_BLOB blob; + TALLOC_CTX *tmp_ctx = talloc_new(dgmsock); + struct nbt_name myname; + struct socket_address *dest; + + status = push_nbt_netlogon_response(&blob, tmp_ctx, reply); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + make_nbt_name_client(&myname, my_netbios_name); + + dest = socket_address_from_strings(tmp_ctx, dgmsock->sock->backend_name, + request->src_addr, request->src_port); + if (!dest) { + talloc_free(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + + status = dgram_mailslot_send(dgmsock, DGRAM_DIRECT_UNIQUE, + mailslot_name, + &request->data.msg.source_name, + dest, + &myname, &blob); + talloc_free(tmp_ctx); + return status; +} + + +/* + parse a netlogon request. The packet must be a valid mailslot packet +*/ +NTSTATUS dgram_mailslot_netlogon_parse_request(TALLOC_CTX *mem_ctx, + struct nbt_dgram_packet *dgram, + struct nbt_netlogon_packet *netlogon) +{ + DATA_BLOB data = dgram_mailslot_data(dgram); + enum ndr_err_code ndr_err; + + ndr_err = ndr_pull_struct_blob(&data, mem_ctx, netlogon, + (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_packet); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n", + (int)data.length, nt_errstr(status))); + if (DEBUGLVL(10)) { + (void)file_save("netlogon.dat", data.data, data.length); + } + return status; + } + return NT_STATUS_OK; +} + +/* + parse a netlogon response. The packet must be a valid mailslot packet +*/ +NTSTATUS dgram_mailslot_netlogon_parse_response(TALLOC_CTX *mem_ctx, + struct nbt_dgram_packet *dgram, + struct nbt_netlogon_response *netlogon) +{ + NTSTATUS status; + DATA_BLOB data = dgram_mailslot_data(dgram); + + status = pull_nbt_netlogon_response(&data, mem_ctx, netlogon); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + -- cgit v1.2.3