first bigger domain trusts patch
Rafal Szczesniak
mimir at diament.ists.pwr.wroc.pl
Wed Feb 13 13:35:15 GMT 2002
This is a patch extending functionality of the 'net' tool. It makes
possible to create trusting domain account on remote rpc server. This
doesn't include samba yet, since samba rpc server can create normal
accounts but not trusting domain's one. Work is in progress, although more
important things (like auth code) are waiting to be finished...
Patch enables also establishing trust to a trusted domain. Initial
password is stored in secrets.tdb. What 'net' can't do yet is to delete
trusting domain's account as well as delete trust to a trusted domain. So
be careful! :)
I've defined some new functions to avoid modifying existing (like in case
of rpc_user_add_internals call from net_rpc.c). If I can modify them, then
of course I'll do that to simplify the code.
Any suggestions/feedbacks are welcome as I know this code is far from
being perfect yet. Of course it needs thorough testing...
cheers,
+------------------------------------------------------------+
|Rafal 'Mimir' Szczesniak <mimir at diament.ists.pwr.wroc.pl> |
|*BSD, GNU/Linux and Samba /
|__________________________________________________________/
-------------- next part --------------
diff -Nur samba/source/auth/auth_util.c head/source/auth/auth_util.c
--- samba/source/auth/auth_util.c Wed Jan 30 07:08:13 2002
+++ head/source/auth/auth_util.c Thu Jan 31 01:42:26 2002
@@ -123,7 +123,7 @@
ZERO_STRUCTP(*user_info);
- DEBUG(5,("makeing strings for %s's user_info struct\n", internal_username));
+ DEBUG(5,("making strings for %s's user_info struct\n", internal_username));
(*user_info)->smb_name.str = strdup(smb_name);
if ((*user_info)->smb_name.str) {
@@ -195,7 +195,6 @@
fstring internal_username;
fstrcpy(internal_username, smb_name);
map_username(internal_username);
-
if (lp_allow_trusted_domains()) {
/* the client could have given us a workstation name
or other crap for the workgroup - we really need a
diff -Nur samba/source/include/includes.h head/source/include/includes.h
--- samba/source/include/includes.h Wed Jan 30 07:08:14 2002
+++ head/source/include/includes.h Wed Feb 13 02:05:57 2002
@@ -699,7 +699,6 @@
#include "hash.h"
#include "trans2.h"
#include "nterr.h"
-#include "secrets.h"
#include "messages.h"
#include "util_list.h"
#include "charset.h"
@@ -717,6 +716,8 @@
#include "smb.h"
#include "smbw.h"
#include "nameserv.h"
+
+#include "secrets.h"
#include "byteorder.h"
diff -Nur samba/source/include/secrets.h head/source/include/secrets.h
--- samba/source/include/secrets.h Wed Jan 30 07:08:15 2002
+++ head/source/include/secrets.h Wed Feb 13 01:56:30 2002
@@ -22,18 +22,31 @@
#define _SECRETS_H
/* the first one is for the hashed password (NT4 style) the latter
- for plaintext (ADS
+ for plaintext (ADS)
*/
#define SECRETS_MACHINE_ACCT_PASS "SECRETS/$MACHINE.ACC"
#define SECRETS_MACHINE_PASSWORD "SECRETS/MACHINE_PASSWORD"
+/* this one is for storing trusted domain account password */
+#define SECRETS_DOMTRUST_ACCT_PASS "SECRETS/$DOMTRUST.ACC"
+
#define SECRETS_DOMAIN_SID "SECRETS/SID"
#define SECRETS_SAM_SID "SAM/SID"
+/* structure for storing machine account password
+ (ie. when samba server is member of a domain */
struct machine_acct_pass {
uint8 hash[16];
time_t mod_time;
};
+
+/* structure for storing trusted domain password */
+struct trusted_dom_pass {
+ uint8 hash[16];
+ time_t mod_time;
+ DOM_SID domain_sid; /* remote domain's sid */
+};
+
#endif /* _SECRETS_H */
diff -Nur samba/source/libsmb/cli_lsarpc.c head/source/libsmb/cli_lsarpc.c
--- samba/source/libsmb/cli_lsarpc.c Wed Feb 13 17:44:49 2002
+++ head/source/libsmb/cli_lsarpc.c Wed Feb 13 18:12:45 2002
@@ -108,7 +108,9 @@
return result;
}
-/** Open a LSA policy handle */
+/** Open a LSA policy handle
+/ *
+/ * @param cli Handle on an initialised SMB connection */
NTSTATUS cli_lsa_open_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
BOOL sec_qos, uint32 des_access, POLICY_HND *pol)
@@ -131,10 +133,10 @@
if (sec_qos) {
init_lsa_sec_qos(&qos, 2, 1, 0);
- init_q_open_pol2(&q, cli->clnt_name_slash, 0, des_access,
+ init_q_open_pol2(&q, cli->srv_name_slash, 0, des_access,
&qos);
} else {
- init_q_open_pol2(&q, cli->clnt_name_slash, 0, des_access,
+ init_q_open_pol2(&q, cli->srv_name_slash, 0, des_access,
NULL);
}
@@ -435,7 +437,9 @@
return result;
}
-/** Query info policy */
+/** Query info policy
+ *
+ * @param domain_sid - returned remote server's domain sid */
NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint16 info_class,
diff -Nur samba/source/libsmb/clientgen.c head/source/libsmb/clientgen.c
--- samba/source/libsmb/clientgen.c Wed Jan 30 07:08:18 2002
+++ head/source/libsmb/clientgen.c Mon Feb 11 01:01:31 2002
@@ -138,7 +138,7 @@
/****************************************************************************
-initialise a client structure
+initialise credentials of a client structure
****************************************************************************/
void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr)
{
diff -Nur samba/source/passdb/secrets.c head/source/passdb/secrets.c
--- samba/source/passdb/secrets.c Wed Jan 30 07:08:25 2002
+++ head/source/passdb/secrets.c Wed Feb 13 18:57:32 2002
@@ -136,7 +136,20 @@
}
/************************************************************************
- Routine to get the trust account password for a domain.
+form a key for fetching a trusted domain password
+************************************************************************/
+char *trustdom_keystr(char *domain)
+{
+ static fstring keystr;
+
+ slprintf(keystr,sizeof(keystr)-1,"%s/%s",
+ SECRETS_DOMTRUST_ACCT_PASS, domain);
+
+ return keystr;
+}
+
+/************************************************************************
+ Routine to get the machine trust account password for a domain.
************************************************************************/
BOOL secrets_fetch_trust_account_password(char *domain, uint8 ret_pwd[16],
time_t *pass_last_set_time)
@@ -170,6 +183,32 @@
return True;
}
+/************************************************************************
+ Routine to get account password to trusted domain
+************************************************************************/
+BOOL secrets_fetch_trusted_domain_password(char *domain, uint8 pwd[16],
+ DOM_SID sid, time_t *pass_last_set_time)
+{
+ struct trusted_dom_pass *pass;
+ size_t size;
+
+ if (!(pass = secrets_fetch(trustdom_keystr(domain), &size))) {
+ DEBUG(5, ("secrets_fetch failed!\n"));
+ return False;
+ }
+
+ if (size != sizeof(*pass)) {
+ DEBUG(0, ("secrets were of incorrect size!\n"));
+ return False;
+ }
+
+ if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
+ memcpy(pwd, pass->hash, 16);
+ memcpy(&sid, &(pass->domain_sid), sizeof(sid));
+ SAFE_FREE(pass);
+
+ return True;
+}
/************************************************************************
Routine to set the trust account password for a domain.
@@ -185,6 +224,21 @@
}
/************************************************************************
+ Routine to set the password for trusted domain
+************************************************************************/
+BOOL secrets_store_trusted_domain_password(char* domain, uint8 new_pwd[16],
+ DOM_SID sid)
+{
+ struct trusted_dom_pass pass;
+
+ pass.mod_time = time(NULL);
+ memcpy(pass.hash, new_pwd, 16);
+ memcpy(&(pass.domain_sid), &sid, sizeof(sid));
+
+ return secrets_store(trustdom_keystr(domain), (void *)&pass, sizeof(pass));
+}
+
+/************************************************************************
Routine to set the plaintext machine account password for a realm
the password is assumed to be a null terminated ascii string
************************************************************************/
@@ -206,13 +260,22 @@
/************************************************************************
- Routine to delete the trust account password file for a domain.
+ Routine to delete the machine trust account password file for a domain.
************************************************************************/
BOOL trust_password_delete(char *domain)
{
return secrets_delete(trust_keystr(domain));
}
+
+/************************************************************************
+ Routine to delete the password for trusted domain
+************************************************************************/
+BOOL trusted_domain_password_delete(char *domain)
+{
+ return secrets_delete(trustdom_keystr(domain));
+}
+
/*******************************************************************
Reset the 'done' variables so after a client process is created
diff -Nur samba/source/smbd/process.c head/source/smbd/process.c
--- samba/source/smbd/process.c Fri Feb 1 00:26:11 2002
+++ head/source/smbd/process.c Fri Feb 1 01:05:08 2002
@@ -818,7 +818,7 @@
}
/****************************************************************************
- process an smb from the client - split out from the process() code so
+ process an smb from the client - split out from the smbd_process() code so
it can be used by the oplock break code.
****************************************************************************/
void process_smb(char *inbuf, char *outbuf)
diff -Nur samba/source/smbd/server.c head/source/smbd/server.c
--- samba/source/smbd/server.c Fri Feb 1 00:26:11 2002
+++ head/source/smbd/server.c Fri Feb 1 01:05:08 2002
@@ -289,6 +289,13 @@
if (smbd_server_fd() != -1 && sys_fork()==0) {
/* Child code ... */
+ /*
+ * mimir: run-stopper to ease debugging
+ * of forked daemon
+ */
+
+ sleep(20);
+
/* close the listening socket(s) */
for(i = 0; i < num_interfaces; i++)
close(fd_listenset[i]);
diff -Nur samba/source/utils/net.c head/source/utils/net.c
--- samba/source/utils/net.c Wed Jan 30 07:08:43 2002
+++ head/source/utils/net.c Wed Feb 13 20:37:44 2002
@@ -232,6 +232,89 @@
return True;
}
+
+BOOL net_find_dc(struct in_addr *server_ip, char **server_name, char **domain_name)
+{
+ struct in_addr *ip_list;
+ int addr_count;
+
+ if (get_dc_list(True /* PDC only*/, *domain_name, &ip_list, &addr_count)) {
+ fstring dc_name;
+ if (addr_count < 1) {
+ return False;
+ }
+
+ *server_ip = *ip_list;
+
+ if (is_zero_ip(*server_ip))
+ return False;
+
+ if (!lookup_dc_name(global_myname, *domain_name, server_ip, dc_name))
+ return False;
+
+ *server_name = strdup(dc_name);
+ return True;
+ } else
+ return False;
+}
+
+/**
+ * Domain trust specific function. Does session setup request to remote domain's
+ * controller and returns nt status code. Function is used to verify validity
+ * of trusting domain account on remote domain's SAM as well as connection function
+ * to pdc of given domain.
+ *
+ * @param cli client structure
+ * @param domain_name remote domain name
+ * @param acct_name our domain's account in remote domain's SAM
+ * @param ntpwd nt hash of the specified trust password
+ *
+ * @return NTSTATUS returned by session setup request
+ **/
+
+NTSTATUS connect_to_trusted_dc(struct cli_state **cli, fstring domain_name,
+ fstring acct_name, uchar *ntpwd)
+{
+ NTSTATUS nt_status;
+ char* server_name = NULL;
+ struct in_addr server_ip;
+
+ /* find the domain controller */
+ if (!net_find_dc(&server_ip, &server_name, &domain_name)) {
+ DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name));
+ return NT_STATUS_UNSUCCESSFUL;
+
+ }
+
+ if (strequal(acct_name, "")) {
+
+ /* prepare anonymous connection */
+ opt_password = strdup("");
+ safe_strcpy(opt_workgroup, "", 2 /* FIXME: replace it with opt_workgroup length */);
+ } else {
+ if (!got_pass) {
+ char *pass = getpass("Password:");
+ if (pass) {
+ opt_password = strdup(pass);
+ }
+ }
+ /* generate nt hash of the password */
+ E_md4hash(opt_password, ntpwd);
+ }
+
+ /* connect to IPC$ */
+ nt_status = cli_full_connection(cli, opt_requester_name, server_name,
+ &server_ip, opt_port,
+ "IPC$", "IPC",
+ acct_name, domain_name,
+ opt_password, strlen(opt_password));
+
+ SAFE_FREE(server_name);
+
+ return nt_status;
+}
+
+
struct cli_state *net_make_ipc_connection(unsigned flags)
{
char *server_name = NULL;
@@ -265,13 +348,12 @@
static int help_usage(int argc, const char **argv)
{
- d_printf(
-"\n"\
-"Usage: net help <function>\n"\
-"\n"\
-"Valid functions are:\n"\
-" RPC RAP ADS FILE SHARE SESSION SERVER DOMAIN PRINTQ USER GROUP VALIDATE\n"\
-" GROUPMEMBER ADMIN SERVICE PASSWORD TIME LOOKUP\n");
+ d_printf("\n");
+ d_printf("Usage: net help <function>\n");
+ d_printf("\n");
+ d_printf("Valid functions are:\n");
+ d_printf(" RPC RAP ADS FILE SHARE SESSION SERVER DOMAIN PRINTQ USER GROUP VALIDATE\n");
+ d_printf(" GROUPMEMBER ADMIN SERVICE PASSWORD TIME LOOKUP\n");
return -1;
}
diff -Nur samba/source/utils/net.h head/source/utils/net.h
--- samba/source/utils/net.h Wed Jan 30 07:08:45 2002
+++ head/source/utils/net.h Sat Feb 9 16:25:32 2002
@@ -45,3 +45,4 @@
extern int opt_reboot;
extern int opt_force;
extern int opt_timeout;
+
diff -Nur samba/source/utils/net_rpc.c head/source/utils/net_rpc.c
--- samba/source/utils/net_rpc.c Wed Jan 30 07:08:45 2002
+++ head/source/utils/net_rpc.c Wed Feb 13 19:52:38 2002
@@ -302,9 +302,9 @@
* All paramaters are provided by the run_rpc_command funcion, except for
* argc, argv which are passes through.
*
- * @param domain_sid The domain sid aquired from the remote server
+ * @param domain_sid The domain sid acquired from the remote server
* @param cli A cli_state connected to the server.
- * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
* @param argc Standard main() style argc
* @param argc Standard main() style argv. Initial components are already
* stripped
@@ -554,6 +554,298 @@
argc, argv);
}
+/***************************************************************************
+ NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
+
+ ***************************************************************************/
+
+/**
+ * Add interdomain trust account to the RPC server.
+ * All parameters (except for argc and argv) are passed by run_rpc_command
+ * function.
+ *
+ * @param domain_sid The domain sid acquired from the server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return normal NTSTATUS return code
+ */
+
+static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv) {
+
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ fstring acct_name;
+ uint16 acb_info;
+ uint32 unknown, user_rid;
+
+ if (argc != 1) {
+ d_printf("Usage: net rpc trustdom add <domain_name>\n");
+ return NT_STATUS_OK;
+ }
+
+ /*
+ * Make valid trusting domain account (ie. uppercased and with '$' appended)
+ */
+
+ snprintf(acct_name, sizeof(acct_name) - 1, "%s$", argv[0]);
+ strupper(acct_name);
+
+ /* Get sam policy handle */
+
+ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Get domain policy handle */
+
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ domain_sid, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Create trusting domain's account */
+
+ acb_info = ACB_DOMTRUST;
+ unknown = 0xe005000b; /* No idea what this is - a permission mask?
+ Is it needed for interdomain account also ? */
+
+ result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
+ acct_name, acb_info, unknown,
+ &user_pol, &user_rid);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ done:
+ return result;
+}
+
+/**
+ * Create interdomain trust account for a remote domain.
+ *
+ * @param argc standard argc
+ * @param argv standard argv without initial components
+ *
+ * @return Integer status (0 means success)
+ */
+
+static int rpc_trustdom_add(int argc, const char **argv)
+{
+ return run_rpc_command(PIPE_SAMR, 0, rpc_trustdom_add_internals,
+ argc, argv);
+}
+
+
+/**
+ * Establish trust relationship to a trusting domain.
+ * Interdomain account must already be created on remote PDC.
+ *
+ * @param argc standard argc
+ * @param argv standard argv without initial components
+ *
+ * @return Integer status (0 means success)
+ */
+
+static int rpc_trustdom_establish(int argc, const char **argv) {
+
+ struct cli_state *cli;
+ POLICY_HND connect_hnd;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS nt_status;
+ DOM_SID domain_sid;
+ WKS_INFO_100 wks_info;
+
+ uchar ntpwd[16];
+
+ fstring domain_name;
+ fstring acct_name;
+ fstring pdc_name;
+
+ /*
+ * Connect to \\server\IPC$ as 'our domain' account with password
+ */
+
+ safe_strcpy(domain_name, argv[0], FSTRING_LEN);
+ strupper(domain_name);
+
+ snprintf(acct_name, strlen(lp_workgroup()) + 2, "%s$", lp_workgroup());
+ strupper(acct_name);
+
+ nt_status = connect_to_trusted_dc(&cli, domain_name, acct_name, ntpwd);
+ if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
+
+ /* Is it trusting domain accout for sure ? */
+ DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
+ get_nt_error_msg(nt_status)));
+ return -1;
+ }
+
+
+ /*
+ * Connect to \\server\IPC$ anonymously this time
+ */
+
+ safe_strcpy(acct_name, "", FSTRING_LEN);
+
+ nt_status = connect_to_trusted_dc(&cli, domain_name, acct_name, ntpwd);
+ if (NT_STATUS_IS_ERR(nt_status)) {
+ DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
+ domain_name, get_nt_error_msg(nt_status)));
+ }
+
+
+ /*
+ * Use NetServerEnum2 to make sure we're talking to a proper server
+ */
+
+ if (cli_get_pdc_name(cli, domain_name, pdc_name)) {
+ DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
+ for domain %s\n", domain_name));
+ }
+
+ /*
+ * Call WksQueryInfo to check remote server's capabilities
+ * FIXME:Is really necessary ? nt serv does this, but from samba's
+ * point of view it doesn't seem to make the difference
+ * IDEA: It may be used to get info about type of pdc we're talking to
+ * (e.g. WinNT or Win2k)
+ */
+
+ if (!cli_nt_session_open(cli, PIPE_WKSSVC)) {
+ DEBUG(0, ("Couldn't not initialise wkssvc pipe\n"));
+ return -1;
+ }
+
+/* TODO: convert this call from rpc_client/cli_wkssvc.c to cli_wks_query_info()
+ in libsmb/cli_wkssvc.c
+
+ if (!do_wks_query_info(cli, pdc_name, 100 /* wks info level , &wks_info)) {
+ DEBUG(0, ("WksQueryInfo call failed.\n"))
+ return -1;
+ }
+*/
+ if (cli->nt_pipe_fnum)
+ cli_nt_session_close(cli);
+
+
+ /*
+ * Call LsaOpenPolicy and LsaQueryInfo
+ */
+
+ if (!(mem_ctx = talloc_init())) {
+ DEBUG(0, ("talloc_init() failed\n"));
+ cli_shutdown(cli);
+ return -1;
+ }
+
+ if (!cli_nt_session_open(cli, PIPE_LSARPC)) {
+ DEBUG(0, ("Could not initialise lsa pipe\n"));
+ }
+
+ nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
+ &connect_hnd);
+ if (NT_STATUS_IS_ERR(nt_status)) {
+ DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
+ get_nt_error_msg(nt_status)));
+ return -1;
+ }
+
+
+ /* Querying info level 5 */
+
+ nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
+ 5 /* info level */, domain_name, &domain_sid);
+ if (NT_STATUS_IS_ERR(nt_status)) {
+ DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
+ get_nt_error_msg(nt_status)));
+ return -1;
+ }
+
+
+ /* There should be actually query info level 3 (following nt serv behaviour),
+ but I still don't know whether it is _really_ necessary */
+
+
+ /*
+ * Close the pipes and clean up
+ */
+
+ nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
+ if (NT_STATUS_IS_ERR(nt_status)) {
+ DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
+ get_nt_error_msg(nt_status)));
+ return -1;
+ }
+
+ if (cli->nt_pipe_fnum)
+ cli_nt_session_close(cli);
+
+ talloc_destroy(mem_ctx);
+
+
+ /*
+ * Store the password in secrets db
+ */
+
+ if (!secrets_store_trusted_domain_password(domain_name, ntpwd, domain_sid)) {
+ DEBUG(0, ("Storing password for trusted domain failed.\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * Usage for 'net rpc trustdom' command
+ *
+ * @param argc standard argc
+ * @param argv standard argv without inital components
+ *
+ * @return Integer status returned to shell
+ **/
+
+static int rpc_trustdom_usage(int argc, const char **argv) {
+ d_printf(" net rpc trustdom add \t\t add trusting domain's account\n");
+ d_printf(" net rpc trustdom establish \t establish relationship to trusted domain\n");
+ return -1;
+}
+
+
+/**
+ * Entrypoint for 'net rpc trustdom' code
+ *
+ * @param argc standard argc
+ * @param argv standard argv without initial components
+ *
+ * @return Integer status (0 means success)
+ */
+
+static int rpc_trustdom(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"add", rpc_trustdom_add},
+ {"establish", rpc_trustdom_establish},
+ {NULL, NULL}
+ };
+
+ if (argc == 0) {
+ rpc_trustdom_usage(argc, argv);
+ return -1;
+ }
+
+ return (net_run_function(argc, argv, func, rpc_user_usage));
+}
+
/****************************************************************************/
@@ -569,6 +861,7 @@
d_printf(" net rpc join \tto join a domain \n");
d_printf(" net rpc user \tto add, delete and list users\n");
d_printf(" net rpc changetrustpw \tto change the trust account password\n");
+ d_printf(" net rpc trustdom \tto create trusting domain's account or establish trust\n");
d_printf(" net rpc abortshutdown \tto to abort the shutdown of a remote server\n");
d_printf(" net rpc shutdown \tto to shutdown a remote server\n");
d_printf("\n");
@@ -593,6 +886,7 @@
{"join", rpc_join},
{"user", rpc_user},
{"changetrustpw", rpc_changetrustpw},
+ {"trustdom", rpc_trustdom},
{"abortshutdown", rpc_shutdown_abort},
{"shutdown", rpc_shutdown},
{NULL, NULL}
More information about the samba-technical
mailing list