1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-02 09:47:23 +03:00

r6573: Start on my project to implement an NT4 compatible BDC in Samba4.

This brings in a compatability layer for Samba3 in Samba4 - where we
will start to define file formats and similar details.

The 'net samdump' command uses 'password server = ' for now, and
performs a similar task to Samba3's 'net rpc samsync'.

Andrew Bartlett
(This used to be commit 550f17f9924fe783917318753de7d1a388423908)
This commit is contained in:
Andrew Bartlett 2005-05-02 14:17:19 +00:00 committed by Gerald (Jerry) Carter
parent 591ff7675d
commit 8bf57cf8f5
14 changed files with 577 additions and 2 deletions

View File

@ -201,3 +201,6 @@ struct wrepl_pull_table;
struct wrepl_pull_names; struct wrepl_pull_names;
struct arcfour_state; struct arcfour_state;
union libnet_SamDump;

View File

@ -40,6 +40,15 @@ INIT_OBJ_FILES = \
# End SUBSYSTEM LIBCOMPRESION # End SUBSYSTEM LIBCOMPRESION
################################################ ################################################
################################################
# Start SUBSYSTEM LIBSAMBA3
[SUBSYSTEM::LIBSAMBA3]
INIT_OBJ_FILES = \
lib/samba3/smbpasswd.o
# End SUBSYSTEM LIBSAMBA3
################################################
############################## ##############################
# Start SUBSYSTEM LIBBASIC # Start SUBSYSTEM LIBBASIC
[SUBSYSTEM::LIBBASIC] [SUBSYSTEM::LIBBASIC]

View File

