mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
r6321: added IDL and test suite for NBT dgram 'sam logon' request (sent by
clients when a user tries to login)
This commit is contained in:
parent
4507bdc339
commit
08ded62156
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
117
source/libcli/dgram/ntlogon.c
Normal file
117
source/libcli/dgram/ntlogon.c
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
76
source/nbt_server/dgram/ntlogon.c
Normal file
76
source/nbt_server/dgram/ntlogon.c
Normal file
@ -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);
|
||||
}
|
@ -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 }
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user