mirror of
https://github.com/samba-team/samba.git
synced 2025-08-05 12:22:11 +03:00
The beginning of trusted and trusting domain support from
Rafal Szczesniak <mimir@diament.ists.pwr.wroc.pl>
This adds the 'net' tools to manipulate the trusted domains.
Andrew Bartlett
(This used to be commit 770c8a31d9
)
This commit is contained in:
@ -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"
|
||||
|
@ -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 */
|
||||
|
112
source3/libsmb/cli_wkssvc.c
Normal file
112
source3/libsmb/cli_wkssvc.c
Normal file
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
|
Reference in New Issue
Block a user