@ -458,6 +458,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
"samAccountName", "samAccountName",
"flatname", "flatname",
"realm", "realm",
"secureChannelType",
NULL NULL
}; };
@ -512,7 +513,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
} }
sct = ldb_msg_find_int(msgs[0], "secureChannelType", 0); sct = ldb_msg_find_int(msgs[0], "secureChannelType", 0);
if (!sct) { if (sct) {
cli_credentials_set_secure_channel_type(cred, sct); cli_credentials_set_secure_channel_type(cred, sct);
} else { } else {
DEBUG(1, ("Domain join for acocunt %s did not have a secureChannelType set!\n", DEBUG(1, ("Domain join for acocunt %s did not have a secureChannelType set!\n",

View File

@ -0,0 +1,5 @@
This directory contains various files and functions for the purpose of
Samba3 import, migration and compatability.
For example, the first file in this directory (smbpasswd.c) handles
portions of the smbpasswd file format.

View File

@ -0,0 +1,208 @@
/*
Unix SMB/CIFS implementation.
smbpasswd file format routines
Copyright (C) Andrew Tridgell 1992-1998
Modified by Jeremy Allison 1995.
Modified by Gerald (Jerry) Carter 2000-2001
Copyright (C) Tim Potter 2001
Copyright (C) Andrew Bartlett <abartlet@samba.org> 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.
*/
/*! \file lib/smbpasswd.c
The smbpasswd file is used to store encrypted passwords in a similar
fashion to the /etc/passwd file. The format is colon separated fields
with one user per line like so:
<username>:<uid>:<lanman hash>:<nt hash>:<acb info>:<last change time>
The username and uid must correspond to an entry in the /etc/passwd
file. The lanman and nt password hashes are 32 hex digits corresponding
to the 16-byte lanman and nt hashes respectively.
The password last change time is stored as a string of the format
LCD-<change time> where the change time is expressed as an
'N' No password
'D' Disabled
'H' Homedir required
'T' Temp account.
'U' User account (normal)
'M' MNS logon user account - what is this ?
'W' Workstation account
'S' Server account
'L' Locked account
'X' No Xpiry on password
'I' Interdomain trust account
*/
#include "includes.h"
#include "librpc/gen_ndr/ndr_samr.h"
#include "system/iconv.h"
/*! Convert 32 hex characters into a 16 byte array. */
struct samr_Password *smbpasswd_gethexpwd(TALLOC_CTX *mem_ctx, char *p)
{
int i;
unsigned char lonybble, hinybble;
const char *hexchars = "0123456789ABCDEF";
char *p1, *p2;
struct samr_Password *pwd = talloc(mem_ctx, struct samr_Password);
if (!p) return NULL;
for (i = 0; i < (sizeof(pwd->hash) * 2); i += 2)
{
hinybble = toupper(p[i]);
lonybble = toupper(p[i + 1]);
p1 = strchr_m(hexchars, hinybble);
p2 = strchr_m(hexchars, lonybble);
if (!p1 || !p2)
{
return (False);
}
hinybble = PTR_DIFF(p1, hexchars);
lonybble = PTR_DIFF(p2, hexchars);
pwd->hash[i / 2] = (hinybble << 4) | lonybble;
}
return pwd;
}
/*! Convert a 16-byte array into 32 hex characters. */
struct samr_Password *lm_hash_p = NULL;
struct samr_Password *nt_hash_p = NULL;
char *smbpasswd_sethexpwd(TALLOC_CTX *mem_ctx, struct samr_Password *pwd, uint16_t acb_info)
{
char *p;
if (pwd != NULL) {
int i;
p = talloc_array(mem_ctx, char, 33);
if (!p) {
return NULL;
}
for (i = 0; i < sizeof(pwd->hash); i++)
slprintf(&p[i*2], 3, "%02X", pwd->hash[i]);
} else {
if (acb_info & ACB_PWNOTREQ)
p = talloc_strdup(mem_ctx, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
else
p = talloc_strdup(mem_ctx, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
}
return p;
}
/*! Decode the account control bits (ACB) info from a string. */
uint16_t smbpasswd_decode_acb_info(const char *p)
{
uint16_t acb_info = 0;
BOOL finished = False;
/*
* Check if the account type bits have been encoded after the
* NT password (in the form [NDHTUWSLXI]).
*/
if (*p != '[') return 0;
for (p++; *p && !finished; p++)
{
switch (*p) {
case 'N': /* 'N'o password. */
acb_info |= ACB_PWNOTREQ;
break;
case 'D': /* 'D'isabled. */
acb_info |= ACB_DISABLED;
break;
case 'H': /* 'H'omedir required. */
acb_info |= ACB_HOMDIRREQ;
break;
case 'T': /* 'T'emp account. */
acb_info |= ACB_TEMPDUP;
break;
case 'U': /* 'U'ser account (normal). */
acb_info |= ACB_NORMAL;
break;
case 'M': /* 'M'NS logon user account. What is this ? */
acb_info |= ACB_MNS;
break;
case 'W': /* 'W'orkstation account. */
acb_info |= ACB_WSTRUST;
break;
case 'S': /* 'S'erver account. */
acb_info |= ACB_SVRTRUST;
break;
case 'L': /* 'L'ocked account. */
acb_info |= ACB_AUTOLOCK;
break;
case 'X': /* No 'X'piry on password */
acb_info |= ACB_PWNOEXP;
break;
case 'I': /* 'I'nterdomain trust account. */
acb_info |= ACB_DOMTRUST;
break;
case ' ':
break;
case ':':
case '\n':
case '\0':
case ']':
default:
finished = True;
break;
}
}
return acb_info;
}
/*! Encode account control bits (ACBs) into a string. */
char *smbpasswd_encode_acb_info(TALLOC_CTX *mem_ctx, uint16_t acb_info)
{
char *acct_str = talloc_array(mem_ctx, char, 35);
size_t i = 0;
acct_str[i++] = '[';
if (acb_info & ACB_PWNOTREQ ) acct_str[i++] = 'N';
if (acb_info & ACB_DISABLED ) acct_str[i++] = 'D';
if (acb_info & ACB_HOMDIRREQ) acct_str[i++] = 'H';
if (acb_info & ACB_TEMPDUP ) acct_str[i++] = 'T';
if (acb_info & ACB_NORMAL ) acct_str[i++] = 'U';
if (acb_info & ACB_MNS ) acct_str[i++] = 'M';
if (acb_info & ACB_WSTRUST ) acct_str[i++] = 'W';
if (acb_info & ACB_SVRTRUST ) acct_str[i++] = 'S';
if (acb_info & ACB_AUTOLOCK ) acct_str[i++] = 'L';
if (acb_info & ACB_PWNOEXP ) acct_str[i++] = 'X';
if (acb_info & ACB_DOMTRUST ) acct_str[i++] = 'I';
acct_str[i++] = ']';
acct_str[i++] = '\0';
return acct_str;
}

View File

@ -395,6 +395,7 @@ char *StrnCpy(char *dest,const char *src,size_t n)
valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n" valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
**/ **/
size_t strhex_to_str(char *p, size_t len, const char *strhex) size_t strhex_to_str(char *p, size_t len, const char *strhex)
{ {

View File

@ -8,9 +8,10 @@ ADD_OBJ_FILES = \
libnet/libnet_time.o \ libnet/libnet_time.o \
libnet/libnet_rpc.o \ libnet/libnet_rpc.o \
libnet/libnet_join.o \ libnet/libnet_join.o \
libnet/libnet_vampire.o \
libnet/libnet_user.o \ libnet/libnet_user.o \
libnet/userinfo.o \ libnet/userinfo.o \
libnet/userman.o libnet/userman.o
REQUIRED_SUBSYSTEMS = RPC_NDR_SAMR RPC_NDR_SRVSVC LIBCLI_COMPOSITE REQUIRED_SUBSYSTEMS = RPC_NDR_SAMR RPC_NDR_SRVSVC LIBCLI_COMPOSITE LIBSAMBA3
# End SUBSYSTEM LIBNET # End SUBSYSTEM LIBNET
################################# #################################

View File

@ -32,4 +32,5 @@ struct libnet_context {
#include "libnet/libnet_time.h" #include "libnet/libnet_time.h"
#include "libnet/libnet_rpc.h" #include "libnet/libnet_rpc.h"
#include "libnet/libnet_join.h" #include "libnet/libnet_join.h"
#include "libnet/libnet_vampire.h"
#include "libnet/libnet_user.h" #include "libnet/libnet_user.h"

View File

@ -0,0 +1,225 @@
/*
Unix SMB/CIFS implementation.
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-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 "libnet/libnet.h"
#include "librpc/gen_ndr/ndr_netlogon.h"
#include "librpc/gen_ndr/ndr_samr.h"
static BOOL vampire_samdump_handle_user(TALLOC_CTX *mem_ctx,
struct creds_CredentialState *creds,
struct netr_DELTA_ENUM *delta)
{
uint32_t rid = delta->delta_id_union.rid;
struct netr_DELTA_USER *user = delta->delta_union.user;
struct samr_Password lm_hash;
struct samr_Password nt_hash;
struct samr_Password *lm_hash_p = NULL;
struct samr_Password *nt_hash_p = NULL;
const char *username = user->account_name.string;
char *hex_lm_password;
char *hex_nt_password;
NTSTATUS nt_status;
if (user->lm_password_present) {
sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0);
lm_hash_p = &lm_hash;
}
if (user->nt_password_present) {
sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0);
nt_hash_p = &nt_hash;
}
if (user->user_private_info.SensitiveData) {
DATA_BLOB data;
struct netr_USER_KEYS keys;
data.data = user->user_private_info.SensitiveData;
data.length = user->user_private_info.DataLength;
creds_arcfour_crypt(creds, data.data, data.length);
nt_status = ndr_pull_struct_blob(&data, mem_ctx, &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
if (NT_STATUS_IS_OK(nt_status)) {
if (keys.keys.keys2.lmpassword.length == 16) {
sam_rid_crypt(rid, keys.keys.keys2.lmpassword.pwd.hash, lm_hash.hash, 0);
lm_hash_p = &lm_hash;
}
if (keys.keys.keys2.ntpassword.length == 16) {
sam_rid_crypt(rid, keys.keys.keys2.ntpassword.pwd.hash, nt_hash.hash, 0);
nt_hash_p = &nt_hash;
}
} else {
printf("Failed to parse Sensitive Data for %s:\n", username);
dump_data(10, data.data, data.length);
return False;
}
}
hex_lm_password = smbpasswd_sethexpwd(mem_ctx, lm_hash_p, user->acct_flags);
hex_nt_password = smbpasswd_sethexpwd(mem_ctx, nt_hash_p, user->acct_flags);
printf("%s:%d:%s:%s:%s:LCT-%08X\n", username,
rid, hex_lm_password, hex_nt_password,
smbpasswd_encode_acb_info(mem_ctx, user->acct_flags),
(unsigned int)nt_time_to_unix(user->last_password_change));
return True;
}
static NTSTATUS libnet_SamDump_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SamDump *r)
{
NTSTATUS nt_status;
TALLOC_CTX *loop_ctx, *delta_ctx;
struct creds_CredentialState *creds;
struct netr_DatabaseSync dbsync;
struct cli_credentials *machine_account;
struct dcerpc_binding *b;
struct dcerpc_pipe *p;
/* TODO: This is bogus */
const char **bindings = lp_passwordserver();
const char *binding;
if (bindings && bindings[0]) {
binding = bindings[0];
}
machine_account = cli_credentials_init(mem_ctx);
if (!machine_account) {
return NT_STATUS_NO_MEMORY;
}
cli_credentials_set_conf(machine_account);
nt_status = cli_credentials_set_machine_account(machine_account);
if (!NT_STATUS_IS_OK(nt_status)) {
r->netlogon.error_string = talloc_strdup(mem_ctx, "Could not obtain machine account password - are we joined to the domain?");
return nt_status;
}
if (cli_credentials_get_secure_channel_type(machine_account) != SEC_CHAN_BDC) {
r->netlogon.error_string
= talloc_asprintf(mem_ctx,
"Our join to domain %s is not as a BDC (%d), please rejoin as a BDC",
cli_credentials_get_secure_channel_type(machine_account),
cli_credentials_get_domain(machine_account));
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
/* Connect to DC (take a binding string for now) */
nt_status = dcerpc_parse_binding(mem_ctx, binding, &b);
if (!NT_STATUS_IS_OK(nt_status)) {
r->netlogon.error_string = talloc_asprintf(mem_ctx, "Bad binding string %s\n", binding);
return NT_STATUS_INVALID_PARAMETER;
}
/* We like schannel */
b->flags &= ~DCERPC_AUTH_OPTIONS;
b->flags |= DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_128;
/* Setup schannel */
nt_status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
DCERPC_NETLOGON_UUID,
DCERPC_NETLOGON_VERSION,
machine_account);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
/* call domain logon */
nt_status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
dbsync.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
dbsync.in.computername = cli_credentials_get_workstation(machine_account);
dbsync.in.preferredmaximumlength = (uint32_t)-1;
ZERO_STRUCT(dbsync.in.return_authenticator);
dbsync.in.sync_context = 0;
dbsync.in.database_id = SAM_DATABASE_DOMAIN;
do {
int d;
loop_ctx = talloc_named(mem_ctx, 0, "DatabaseSync loop context");
creds_client_authenticator(creds, &dbsync.in.credential);
nt_status = dcerpc_netr_DatabaseSync(p, loop_ctx, &dbsync);
if (!NT_STATUS_IS_OK(nt_status) &&
!NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES)) {
printf("DatabaseSync - %s\n", nt_errstr(nt_status));
return nt_status;
}
if (!creds_client_check(creds, &dbsync.out.return_authenticator.cred)) {
printf("Credential chaining failed\n");
}
dbsync.in.sync_context = dbsync.out.sync_context;
for (d=0; d < dbsync.out.delta_enum_array->num_deltas; d++) {
delta_ctx = talloc_named(loop_ctx, 0, "DatabaseSync delta context");
switch (dbsync.out.delta_enum_array->delta_enum[d].delta_type) {
case NETR_DELTA_USER:
if (!vampire_samdump_handle_user(delta_ctx,
creds,
&dbsync.out.delta_enum_array->delta_enum[d])) {
return NT_STATUS_INVALID_PARAMETER;
}
break;
}
talloc_free(delta_ctx);
}
talloc_free(loop_ctx);
} while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
return NT_STATUS_OK;
}
NTSTATUS libnet_SamDump_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SamDump *r)
{
NTSTATUS nt_status;
union libnet_SamDump r2;
r2.generic.level = LIBNET_SAMDUMP_NETLOGON;
r2.generic.error_string = NULL;
nt_status = libnet_SamDump(ctx, mem_ctx, &r2);
r->generic.error_string = r2.netlogon.error_string;
return nt_status;
}
NTSTATUS libnet_SamDump(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SamDump *r)
{
switch (r->generic.level) {
case LIBNET_SAMDUMP_GENERIC:
return libnet_SamDump_generic(ctx, mem_ctx, r);
case LIBNET_SAMDUMP_NETLOGON:
return libnet_SamDump_netlogon(ctx, mem_ctx, r);
}
return NT_STATUS_INVALID_LEVEL;
}

View File

@ -0,0 +1,40 @@
/*
Unix SMB/CIFS implementation.
Copyright (C) Andrew Bartlett <abartlet@samba.org> 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 "librpc/gen_ndr/ndr_netlogon.h"
/* struct and enum for doing a remote domain join */
enum libnet_SamDump_level {
LIBNET_SAMDUMP_GENERIC,
LIBNET_SAMDUMP_NETLOGON,
};
union libnet_SamDump {
struct {
enum libnet_SamDump_level level;
char *error_string;
} generic;
struct {
enum libnet_SamDump_level level;
char *error_string;
} netlogon;
};

View File

@ -181,17 +181,28 @@ struct ldb_context *secrets_db_connect(TALLOC_CTX *mem_ctx)
{ {
char *path; char *path;
struct ldb_context *ldb; struct ldb_context *ldb;
BOOL existed;
const char *init_ldif =
"dn: @ATTRIBUTES\n" \
"computerName: CASE_INSENSITIVE\n" \
"flatname: CASE_INSENSITIVE\n";
path = private_path(mem_ctx, "secrets.ldb"); path = private_path(mem_ctx, "secrets.ldb");
if (!path) { if (!path) {
return NULL; return NULL;
} }
existed = file_exists(path);
ldb = ldb_wrap_connect(mem_ctx, path, 0, NULL); ldb = ldb_wrap_connect(mem_ctx, path, 0, NULL);
talloc_free(path); talloc_free(path);
if (!ldb) { if (!ldb) {
return NULL; return NULL;
} }
if (!existed) {
gendb_add_ldif(ldb, init_ldif);
}
return ldb; return ldb;
} }

View File

@ -8,6 +8,7 @@ OBJ_FILES = \
utils/net/net_password.o \ utils/net/net_password.o \
utils/net/net_time.o \ utils/net/net_time.o \
utils/net/net_join.o \ utils/net/net_join.o \
utils/net/net_vampire.o \
utils/net/net_user.o utils/net/net_user.o
REQUIRED_SUBSYSTEMS = \ REQUIRED_SUBSYSTEMS = \
CONFIG \ CONFIG \

View File

@ -105,6 +105,7 @@ static const struct net_functable net_functable[] = {
{"password", "change password\n", net_password, net_password_usage}, {"password", "change password\n", net_password, net_password_usage},
{"time", "get remote server's time\n", net_time, net_time_usage}, {"time", "get remote server's time\n", net_time, net_time_usage},
{"join", "join a domain\n", net_join, net_join_usage}, {"join", "join a domain\n", net_join, net_join_usage},
{"samdump", "dump the sam of a domain\n", net_samdump, net_samdump_usage},
{"user", "manage user accounts\n", net_user, net_user_usage}, {"user", "manage user accounts\n", net_user, net_user_usage},
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };

View File

@ -0,0 +1,68 @@
/*
Samba Unix/Linux SMB client library
Distributed SMB/CIFS Server Management Utility
Copyright (C) 2004 Stefan Metzmacher <metze@samba.org>
Copyright (C) 2005 Andrew Bartlett <abartlet@samba.org>
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 "utils/net/net.h"
#include "libnet/libnet.h"
#include "librpc/gen_ndr/ndr_samr.h"
int net_samdump(struct net_context *ctx, int argc, const char **argv)
{
NTSTATUS status;
struct libnet_context *libnetctx;
union libnet_SamDump r;
libnetctx = libnet_context_init();
if (!libnetctx) {
return -1;
}
libnetctx->credentials = ctx->credentials;
/* prepare password change */
r.generic.level = LIBNET_SAMDUMP_GENERIC;
r.generic.error_string = NULL;
/* do the domain join */
status = libnet_SamDump(libnetctx, ctx->mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("libnet_SamDump returned %s: %s\n",
nt_errstr(status),
r.generic.error_string));
return -1;
}
libnet_context_destroy(&libnetctx);
return 0;
}
int net_samdump_usage(struct net_context *ctx, int argc, const char **argv)
{
d_printf("net samdump\n");
return 0;
}
int net_samdump_help(struct net_context *ctx, int argc, const char **argv)
{
d_printf("Dumps the sam of the domain we are joined to.\n");
return 0;
}