summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/libcli/config.mk3
-rw-r--r--source4/libcli/dgram/libdgram.h15
-rw-r--r--source4/libcli/dgram/ntlogon.c117
-rw-r--r--source4/librpc/idl/nbt.idl45
-rw-r--r--source4/nbt_server/config.mk1
-rw-r--r--source4/nbt_server/dgram/ntlogon.c76
-rw-r--r--source4/nbt_server/dgram/request.c1
-rw-r--r--source4/torture/nbt/dgram.c112
-rw-r--r--source4/torture/rpc/testjoin.c11
9 files changed, 377 insertions, 4 deletions
diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk
index 56e923daa2..def7bd0f27 100644
--- a/source4/libcli/config.mk
+++ b/source4/libcli/config.mk
@@ -39,7 +39,8 @@ REQUIRED_SUBSYSTEMS = LIBNDR_RAW NDR_NBT SOCKET LIBCLI_COMPOSITE_BASE LIBEVENTS
ADD_OBJ_FILES = \
libcli/dgram/dgramsocket.o \
libcli/dgram/mailslot.o \
- libcli/dgram/netlogon.o
+ libcli/dgram/netlogon.o \
+ libcli/dgram/ntlogon.o
NOPROTO=YES
REQUIRED_SUBSYSTEMS = LIBCLI_NBT
diff --git a/source4/libcli/dgram/libdgram.h b/source4/libcli/dgram/libdgram.h
index 163cb1e37d..af278d2ab6 100644
--- a/source4/libcli/dgram/libdgram.h
+++ b/source4/libcli/dgram/libdgram.h
@@ -134,3 +134,18 @@ NTSTATUS dgram_mailslot_netlogon_parse(struct dgram_mailslot_handler *dgmslot,
TALLOC_CTX *mem_ctx,
struct nbt_dgram_packet *dgram,
struct nbt_netlogon_packet *netlogon);
+
+NTSTATUS dgram_mailslot_ntlogon_send(struct nbt_dgram_socket *dgmsock,
+ struct nbt_name *dest_name,
+ const char *dest_address,
+ int dest_port,
+ struct nbt_name *src_name,
+ struct nbt_ntlogon_packet *request);
+NTSTATUS dgram_mailslot_ntlogon_reply(struct nbt_dgram_socket *dgmsock,
+ struct nbt_dgram_packet *request,
+ const char *mailslot_name,
+ struct nbt_ntlogon_packet *reply);
+NTSTATUS dgram_mailslot_ntlogon_parse(struct dgram_mailslot_handler *dgmslot,
+ TALLOC_CTX *mem_ctx,
+ struct nbt_dgram_packet *dgram,
+ struct nbt_ntlogon_packet *ntlogon);
diff --git a/source4/libcli/dgram/ntlogon.c b/source4/libcli/dgram/ntlogon.c
new file mode 100644
index 0000000000..7f18e8cec6
--- /dev/null
+++ b/source4/libcli/dgram/ntlogon.c
@@ -0,0 +1,117 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ handling for ntlogon 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "lib/events/events.h"
+#include "dlinklist.h"
+#include "libcli/nbt/libnbt.h"
+#include "libcli/dgram/libdgram.h"
+#include "lib/socket/socket.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
+
+/*
+ send a ntlogon mailslot request
+*/
+NTSTATUS dgram_mailslot_ntlogon_send(struct nbt_dgram_socket *dgmsock,
+ struct nbt_name *dest_name,
+ const char *dest_address,
+ int dest_port,
+ struct nbt_name *src_name,
+ struct nbt_ntlogon_packet *request)
+{
+ NTSTATUS status;
+ DATA_BLOB blob;
+ TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
+
+ status = ndr_push_struct_blob(&blob, tmp_ctx, request,
+ (ndr_push_flags_fn_t)ndr_push_nbt_ntlogon_packet);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+
+ status = dgram_mailslot_send(dgmsock, DGRAM_DIRECT_UNIQUE,
+ NBT_MAILSLOT_NTLOGON,
+ dest_name, dest_address, dest_port,
+ src_name, &blob);
+ talloc_free(tmp_ctx);
+ return status;
+}
+
+
+/*
+ send a ntlogon mailslot reply
+*/
+NTSTATUS dgram_mailslot_ntlogon_reply(struct nbt_dgram_socket *dgmsock,
+ struct nbt_dgram_packet *request,
+ const char *mailslot_name,
+ struct nbt_ntlogon_packet *reply)
+{
+ NTSTATUS status;
+ DATA_BLOB blob;
+ TALLOC_CTX *tmp_ctx = talloc_new(dgmsock);
+ struct nbt_name myname;
+
+ status = ndr_push_struct_blob(&blob, tmp_ctx, reply,
+ (ndr_push_flags_fn_t)ndr_push_nbt_ntlogon_packet);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ myname.name = lp_netbios_name();
+ myname.type = NBT_NAME_CLIENT;
+ myname.scope = NULL;
+
+ status = dgram_mailslot_send(dgmsock, DGRAM_DIRECT_UNIQUE,
+ mailslot_name,
+ &request->data.msg.source_name,
+ request->source, request->src_port,
+ &myname, &blob);
+ talloc_free(tmp_ctx);
+ return status;
+}
+
+
+/*
+ parse a ntlogon response. The packet must be a valid mailslot packet
+*/
+NTSTATUS dgram_mailslot_ntlogon_parse(struct dgram_mailslot_handler *dgmslot,
+ TALLOC_CTX *mem_ctx,
+ struct nbt_dgram_packet *dgram,
+ struct nbt_ntlogon_packet *ntlogon)
+{
+ DATA_BLOB *data = &dgram->data.msg.body.smb.body.trans.data;
+ NTSTATUS status;
+
+ status = ndr_pull_struct_blob(data, mem_ctx, ntlogon,
+ (ndr_pull_flags_fn_t)ndr_pull_nbt_ntlogon_packet);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("Failed to parse ntlogon packet of length %d\n",
+ data->length));
+#if 0
+ file_save("ntlogon.dat", data->data, data->length);
+#endif
+ }
+ return status;
+}
diff --git a/source4/librpc/idl/nbt.idl b/source4/librpc/idl/nbt.idl
index c03f30333e..d7c89966f1 100644
--- a/source4/librpc/idl/nbt.idl
+++ b/source4/librpc/idl/nbt.idl
@@ -228,6 +228,7 @@
easier */
const string NBT_MAILSLOT_NETLOGON = "\\MAILSLOT\\NET\\NETLOGON";
+ const string NBT_MAILSLOT_NTLOGON = "\\MAILSLOT\\NET\\NTLOGON";
const string NBT_MAILSLOT_GETDC = "\\MAILSLOT\\GETDC";
const string NBT_MAILSLOT_BROWSE = "\\MAILSLOT\\BROWSE";
@@ -326,6 +327,7 @@
} nbt_dgram_packet;
+ /*******************************************/
/* \MAILSLOT\NET\NETLOGON mailslot requests */
typedef enum {
NETLOGON_QUERY_FOR_PDC = 0x7,
@@ -376,7 +378,7 @@
uint32 db_count;
nbt_db_change dbchange[db_count];
[value(ndr_size_dom_sid(&r->sid))] uint32 sid_size;
- uint16 unknown;
+ [flag(NDR_ALIGN4)] DATA_BLOB _pad2;
dom_sid sid;
uint32 nt_version;
uint16 lmnt_token;
@@ -393,4 +395,45 @@
nbt_netlogon_command command;
[switch_is(command)] nbt_netlogon_request req;
} nbt_netlogon_packet;
+
+ /*******************************************/
+ /* \MAILSLOT\NET\NTLOGON mailslot requests */
+ typedef enum {
+ NTLOGON_SAM_LOGON = 0x12,
+ NTLOGON_SAM_LOGON_REPLY = 0x13
+ } nbt_ntlogon_command;
+
+ typedef struct {
+ uint16 request_count;
+ nstring computer_name;
+ nstring user_name;
+ astring mailslot_name;
+ uint32 acct_control;
+ [value(ndr_size_dom_sid(&r->sid))] uint32 sid_size;
+ [flag(NDR_ALIGN4)] DATA_BLOB _pad;
+ dom_sid sid;
+ uint32 nt_version;
+ uint16 lmnt_token;
+ uint16 lm20_token;
+ } nbt_ntlogon_sam_logon;
+
+ typedef struct {
+ nstring server;
+ nstring user_name;
+ nstring domain;
+ uint32 nt_version;
+ uint16 lmnt_token;
+ uint16 lm20_token;
+ } nbt_ntlogon_sam_logon_reply;
+
+ typedef [nodiscriminant] union {
+ [case(NTLOGON_SAM_LOGON)] nbt_ntlogon_sam_logon logon;
+ [case(NTLOGON_SAM_LOGON_REPLY)] nbt_ntlogon_sam_logon_reply reply;
+ } nbt_ntlogon_request;
+
+ typedef [flag(NDR_NOALIGN),public] struct {
+ nbt_ntlogon_command command;
+ [switch_is(command)] nbt_ntlogon_request req;
+ } nbt_ntlogon_packet;
+
}
diff --git a/source4/nbt_server/config.mk b/source4/nbt_server/config.mk
index 04a9dde1b0..7576bf3349 100644
--- a/source4/nbt_server/config.mk
+++ b/source4/nbt_server/config.mk
@@ -19,6 +19,7 @@ REQUIRED_SUBSYSTEMS = \
ADD_OBJ_FILES = \
nbt_server/dgram/request.o \
nbt_server/dgram/netlogon.o \
+ nbt_server/dgram/ntlogon.o \
nbt_server/dgram/browse.o
REQUIRED_SUBSYSTEMS = \
LIBCLI_DGRAM
diff --git a/source4/nbt_server/dgram/ntlogon.c b/source4/nbt_server/dgram/ntlogon.c
new file mode 100644
index 0000000000..d035c2f00a
--- /dev/null
+++ b/source4/nbt_server/dgram/ntlogon.c
@@ -0,0 +1,76 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ NBT datagram ntlogon server
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "dlinklist.h"
+#include "nbt_server/nbt_server.h"
+#include "smbd/service_task.h"
+#include "lib/socket/socket.h"
+
+/*
+ handle incoming ntlogon mailslot requests
+*/
+void nbtd_mailslot_ntlogon_handler(struct dgram_mailslot_handler *dgmslot,
+ struct nbt_dgram_packet *packet,
+ const char *src_address, int src_port)
+{
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
+ struct nbtd_interface *iface =
+ talloc_get_type(dgmslot->private, struct nbtd_interface);
+ struct nbt_ntlogon_packet *ntlogon =
+ talloc(dgmslot, struct nbt_ntlogon_packet);
+ struct nbtd_iface_name *iname;
+ struct nbt_name *name = &packet->data.msg.dest_name;
+
+ if (ntlogon == NULL) goto failed;
+
+ /*
+ see if the we are listening on the destination netbios name
+ */
+ iname = nbtd_find_iname(iface, name, 0);
+ if (iname == NULL) {
+ status = NT_STATUS_BAD_NETWORK_NAME;
+ goto failed;
+ }
+
+ DEBUG(2,("ntlogon request to %s from %s:%d\n",
+ nbt_name_string(ntlogon, name), src_address, src_port));
+ status = dgram_mailslot_ntlogon_parse(dgmslot, ntlogon, packet, ntlogon);
+ if (!NT_STATUS_IS_OK(status)) goto failed;
+
+ NDR_PRINT_DEBUG(nbt_ntlogon_packet, ntlogon);
+
+ switch (ntlogon->command) {
+ default:
+ DEBUG(2,("unknown ntlogon op %d from %s:%d\n",
+ ntlogon->command, src_address, src_port));
+ break;
+ }
+
+ talloc_free(ntlogon);
+ return;
+
+failed:
+ DEBUG(2,("nbtd ntlogon handler failed from %s:%d - %s\n",
+ src_address, src_port, nt_errstr(status)));
+ talloc_free(ntlogon);
+}
diff --git a/source4/nbt_server/dgram/request.c b/source4/nbt_server/dgram/request.c
index 59b94bcecb..f59193bec5 100644
--- a/source4/nbt_server/dgram/request.c
+++ b/source4/nbt_server/dgram/request.c
@@ -34,6 +34,7 @@ static const struct {
dgram_mailslot_handler_t handler;
} mailslot_handlers[] = {
{ NBT_MAILSLOT_NETLOGON, nbtd_mailslot_netlogon_handler },
+ { NBT_MAILSLOT_NTLOGON, nbtd_mailslot_ntlogon_handler },
{ NBT_MAILSLOT_BROWSE, nbtd_mailslot_browse_handler }
};
diff --git a/source4/torture/nbt/dgram.c b/source4/torture/nbt/dgram.c
index b62c41b17d..14d98fc0c0 100644
--- a/source4/torture/nbt/dgram.c
+++ b/source4/torture/nbt/dgram.c
@@ -24,6 +24,7 @@
#include "libcli/nbt/libnbt.h"
#include "libcli/dgram/libdgram.h"
#include "librpc/gen_ndr/ndr_nbt.h"
+#include "librpc/gen_ndr/ndr_samr.h"
#include "lib/socket/socket.h"
#include "lib/events/events.h"
@@ -61,7 +62,7 @@ static BOOL nbt_test_netlogon(TALLOC_CTX *mem_ctx,
{
struct dgram_mailslot_handler *dgmslot;
struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(mem_ctx, NULL);
- const char *myaddress = talloc_strdup(mem_ctx, iface_best_ip(address));
+ const char *myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
struct nbt_netlogon_packet logon;
struct nbt_name myname;
NTSTATUS status;
@@ -117,6 +118,112 @@ failed:
/*
+ reply handler for ntlogon request
+*/
+static void ntlogon_handler(struct dgram_mailslot_handler *dgmslot,
+ struct nbt_dgram_packet *packet,
+ const char *src_address, int src_port)
+{
+ NTSTATUS status;
+ struct nbt_ntlogon_packet ntlogon;
+ int *replies = dgmslot->private;
+
+ printf("ntlogon reply from %s:%d\n", src_address, src_port);
+
+ status = dgram_mailslot_ntlogon_parse(dgmslot, dgmslot, packet, &ntlogon);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to parse ntlogon packet from %s:%d\n",
+ src_address, src_port);
+ return;
+ }
+
+ NDR_PRINT_DEBUG(nbt_ntlogon_packet, &ntlogon);
+
+ (*replies)++;
+}
+
+
+/* test UDP/138 ntlogon requests */
+static BOOL nbt_test_ntlogon(TALLOC_CTX *mem_ctx,
+ struct nbt_name name, const char *address)
+{
+ struct dgram_mailslot_handler *dgmslot;
+ struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(mem_ctx, NULL);
+ const char *myaddress = talloc_strdup(dgmsock, iface_best_ip(address));
+ struct nbt_ntlogon_packet logon;
+ struct nbt_name myname;
+ NTSTATUS status;
+ struct timeval tv = timeval_current();
+ int replies = 0;
+ struct test_join *join_ctx;
+ const char *password;
+ const char *dom_sid;
+
+ join_ctx = torture_join_domain(TEST_NAME, lp_workgroup(),
+ ACB_WSTRUST, &password);
+ if (join_ctx == NULL) {
+ printf("Failed to join domain %s as %s\n", lp_workgroup(), TEST_NAME);
+ talloc_free(dgmsock);
+ return False;
+ }
+
+ dom_sid = torture_join_sid(join_ctx);
+
+ /* try receiving replies on port 138 first, which will only
+ work if we are root and smbd/nmbd are not running - fall
+ back to listening on any port, which means replies from
+ some windows versions won't be seen */
+ status = socket_listen(dgmsock->sock, myaddress, lp_dgram_port(), 0, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ socket_listen(dgmsock->sock, myaddress, 0, 0, 0);
+ }
+
+ /* setup a temporary mailslot listener for replies */
+ dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
+ ntlogon_handler, &replies);
+
+
+ ZERO_STRUCT(logon);
+ logon.command = NTLOGON_SAM_LOGON;
+ logon.req.logon.request_count = 0;
+ logon.req.logon.computer_name = TEST_NAME;
+ logon.req.logon.user_name = TEST_NAME"$";
+ logon.req.logon.mailslot_name = dgmslot->mailslot_name;
+ logon.req.logon.acct_control = ACB_WSTRUST;
+ logon.req.logon.sid = *dom_sid_parse_talloc(dgmslot, dom_sid);
+ logon.req.logon.nt_version = 1;
+ logon.req.logon.lmnt_token = 0xFFFF;
+ logon.req.logon.lm20_token = 0xFFFF;
+
+
+ myname.name = TEST_NAME;
+ myname.type = NBT_NAME_CLIENT;
+ myname.scope = NULL;
+
+ status = dgram_mailslot_ntlogon_send(dgmsock, &name, address,
+ 0, &myname, &logon);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to send ntlogon request - %s\n", nt_errstr(status));
+ goto failed;
+ }
+
+
+ while (timeval_elapsed(&tv) < 5 && replies == 0) {
+ event_loop_once(dgmsock->event_ctx);
+ }
+
+ torture_leave_domain(join_ctx);
+ talloc_free(dgmsock);
+ return True;
+
+failed:
+ torture_leave_domain(join_ctx);
+ talloc_free(dgmsock);
+ return False;
+}
+
+
+/*
test nbt dgram operations
*/
BOOL torture_nbt_dgram(void)
@@ -127,7 +234,7 @@ BOOL torture_nbt_dgram(void)
NTSTATUS status;
BOOL ret = True;
- name.name = lp_parm_string(-1, "torture", "host");
+ name.name = lp_workgroup();
name.type = NBT_NAME_PDC;
name.scope = NULL;
@@ -141,6 +248,7 @@ BOOL torture_nbt_dgram(void)
}
ret &= nbt_test_netlogon(mem_ctx, name, address);
+ ret &= nbt_test_ntlogon(mem_ctx, name, address);
talloc_free(mem_ctx);
diff --git a/source4/torture/rpc/testjoin.c b/source4/torture/rpc/testjoin.c
index 5e4c5a32f3..270d8ff7b7 100644
--- a/source4/torture/rpc/testjoin.c
+++ b/source4/torture/rpc/testjoin.c
@@ -32,6 +32,7 @@
struct test_join {
struct dcerpc_pipe *p;
struct policy_handle user_handle;
+ const char *dom_sid;
};
@@ -156,6 +157,8 @@ struct test_join *torture_create_testuser(const char *username,
goto failed;
}
+ join->dom_sid = dom_sid_string(join, l.out.sid);
+
o.in.connect_handle = &handle;
o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
o.in.sid = l.out.sid;
@@ -309,6 +312,14 @@ void torture_leave_domain(struct test_join *join)
talloc_free(join);
}
+/*
+ return the dom sid for a test join
+*/
+const char *torture_join_sid(struct test_join *join)
+{
+ return join->dom_sid;
+}
+
struct test_join_ads_dc {
struct test_join *join;