domain trusts patch

Rafal Szczesniak mimir at diament.ists.pwr.wroc.pl
Wed Feb 27 10:13:06 GMT 2002


This is yet another version of this patch. It stores trust password as
plain text instead of nt hash.
Any more wishes ? :)


cheers,
+------------------------------------------------------------+
|Rafal 'Mimir' Szczesniak <mimir at diament.ists.pwr.wroc.pl>   |
|*BSD, GNU/Linux and Samba                                  /
|__________________________________________________________/
-------------- next part --------------
diff -Nur samba/source/Makefile.in head/source/Makefile.in
--- samba/source/Makefile.in	Wed Feb 27 16:29:44 2002
+++ head/source/Makefile.in	Wed Feb 27 13:02:30 2002
@@ -155,8 +155,8 @@
 	     $(LIBADS_OBJ)
 
 LIBMSRPC_OBJ = libsmb/cli_lsarpc.o libsmb/cli_samr.o libsmb/cli_spoolss.o \
-	       libsmb/cli_netlogon.o libsmb/cli_srvsvc.o libsmb/cli_dfs.o \
-	       libsmb/cli_reg.o libsmb/trust_passwd.o\
+	       libsmb/cli_netlogon.o libsmb/cli_srvsvc.o libsmb/cli_wkssvc.o \
+	       libsmb/cli_dfs.o libsmb/cli_reg.o libsmb/trust_passwd.o\
 	       rpc_client/cli_pipe.o libsmb/cli_pipe_util.o
 
 LIBMSRPC_PICOBJ = $(LIBMSRPC_OBJ:.o=.po)
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) { 
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 27 13:36:40 2002
@@ -22,18 +22,32 @@
 #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 {
+	int pass_len;
+	char* pass;
+	time_t mod_time;
+	DOM_SID domain_sid; /* remote domain's sid */
+};
+
 
 #endif /* _SECRETS_H */
