domain trusts patch -- correction
Rafal Szczesniak
mimir at diament.ists.pwr.wroc.pl
Wed Feb 13 13:53:03 GMT 2002
This is corrected patch that replaces the previous one. I didn't clean up
the code enough, so one sleep(20) call appeared in certainly wrong place
(thanks abartlet!).
Of course further comments are appreciated :-)
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/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