diff options
| -rw-r--r-- | source3/include/includes.h | 3 | ||||
| -rw-r--r-- | source3/include/secrets.h | 16 | ||||
| -rw-r--r-- | source3/libsmb/cli_wkssvc.c | 112 | ||||
| -rw-r--r-- | source3/passdb/secrets.c | 92 | ||||
| -rw-r--r-- | source3/utils/net.c | 54 | ||||
| -rw-r--r-- | source3/utils/net_rpc.c | 372 | 
6 files changed, 629 insertions, 20 deletions
diff --git a/source3/include/includes.h b/source3/include/includes.h index 2037b5ae05..51fc0d153b 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -699,7 +699,6 @@ extern int errno;  #include "hash.h"  #include "trans2.h"  #include "nterr.h" -#include "secrets.h"  #include "messages.h"  #include "util_list.h"  #include "charset.h" @@ -718,6 +717,8 @@ extern int errno;  #include "smbw.h"  #include "nameserv.h" +#include "secrets.h" +  #include "byteorder.h"  #include "ntdomain.h" diff --git a/source3/include/secrets.h b/source3/include/secrets.h index 53d9c8ab88..2ab8d1168f 100644 --- a/source3/include/secrets.h +++ b/source3/include/secrets.h @@ -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 --git a/source3/libsmb/cli_wkssvc.c b/source3/libsmb/cli_wkssvc.c new file mode 100644 index 0000000000..391aee1782 --- /dev/null +++ b/source3/libsmb/cli_wkssvc.c @@ -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 --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 995541ab0c..5afddfec24 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -123,7 +123,7 @@ BOOL secrets_fetch_domain_sid(char *domain, DOM_SID *sid)  /************************************************************************ -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,24 @@ char *trust_keystr(char *domain)  	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 char* keystr; + +	asprintf(&keystr, "%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 +186,41 @@ BOOL secrets_fetch_trust_account_password(char *domain, uint8 ret_pwd[16],  	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 +235,32 @@ BOOL secrets_store_trust_account_password(char *domain, uint8 new_pwd[16])  	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,7 +295,7 @@ char *secrets_fetch_machine_password(void)  /************************************************************************ - 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) @@ -226,6 +303,15 @@ 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   from a fork call these calls will be re-done. This should be diff --git a/source3/utils/net.c b/source3/utils/net.c index 3577b922d3..aac5235ac8 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -104,9 +104,9 @@ int net_run_function(int argc, const char **argv, struct functable *table,  /****************************************************************************  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 @@ static struct cli_state *connect_to_ipc(struct in_addr *server_ip, const char *s  		}  	} -	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 @@ static struct cli_state *connect_to_ipc(struct in_addr *server_ip, const char *s  		    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 @@ static BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **se  	return True;  } + +BOOL net_find_dc(struct in_addr *server_ip, fstring 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 @@ struct cli_state *net_make_ipc_connection(unsigned flags)  	}  	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; diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index d46644acf5..b19a82f366 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -302,9 +302,9 @@ static int rpc_join(int argc, const char **argv)   * 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,372 @@ static int rpc_shutdown(int argc, const char **argv)  				       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; +	char *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) +	 */ +	  +	if (asprintf(&acct_name, "%s$", argv[0]) < 0) { +		return NT_STATUS_NO_MEMORY; +	} + +	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: +	SAFE_FREE(acct_name); +	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; +	 +	char* domain_name; +	char* acct_name; +	fstring pdc_name; + +	/* +	 * Connect to \\server\ipc$ as 'our domain' account with password +	 */ + +	domain_name = smb_xstrdup(argv[0]); +	strupper(domain_name); +	 +	asprintf(&acct_name, "%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, (char*)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, (char*)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; +	} +	 +	DEBUG(0, ("Success!\n")); +	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) { + +	char* domain_name; + +	if (argc < 1) return -1; +	 +	/* generate upper cased domain name */ +	domain_name = smb_xstrdup(argv[0]); +	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 +935,7 @@ int net_rpc_usage(int argc, const char **argv)  	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 +960,7 @@ int net_rpc(int argc, const char **argv)  		{"join", rpc_join},  		{"user", rpc_user},  		{"changetrustpw", rpc_changetrustpw}, +		{"trustdom", rpc_trustdom},  		{"abortshutdown", rpc_shutdown_abort},  		{"shutdown", rpc_shutdown},  		{NULL, NULL}  | 