diff -Nur samba/source/libsmb/cli_wkssvc.c head/source/libsmb/cli_wkssvc.c
--- samba/source/libsmb/cli_wkssvc.c	Thu Jan  1 01:00:00 1970
+++ head/source/libsmb/cli_wkssvc.c	Sun Feb 24 18:11:04 2002
@@ -0,0 +1,112 @@
+/* 
+   Unix SMB/CIFS implementation.
+   NT Domain Authentication SMB / MSRPC client
+   Copyright (C) Andrew Tridgell 1994-2000
+   Copyright (C) Luke Kenneth Casson Leighton 1996-2000
+   Copyright (C) Tim Potter 2001
+   Copytight (C) Rafal Szczesniak 2002
+   
+   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"
+
+/**
+ * Opens a SMB connection to the wkssvc pipe
+ *
+ * @param cli client structure (not yet initialised)
+ * @param system_name called rpc server name
+ * @param creds user credentials
+ *
+ * @return client structure with opened pipe
+ **/
+
+struct cli_state *cli_wkssvc_initialise(struct cli_state *cli, 
+					char *system_name,
+					struct ntuser_creds *creds)
+{
+        return cli_pipe_initialise(cli, system_name, PIPE_WKSSVC, creds);
+}
+
+
+/**
+ * WksQueryInfo rpc call (like query for server's capabilities)
+ *
+ * @param initialised client structure with \PIPE\wkssvc opened
+ * @param mem_ctx memory context assigned to this rpc binding
+ * @param wks100 WksQueryInfo structure
+ *
+ * @return NTSTATUS of rpc call
+ */
+ 
+NTSTATUS cli_wks_query_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+			    WKS_INFO_100 *wks100)
+{
+	prs_struct buf;
+	prs_struct rbuf;
+	WKS_Q_QUERY_INFO q_o;
+	WKS_R_QUERY_INFO r_o;
+	NTSTATUS nt_status;
+
+	if (cli == NULL || wks100 == NULL)
+		return NT_STATUS_UNSUCCESSFUL;
+
+	/* init rpc parse structures */
+	prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+	DEBUG(4, ("WksQueryInfo\n"));
+	
+	/* init query structure with rpc call arguments */
+	init_wks_q_query_info(&q_o, cli->desthost, 100);
+	
+	/* marshall data */
+	if (!wks_io_q_query_info("", &q_o, &buf, 0)) {
+		prs_mem_free(&buf);
+		prs_mem_free(&rbuf);
+		return NT_STATUS_UNSUCCESSFUL;
+	}
+	
+	/* actual rpc call over \PIPE\wkssvc */
+	if (!rpc_api_pipe_req(cli, WKS_QUERY_INFO, &buf, &rbuf)) {
+		prs_mem_free(&buf);
+		prs_mem_free(&rbuf);
+		return NT_STATUS_UNSUCCESSFUL;
+	}
+	
+	prs_mem_free(&buf);
+
+	r_o.wks100 = wks100;
+
+	/* get call results from response buffer */
+	if (!wks_io_r_query_info("", &r_o, &rbuf, 0)) {
+		prs_mem_free(&rbuf);
+		return NT_STATUS_UNSUCCESSFUL;
+	}
+	
+	/* check returnet status code */
+	if (NT_STATUS_IS_ERR(r_o.status)) {
+		/* report the error */
+		DEBUG(0,("WKS_R_QUERY_INFO: %s\n", get_nt_error_msg(r_o.status)));
+		prs_mem_free(&rbuf);
+		return r_o.status;
+	}
+	
+	/* do clean up */
+	prs_mem_free(&rbuf);
+	
+	return nt_status;
+}
+
diff -Nur samba/source/libsmb/cliconnect.c head/source/libsmb/cliconnect.c
--- samba/source/libsmb/cliconnect.c	Wed Jan 30 07:08:18 2002
+++ head/source/libsmb/cliconnect.c	Sun Feb 24 16:47:45 2002
@@ -1270,6 +1270,15 @@
 	{
 		DEBUG(1,("failed session setup\n"));
 		nt_status = cli_nt_error(cli);
+
+		/* if it's a trusting domain's account pass the credentials anyway */
+		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
+			init_creds(&creds, user, domain, password, pass_len);
+			cli_init_creds(cli, &creds);
+			*output_cli = cli;
+			return nt_status;
+		}
+		
 		cli_shutdown(cli);
 		if (NT_STATUS_IS_OK(nt_status)) nt_status = NT_STATUS_UNSUCCESSFUL;
 		return nt_status;
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	Fri Feb 22 23:15:15 2002
+++ head/source/passdb/secrets.c	Wed Feb 27 16:17:19 2002
@@ -123,7 +123,7 @@
 
 
 /************************************************************************
-form a key for fetching a domain trust password
+form a key for fetching the machine trust account password
 ************************************************************************/
 char *trust_keystr(char *domain)
 {
@@ -135,8 +135,25 @@
 	return keystr;
 }
 
+/**
+ * Form a key for fetching a trusted domain password
+ *
+ * @param domain domain name
+ *
+ * @return stored password's key
+ **/
+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 trust account password for a domain.
+ 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 +187,41 @@
 	return True;
 }
 
+/************************************************************************
+ Routine to get account password to trusted domain
+************************************************************************/
+BOOL secrets_fetch_trusted_domain_password(char *domain, char* pwd,
+				DOM_SID sid, time_t *pass_last_set_time)
+{
+	struct trusted_dom_pass *pass;
+	int pass_len;
+	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;
+	}
+	
+	memcpy(&pass_len, &(pass->pass_len), sizeof(pass_len));
+	
+	if (pwd)
+		safe_free(pwd);
+	else
+		pwd = (char*)malloc(pass_len + 1);
+	safe_strcpy(pwd, pass->pass, pass_len);
+
+	if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
+
+	memcpy(&sid, &(pass->domain_sid), sizeof(sid));
+	SAFE_FREE(pass);
+	
+	return True;
+}
 
 /************************************************************************
  Routine to set the trust account password for a domain.
@@ -184,6 +236,32 @@
 	return secrets_store(trust_keystr(domain), (void *)&pass, sizeof(pass));
 }
 
+/**
+ * Routine to set the password for trusted domain
+ *
+ * @param domain remote domain name
+ * @param pwd plain text password of trust relationship
+ * @param sid remote domain sid
+ *
+ * @return true if succeeded
+ **/
+
+BOOL secrets_store_trusted_domain_password(char* domain, char* pwd,
+					   DOM_SID sid)
+{
+	struct trusted_dom_pass pass;
+
+	pass.mod_time = time(NULL);
+
+	pass.pass_len = strlen(pwd);
+	pass.pass = (char*)malloc(strlen(pwd) + 1);
+	safe_strcpy(pass.pass, pwd, strlen(pwd));
+
+	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
@@ -218,13 +296,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/tdb/tdb.c head/source/tdb/tdb.c
--- samba/source/tdb/tdb.c	Wed Jan 30 07:08:41 2002
+++ head/source/tdb/tdb.c	Mon Feb 25 22:14:55 2002
@@ -243,7 +243,7 @@
 	tdb->locked[list+1].count--;
 }
 
