r6321: added IDL and test suite for NBT dgram 'sam logon' request (sent by
authorAndrew Tridgell <tridge@samba.org>
Wed, 13 Apr 2005 05:07:04 +0000 (05:07 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:11:31 +0000 (13:11 -0500)
clients when a user tries to login)

source/libcli/config.mk
source/libcli/dgram/libdgram.h
source/libcli/dgram/ntlogon.c [new file with mode: 0644]
source/librpc/idl/nbt.idl
source/nbt_server/config.mk
source/nbt_server/dgram/ntlogon.c [new file with mode: 0644]
source/nbt_server/dgram/request.c
source/torture/nbt/dgram.c
source/torture/rpc/testjoin.c

index 56e923daa2e2f74229ce5bf0980e4139f7af97bf..def7bd0f2748c16a677d7d09601330bcd1a29997 100644 (file)
@@ -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
 
index 163cb1e37deb6c42fe83eadd55bafd7034b2f45a..af278d2ab69c7f410fd3d55e7c9b498f0c532518 100644 (file)
@@ -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/source/libcli/dgram/ntlogon.c b/source/libcli/dgram/ntlogon.c
new file mode 100644 (file)
index 0000000..7f18e8c
--- /dev/null
@@ -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;
+}
index c03f30333efd0fbfd471c174c72b400f8e3e2837..d7c89966f15652e6061142ecbcf2a60ecb215c73 100644 (file)
           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";
 
        } nbt_dgram_packet;
 
 
+       /*******************************************/
        /* \MAILSLOT\NET\NETLOGON mailslot requests */
        typedef enum {
                NETLOGON_QUERY_FOR_PDC     = 0x7,       
                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;
                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;
+       
 }
index 04a9dde1b0adac504bc0373c27648c44cb0cdc7b..7576bf334939c8c3bfde2e3ca292b115464076e2 100644 (file)
@@ -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/source/nbt_server/dgram/ntlogon.c b/source/nbt_server/dgram/ntlogon.c
new file mode 100644 (file)
index 0000000..d035c2f
--- /dev/null
@@ -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);
+}
index 59b94bcecb0d36f8952486889ad063c1d89a54e7..f59193bec5e72ccbd70329df6f5214951a6f62c2 100644 (file)
@@ -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 }
 };
 
index b62c41b17d854e7803347c4a29cdba6d60038a1a..14d98fc0c0493e4bbbe59c3af5ae7f66010ccb7b 100644 (file)
@@ -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;
@@ -116,6 +117,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
 */
@@ -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);
 
index 5e4c5a32f31fa5bd24967430e145e518bed81e15..270d8ff7b774ecc64e0c1c2209cb4ce1393945a5 100644 (file)
@@ -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;