-/* This is based on the hash agorithm from gdbm */
+/* This is based on the hash algorithm from gdbm */
 static u32 tdb_hash(TDB_DATA *key)
 {
 	u32 value;	/* Used to compute the hash value.  */
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	Tue Feb 26 19:12:51 2002
@@ -104,9 +104,9 @@
 /****************************************************************************
 connect to \\server\ipc$  
 ****************************************************************************/
-static struct cli_state *connect_to_ipc(struct in_addr *server_ip, const char *server_name)
+NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
+					const char *server_name)
 {
-	struct cli_state *c;
 	NTSTATUS nt_status;
 
 	if (!got_pass) {
@@ -116,14 +116,14 @@
 		}
 	}
 	
-	nt_status = cli_full_connection(&c, opt_requester_name, server_name, 
+	nt_status = cli_full_connection(c, opt_requester_name, server_name, 
 					server_ip, opt_port,
 					"IPC$", "IPC",  
 					opt_user_name, opt_workgroup,
 					opt_password, strlen(opt_password));
 	
 	if (NT_STATUS_IS_OK(nt_status)) {
-		return c;
+		return nt_status;
 	} else {
 		DEBUG(0,("Cannot connect to server.  Error was %s\n", 
 			 get_nt_error_msg(nt_status)));
@@ -134,29 +134,29 @@
 		    NT_STATUS_V(NT_STATUS_LOGON_FAILURE))
 			d_printf("The username or password was not correct.\n");
 
-		return NULL;
+		return nt_status;
 	}
 }
 
 /****************************************************************************
 connect to \\server\ipc$ anonymously
 ****************************************************************************/
-static struct cli_state *connect_to_ipc_anonymous(struct in_addr *server_ip, const char *server_name)
+NTSTATUS connect_to_ipc_anonymous(struct cli_state **c,
+			struct in_addr *server_ip, const char *server_name)
 {
-	struct cli_state *c;
 	NTSTATUS nt_status;
 
-	nt_status = cli_full_connection(&c, opt_requester_name, server_name, 
+	nt_status = cli_full_connection(c, opt_requester_name, server_name, 
 					server_ip, opt_port,
 					"IPC$", "IPC",  
 					"", "",
 					"", 0);
 	
 	if (NT_STATUS_IS_OK(nt_status)) {
-		return c;
+		return nt_status;
 	} else {
 		DEBUG(0,("Cannot connect to server (anonymously).  Error was %s\n", get_nt_error_msg(nt_status)));
-		return NULL;
+		return nt_status;
 	}
 }
 
@@ -232,11 +232,39 @@
 	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;
+			
+		safe_strcpy(server_name, dc_name, FSTRING_LEN);
+		return True;
+	} else
+		return False;
+}
+
+
 struct cli_state *net_make_ipc_connection(unsigned flags)
 {
 	char *server_name = NULL;
 	struct in_addr server_ip;
-	struct cli_state *cli;
+	struct cli_state *cli = NULL;
+	NTSTATUS nt_status;
 
 	if (!net_find_server(flags, &server_ip, &server_name)) {
 		d_printf("\nUnable to find a suitable server\n");
@@ -244,9 +272,9 @@
 	}
 
 	if (flags & NET_FLAGS_ANONYMOUS) {
-		cli = connect_to_ipc_anonymous(&server_ip, server_name);
+		nt_status = connect_to_ipc_anonymous(cli, &server_ip, server_name);
 	} else {
-		cli = connect_to_ipc(&server_ip, server_name);
+		nt_status = connect_to_ipc(cli, &server_ip, server_name);
 	}
 	SAFE_FREE(server_name);
 	return cli;
@@ -265,13 +293,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 27 14:08:13 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,367 @@
 				       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);
+}
+
+
+/**
+ * Delete 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_del(int argc, const char **argv)
+{
+	d_printf("Sorry, not yet implemented.\n");
+	return -1;
+}
+
+ 
+/**
+ * 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)
+ **/
+
+extern char *opt_user_name;
+extern char *opt_password;
+
+static int rpc_trustdom_establish(int argc, const char **argv) {
+
+	struct cli_state *cli;
+	struct in_addr server_ip;
+	POLICY_HND connect_hnd;
+	TALLOC_CTX *mem_ctx;
+	NTSTATUS nt_status;
+	DOM_SID domain_sid;
+	WKS_INFO_100 wks_info;
+	
+	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);
+	
+	opt_user_name = (char*)malloc(strlen(acct_name) + 1);
+	safe_strcpy(opt_user_name, acct_name, strlen(acct_name) + 1);
+
+	/* find the domain controller */
+	if (!net_find_dc(&server_ip, pdc_name, domain_name)) {
+		DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name));
+		return -1;
+	}
+
+	/* connect to ipc$ as username/password */
+	nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
+	if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
+
+		/* Is it trusting domain account 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$ again (this time anonymously)
+	 */
+	
+	nt_status = connect_to_ipc_anonymous(&cli, &server_ip, pdc_name);
+	
+	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
+	   UPDATE: already done :)
+	*/
+   
+	if (!(mem_ctx = talloc_init())) {
+		DEBUG(0, ("talloc_init() failed\n"));
+		cli_shutdown(cli);
+		return -1;
+	}
+	
+   	nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info);
+	
+	if (NT_STATUS_IS_ERR(nt_status)) {
+		DEBUG(0, ("WksQueryInfo call failed.\n"));
+		return -1;
+	}
+
+	if (cli->nt_pipe_fnum) {
+		cli_nt_session_close(cli);
+		talloc_destroy(mem_ctx);
+	}
+
+
+	/*
+	 * 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 if it's _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, opt_password,
+						   domain_sid)) {
+		DEBUG(0, ("Storing password for trusted domain failed.\n"));
+		return -1;
+	}
+	
+	return 0;
+}
+
+/**
+ * Revoke trust relationship to the remote domain
+ *
+ * @param argc standard argc
+ * @param argv standard argv without initial components
+ *
+ * @return Integer status (0 means success)
+ **/
+
+static int rpc_trustdom_revoke(int argc, const char **argv) {
+
+	fstring domain_name;
+
+	if (argc < 1) return -1;
+	
+	/* generate upper cased domain name */
+	safe_strcpy(domain_name, argv[0], FSTRING_LEN);
+	strupper(domain_name);
+
+	/* delete password of the trust */
+	if (!trusted_domain_password_delete(domain_name)) {
+		DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
+			  domain_name));
+		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 del \t\t delete trusting domain's account\n");
+	d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
+	d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
+	d_printf("  net rpc trustdom list \t show current interdomain trust relationships\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},
+		{"del", rpc_trustdom_del},
+		{"establish", rpc_trustdom_establish},
+		{"revoke", rpc_trustdom_revoke},
+		{NULL, NULL}
+	};
+
+	if (argc == 0) {
+		rpc_trustdom_usage(argc, argv);
+		return -1;
+	}
+
+	return (net_run_function(argc, argv, func, rpc_user_usage));
+}
+
 /****************************************************************************/
 
 
@@ -569,6 +930,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 +955,7 @@
 		{"join", rpc_join},
 		{"user", rpc_user},
 		{"changetrustpw", rpc_changetrustpw},
+		{"trustdom", rpc_trustdom},
 		{"abortshutdown", rpc_shutdown_abort},
 		{"shutdown", rpc_shutdown},
 		{NULL, NULL}
diff -Nur samba/source/utils/smbpasswd.c head/source/utils/smbpasswd.c
--- samba/source/utils/smbpasswd.c	Wed Jan 30 07:08:45 2002
+++ head/source/utils/smbpasswd.c	Thu Jan 31 01:45:12 2002
@@ -397,7 +397,6 @@
 		fstrcpy(user_name, buf);
 
 	} else {
-		
 		if (remote_machine != NULL) {
 			old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
 		}


More information about the samba-technical mailing list