From 8ba00d147bbdb705b411e182433632c81a036188 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 5 Dec 2001 11:00:26 +0000 Subject: OK. Smbpasswd -j is DEAD. This moves the rest of the functionality into the 'net rpc join' code. Futhermore, this moves that entire area over to the libsmb codebase, rather than the crufty old rpc_client stuff. I have also fixed up the smbpasswd -a -m bug in the process. We also have a new 'net rpc changetrustpw' that can be called from a cron-job to regularly change the trust account password, for sites that run winbind but not smbd. With a little more work, we can kill rpc_client from smbd entirly! (It is mostly the domain auth stuff - which I can rework - and the spoolss stuff that sombody else will need to look over). Andrew Bartlett (This used to be commit 575897e879fc175ba702adf245384033342c903d) --- source3/Makefile.in | 29 +++--- source3/include/smb.h | 6 ++ source3/libsmb/cli_netlogon.c | 83 ++++++++++++++++- source3/libsmb/trust_passwd.c | 116 ++++++++++++++++++++++++ source3/rpc_client/cli_login.c | 21 ----- source3/rpc_client/cli_netlogon.c | 70 --------------- source3/rpc_client/cli_trust.c | 184 +++++++++----------------------------- source3/rpc_parse/parse_net.c | 9 +- source3/utils/net.c | 4 +- source3/utils/net.h | 6 +- source3/utils/net_ads.c | 2 +- source3/utils/net_rpc.c | 68 ++++++++++++-- source3/utils/net_rpc_join.c | 6 +- source3/utils/smbpasswd.c | 179 +++++++++--------------------------- 14 files changed, 383 insertions(+), 400 deletions(-) create mode 100644 source3/libsmb/trust_passwd.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index eaa225cd04..2a7294b0f5 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -148,7 +148,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ 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/cli_reg.o libsmb/trust_passwd.o\ rpc_client/cli_pipe.o libsmb/cli_pipe_util.o LIBMSRPC_PICOBJ = $(LIBMSRPC_OBJ:.o=.po) @@ -175,7 +175,7 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \ RPC_CLIENT_OBJ = rpc_client/cli_netlogon.o rpc_client/cli_pipe.o \ - rpc_client/cli_login.o rpc_client/cli_trust.o \ + rpc_client/cli_login.o \ rpc_client/cli_spoolss_notify.o LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o @@ -214,7 +214,12 @@ SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \ smbd/posix_acls.o \ smbd/process.o smbd/service.o smbd/error.o \ printing/printfsp.o lib/util_seaccess.o smbd/srvstr.o \ - smbd/build_options.o + smbd/build_options.o \ + rpc_client/cli_trust.o \ + rpc_client/cli_netlogon.o \ + rpc_client/cli_login.o \ + rpc_client/cli_spoolss_notify.o + PRINTING_OBJ = printing/pcap.o printing/print_svid.o \ printing/print_cups.o printing/print_generic.o \ @@ -225,10 +230,11 @@ PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o MSDFS_OBJ = msdfs/msdfs.o SMBD_OBJ = $(SMBD_OBJ1) $(MSDFS_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \ - $(RPC_SERVER_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \ + $(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) \ $(LOCKING_OBJ) $(PASSDB_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) \ $(LIB_OBJ) $(PRINTBACKEND_OBJ) $(QUOTAOBJS) $(OPLOCK_OBJ) \ - $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) + $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) $(LIBMSRPC_OBJ) + NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \ nmbd/nmbd_become_lmb.o nmbd/nmbd_browserdb.o \ @@ -248,9 +254,9 @@ NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \ SWAT_OBJ = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \ web/swat.o web/neg_lang.o $(PRINTING_OBJ) $(LIBSMB_OBJ) $(LOCKING_OBJ) \ - $(PARAM_OBJ) $(PASSDB_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) \ - $(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ) \ - smbwrapper/shared.o + $(PARAM_OBJ) $(PASSDB_OBJ) \ + $(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ) \ + smbwrapper/shared.o SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \ $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) @@ -275,8 +281,7 @@ TESTPRNS_OBJ = utils/testprns.o $(PARAM_OBJ) $(PRINTING_OBJ) $(UBIQX_OBJ) \ SMBPASSWD_OBJ = utils/smbpasswd.o $(PARAM_OBJ) \ $(LIBSMB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ)\ - $(UBIQX_OBJ) $(RPC_CLIENT_OBJ) $(RPC_PARSE_OBJ) $(LIB_OBJ) \ - libsmb/cli_lsarpc.o libsmb/cli_samr.o libsmb/cli_pipe_util.o + $(UBIQX_OBJ) $(LIB_OBJ) PDBEDIT_OBJ = utils/pdbedit.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(PASSDB_OBJ) \ $(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) @@ -322,8 +327,8 @@ CLIENT_OBJ = client/client.o client/clitar.o \ NET_OBJ = utils/net.o utils/net_ads.o utils/net_rap.o utils/net_rpc.o \ utils/net_rpc_join.o \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \ - $(GROUPDB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \ - $(NECESSARY_BECAUSE_SAMBA_DEPENDENCIES_ARE_SO_BROKEN_OBJ) + $(GROUPDB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) + CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) diff --git a/source3/include/smb.h b/source3/include/smb.h index 0ac2118b94..fa4cec4bdb 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1648,4 +1648,10 @@ typedef struct { void *cd_direct, *cd_pull, *cd_push; } *smb_iconv_t; +/* The maximum length of a trust account password. + Used when we randomly create it, 15 char passwords + exceed NT4's max password length */ + +#define DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH 14 + #endif /* _SMB_H */ diff --git a/source3/libsmb/cli_netlogon.c b/source3/libsmb/cli_netlogon.c index 7499d9ca7b..d20e466cc9 100644 --- a/source3/libsmb/cli_netlogon.c +++ b/source3/libsmb/cli_netlogon.c @@ -2,9 +2,12 @@ Unix SMB/Netbios implementation. Version 1.9. NT Domain Authentication SMB / MSRPC client - Copyright (C) Andrew Tridgell 1994-2000 + Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Luke Kenneth Casson Leighton 1996-2000 Copyright (C) Tim Potter 2001 + Copyright (C) Paul Ashton 1997. + Copyright (C) Jeremy Allison 1998. + Copyright (C) Andrew Bartlett 2001. 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 @@ -492,3 +495,81 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, done: return result; } + +/*************************************************************************** +LSA Server Password Set. +****************************************************************************/ + +NTSTATUS cli_net_srv_pwset(struct cli_state *cli, TALLOC_CTX *mem_ctx, + char* machine_name, uint8 hashed_mach_pwd[16]) +{ + prs_struct rbuf; + prs_struct buf; + DOM_CRED new_clnt_cred; + NET_Q_SRV_PWSET q_s; + uint16 sec_chan_type = 2; + NTSTATUS nt_status; + char *mach_acct; + + gen_next_creds( cli, &new_clnt_cred); + + prs_init(&buf , 1024, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* create and send a MSRPC command with api NET_SRV_PWSET */ + + mach_acct = talloc_asprintf(mem_ctx, "%s$", machine_name); + + if (!mach_acct) { + DEBUG(0,("talloc_asprintf failed!\n")); + return NT_STATUS_NO_MEMORY; + } + + DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s clnt %s %x\n", + cli->srv_name_slash, mach_acct, sec_chan_type, machine_name, + credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time)); + + /* store the parameters */ + init_q_srv_pwset(&q_s, cli->srv_name_slash, cli->sess_key, + mach_acct, sec_chan_type, machine_name, + &new_clnt_cred, (char *)hashed_mach_pwd); + + /* turn parameters into data stream */ + if(!net_io_q_srv_pwset("", &q_s, &buf, 0)) { + DEBUG(0,("cli_net_srv_pwset: Error : failed to marshall NET_Q_SRV_PWSET struct.\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, NET_SRVPWSET, &buf, &rbuf)) + { + NET_R_SRV_PWSET r_s; + + if (!net_io_r_srv_pwset("", &r_s, &rbuf, 0)) { + return NT_STATUS_UNSUCCESSFUL; + } + + nt_status = r_s.status; + + if (!NT_STATUS_IS_OK(r_s.status)) + { + /* report error code */ + DEBUG(0,("cli_net_srv_pwset: %s\n", get_nt_error_msg(nt_status))); + return nt_status; + } + + /* Update the credentials. */ + if (!clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_cred))) + { + /* + * Server replied with bad credential. Fail. + */ + DEBUG(0,("cli_net_srv_pwset: server %s replied with bad credential (bad machine \ +password ?).\n", cli->desthost )); + nt_status = NT_STATUS_UNSUCCESSFUL; + } + } + + return nt_status; +} + diff --git a/source3/libsmb/trust_passwd.c b/source3/libsmb/trust_passwd.c new file mode 100644 index 0000000000..7f7a5d29dc --- /dev/null +++ b/source3/libsmb/trust_passwd.c @@ -0,0 +1,116 @@ +/* + * Unix SMB/Netbios implementation. + * Version 3.0 + * Routines to change + * Copyright (C) Andrew Bartlett 2001. + * + * 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" + +extern pstring global_myname; + +/********************************************************* + Change the domain password on the PDC. + + Just changes the password betwen the two values specified. + + Caller must have the cli connected to the netlogon pipe + already. +**********************************************************/ +static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_ctx, + unsigned char orig_trust_passwd_hash[16], + unsigned char new_trust_passwd_hash[16]) +{ + NTSTATUS result; + result = new_cli_nt_setup_creds(cli, orig_trust_passwd_hash); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("just_change_the_password: unable to setup creds (%s)!\n", + get_nt_error_msg(result))); + return result; + } + + result = cli_net_srv_pwset(cli, mem_ctx, global_myname, new_trust_passwd_hash); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("just_change_the_password: unable to change password (%s)!\n", + get_nt_error_msg(result))); + } + return result; +} + +/********************************************************* + Change the domain password on the PDC. + Store the password ourselves, but use the supplied password + Caller must have already setup the connection to the NETLOGON pipe +**********************************************************/ + +NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx, + unsigned char orig_trust_passwd_hash[16]) +{ + unsigned char new_trust_passwd_hash[16]; + char *new_trust_passwd; + char *str; + NTSTATUS nt_status; + + /* Create a random machine account password */ + str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); + new_trust_passwd = talloc_strdup(mem_ctx, str); + + E_md4hash((uchar *)new_trust_passwd, new_trust_passwd_hash); + + nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash, + new_trust_passwd_hash); + + if (NT_STATUS_IS_OK(nt_status)) { + DEBUG(3,("%s : change_trust_account_password: Changed password.\n", timestring(False))); + /* + * Return the result of trying to write the new password + * back into the trust account file. + */ + if (!secrets_store_machine_password(new_trust_passwd)) { + nt_status = NT_STATUS_UNSUCCESSFUL; + } + } + + return nt_status; +} + +/********************************************************* + Change the domain password on the PDC. + Do most of the legwork ourselfs. Caller must have + already setup the connection to the NETLOGON pipe +**********************************************************/ + +NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx, char *domain) +{ + unsigned char old_trust_passwd_hash[16]; + char *up_domain; + + up_domain = talloc_strdup(mem_ctx, domain); + + if (!secrets_fetch_trust_account_password(domain, + old_trust_passwd_hash, + NULL)) { + DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain)); + return NT_STATUS_UNSUCCESSFUL; + } + + return trust_pw_change_and_store_it(cli, mem_ctx, old_trust_passwd_hash); + +} + diff --git a/source3/rpc_client/cli_login.c b/source3/rpc_client/cli_login.c index e5c221690d..be32533541 100644 --- a/source3/rpc_client/cli_login.c +++ b/source3/rpc_client/cli_login.c @@ -78,27 +78,6 @@ NTSTATUS cli_nt_setup_creds(struct cli_state *cli, unsigned char mach_pwd[16]) return NT_STATUS_OK; } -/**************************************************************************** - Set machine password. - ****************************************************************************/ - -BOOL cli_nt_srv_pwset(struct cli_state *cli, unsigned char *new_hashof_mach_pwd) -{ - unsigned char processed_new_pwd[16]; - - DEBUG(5,("cli_nt_srv_pwset: %d\n", __LINE__)); - -#ifdef DEBUG_PASSWORD - dump_data(6, (char *)new_hashof_mach_pwd, 16); -#endif - - /* Process the new password. */ - cred_hash3( processed_new_pwd, new_hashof_mach_pwd, cli->sess_key, 1); - - /* send client srv_pwset challenge */ - return cli_net_srv_pwset(cli, processed_new_pwd); -} - /**************************************************************************** NT login - interactive. *NEVER* use this code. This method of doing a logon (sending the cleartext diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 869de91c80..8a2d8e28cc 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -260,76 +260,6 @@ BOOL cli_net_req_chal(struct cli_state *cli, DOM_CHAL *clnt_chal, DOM_CHAL *srv_ return valid_chal; } - -/*************************************************************************** -LSA Server Password Set. -****************************************************************************/ - -BOOL cli_net_srv_pwset(struct cli_state *cli, uint8 hashed_mach_pwd[16]) -{ - prs_struct rbuf; - prs_struct buf; - DOM_CRED new_clnt_cred; - NET_Q_SRV_PWSET q_s; - BOOL ok = False; - uint16 sec_chan_type = 2; - - gen_next_creds( cli, &new_clnt_cred); - - prs_init(&buf , 1024, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api NET_SRV_PWSET */ - - DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s clnt %s %x\n", - cli->srv_name_slash, cli->mach_acct, sec_chan_type, global_myname, - credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time)); - - /* store the parameters */ - init_q_srv_pwset(&q_s, cli->srv_name_slash, - cli->mach_acct, sec_chan_type, global_myname, - &new_clnt_cred, (char *)hashed_mach_pwd); - - /* turn parameters into data stream */ - if(!net_io_q_srv_pwset("", &q_s, &buf, 0)) { - DEBUG(0,("cli_net_srv_pwset: Error : failed to marshall NET_Q_SRV_PWSET struct.\n")); - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (rpc_api_pipe_req(cli, NET_SRVPWSET, &buf, &rbuf)) - { - NET_R_SRV_PWSET r_s; - - ok = net_io_r_srv_pwset("", &r_s, &rbuf, 0); - - if (ok && !NT_STATUS_IS_OK(r_s.status)) - { - /* report error code */ - DEBUG(0,("cli_net_srv_pwset: %s\n", get_nt_error_msg(r_s.status))); - ok = False; - } - - /* Update the credentials. */ - if (ok && !clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_cred))) - { - /* - * Server replied with bad credential. Fail. - */ - DEBUG(0,("cli_net_srv_pwset: server %s replied with bad credential (bad machine \ -password ?).\n", cli->desthost )); - ok = False; - } - } - - prs_mem_free(&buf); - prs_mem_free(&rbuf); - - return ok; -} - /*************************************************************************** LSA SAM Logon internal - interactive or network. Does level 2 or 3 but always returns level 3. diff --git a/source3/rpc_client/cli_trust.c b/source3/rpc_client/cli_trust.c index c910e2f334..fbb75573cb 100644 --- a/source3/rpc_client/cli_trust.c +++ b/source3/rpc_client/cli_trust.c @@ -6,6 +6,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997. * Copyright (C) Jeremy Allison 1998. + * Copyright (C) Andrew Bartlett 2001. * * 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 @@ -30,13 +31,13 @@ extern pstring global_myname; Change the domain password on the PDC. **********************************************************/ -static BOOL modify_trust_password( char *domain, char *remote_machine, - unsigned char orig_trust_passwd_hash[16], - unsigned char new_trust_passwd_hash[16]) +static NTSTATUS modify_trust_password( char *domain, char *remote_machine, + unsigned char orig_trust_passwd_hash[16]) { - struct cli_state cli; - NTSTATUS result; + struct cli_state *cli; DOM_SID domain_sid; + struct in_addr dest_ip; + NTSTATUS nt_status; /* * Ensure we have the domain SID for this domain. @@ -44,150 +45,63 @@ static BOOL modify_trust_password( char *domain, char *remote_machine, if (!secrets_fetch_domain_sid(domain, &domain_sid)) { DEBUG(0, ("domain_client_validate: unable to fetch domain sid.\n")); - return False; + return NT_STATUS_UNSUCCESSFUL; } - ZERO_STRUCT(cli); - if(cli_initialise(&cli) == NULL) { - DEBUG(0,("modify_trust_password: unable to initialize client connection.\n")); - return False; - } - - if(!resolve_name( remote_machine, &cli.dest_ip, 0x20)) { - DEBUG(0,("modify_trust_password: Can't resolve address for %s\n", remote_machine)); - cli_shutdown(&cli); - return False; - } - - if (ismyip(cli.dest_ip)) { - DEBUG(0,("modify_trust_password: Machine %s is one of our addresses. Cannot add \ -to ourselves.\n", remote_machine)); - cli_shutdown(&cli); - return False; - } - - if (!cli_connect(&cli, remote_machine, &cli.dest_ip)) { - DEBUG(0,("modify_trust_password: unable to connect to SMB server on \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) )); - cli_shutdown(&cli); - return False; + if(!resolve_name( remote_machine, &dest_ip, 0x20)) { + DEBUG(0,("modify_trust_password: Can't resolve address for %s\n", remote_machine)); + return NT_STATUS_UNSUCCESSFUL; } - if (!attempt_netbios_session_request(&cli, global_myname, remote_machine, &cli.dest_ip)) { - DEBUG(0,("modify_trust_password: machine %s rejected the NetBIOS \ -session request. Error was %s\n", remote_machine, cli_errstr(&cli) )); - cli_shutdown(&cli); - return False; - } - - cli.protocol = PROTOCOL_NT1; - - if (!cli_negprot(&cli)) { - DEBUG(0,("modify_trust_password: machine %s rejected the negotiate protocol. \ -Error was : %s.\n", remote_machine, cli_errstr(&cli) )); - cli_shutdown(&cli); - return False; + if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname, remote_machine, + &dest_ip, 0, + "IPC$", "IPC", + "", "", + "", 0))) { + DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); + return NT_STATUS_UNSUCCESSFUL; } - - if (cli.protocol != PROTOCOL_NT1) { - DEBUG(0,("modify_trust_password: machine %s didn't negotiate NT protocol.\n", - remote_machine)); - cli_shutdown(&cli); - return False; - } - - /* - * Do an anonymous session setup. - */ - - if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) { - DEBUG(0,("modify_trust_password: machine %s rejected the session setup. \ -Error was : %s.\n", remote_machine, cli_errstr(&cli) )); - cli_shutdown(&cli); - return False; - } - - if (!(cli.sec_mode & 1)) { - DEBUG(0,("modify_trust_password: machine %s isn't in user level security mode\n", - remote_machine)); - cli_shutdown(&cli); - return False; - } - - if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { - DEBUG(0,("modify_trust_password: machine %s rejected the tconX on the IPC$ share. \ -Error was : %s.\n", remote_machine, cli_errstr(&cli) )); - cli_shutdown(&cli); - return False; - } - + /* * Ok - we have an anonymous connection to the IPC$ share. * Now start the NT Domain stuff :-). */ - if(cli_nt_session_open(&cli, PIPE_NETLOGON) == False) { + if(cli_nt_session_open(cli, PIPE_NETLOGON) == False) { DEBUG(0,("modify_trust_password: unable to open the domain client session to \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli))); - cli_nt_session_close(&cli); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return False; +machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli))); + cli_nt_session_close(cli); + cli_ulogoff(cli); + cli_shutdown(cli); + return NT_STATUS_UNSUCCESSFUL; } - - result = cli_nt_setup_creds(&cli, orig_trust_passwd_hash); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("modify_trust_password: unable to setup the PDC credentials to machine \ -%s. Error was : %s.\n", remote_machine, get_nt_error_msg(result))); - cli_nt_session_close(&cli); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return False; - } - - if( cli_nt_srv_pwset( &cli,new_trust_passwd_hash ) == False) { - DEBUG(0,("modify_trust_password: unable to change password for machine %s in domain \ -%s to Domain controller %s. Error was %s.\n", global_myname, domain, remote_machine, - cli_errstr(&cli))); - cli_close(&cli, cli.nt_pipe_fnum); - cli_ulogoff(&cli); - cli_shutdown(&cli); - return False; - } - cli_nt_session_close(&cli); - cli_ulogoff(&cli); - cli_shutdown(&cli); - - return True; + nt_status = trust_pw_change_and_store_it(cli, cli->mem_ctx, + orig_trust_passwd_hash); + + cli_nt_session_close(cli); + cli_ulogoff(cli); + cli_shutdown(cli); + return nt_status; } /************************************************************************ Change the trust account password for a domain. - The user of this function must have locked the trust password file for - update. ************************************************************************/ -BOOL change_trust_account_password( char *domain, char *remote_machine_list) +NTSTATUS change_trust_account_password( char *domain, char *remote_machine_list) { fstring remote_machine; unsigned char old_trust_passwd_hash[16]; - unsigned char new_trust_passwd_hash[16]; time_t lct; - BOOL res = False; + NTSTATUS res = NT_STATUS_UNSUCCESSFUL; if(!secrets_fetch_trust_account_password(domain, old_trust_passwd_hash, &lct)) { DEBUG(0,("change_trust_account_password: unable to read the machine \ account password for domain %s.\n", domain)); - return False; + return NT_STATUS_UNSUCCESSFUL; } - /* - * Create the new (random) password. - */ - generate_random_buffer( new_trust_passwd_hash, 16, True); - while(remote_machine_list && next_token(&remote_machine_list, remote_machine, LIST_SEP, sizeof(remote_machine))) { @@ -215,36 +129,24 @@ account password for domain %s.\n", domain)); fstring dc_name; if(!lookup_dc_name(global_myname, domain, &ip_list[i], dc_name)) continue; - if((res = modify_trust_password( domain, dc_name, - old_trust_passwd_hash, new_trust_passwd_hash))) + if(NT_STATUS_IS_OK(res = modify_trust_password( domain, dc_name, + old_trust_passwd_hash))) break; } SAFE_FREE(ip_list); } else { - res = modify_trust_password( domain, remote_machine, - old_trust_passwd_hash, new_trust_passwd_hash); + res = modify_trust_password( domain, remote_machine, + old_trust_passwd_hash); } - if(res) { - DEBUG(0,("%s : change_trust_account_password: Changed password for \ -domain %s.\n", timestring(False), domain)); - /* - * Return the result of trying to write the new password - * back into the trust account file. - */ - res = secrets_store_trust_account_password(domain, new_trust_passwd_hash); - memset(new_trust_passwd_hash, 0, 16); - memset(old_trust_passwd_hash, 0, 16); - return res; - } } - memset(new_trust_passwd_hash, 0, 16); - memset(old_trust_passwd_hash, 0, 16); - - DEBUG(0,("%s : change_trust_account_password: Failed to change password for \ + if (!NT_STATUS_IS_OK(res)) { + DEBUG(0,("%s : change_trust_account_password: Failed to change password for \ domain %s.\n", timestring(False), domain)); - return False; + } + + return res; } diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c index e3f7ea5d9a..5c8da80c01 100644 --- a/source3/rpc_parse/parse_net.c +++ b/source3/rpc_parse/parse_net.c @@ -743,10 +743,15 @@ BOOL net_io_r_auth_2(char *desc, NET_R_AUTH_2 *r_a, prs_struct *ps, int depth) Inits a NET_Q_SRV_PWSET. ********************************************************************/ -void init_q_srv_pwset(NET_Q_SRV_PWSET *q_s, char *logon_srv, char *acct_name, - uint16 sec_chan, char *comp_name, DOM_CRED *cred, char nt_cypher[16]) +void init_q_srv_pwset(NET_Q_SRV_PWSET *q_s, char *logon_srv, char *sess_key, char *acct_name, + uint16 sec_chan, char *comp_name, DOM_CRED *cred, char hashed_mach_pwd[16]) { + unsigned char nt_cypher[16]; + DEBUG(5,("init_q_srv_pwset\n")); + + /* Process the new password. */ + cred_hash3( nt_cypher, hashed_mach_pwd, sess_key, 1); init_clnt_info(&q_s->clnt_id, logon_srv, acct_name, sec_chan, comp_name, cred); diff --git a/source3/utils/net.c b/source3/utils/net.c index e20833bc0b..5efd79fa5b 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -163,7 +163,7 @@ static BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **se if (!*server_name) { *server_name = strdup(inet_ntoa(dest_ip)); } - } else if (server_name) { + } else if (*server_name) { /* resolve the IP address */ if (!resolve_name(*server_name, server_ip, 0x20)) { DEBUG(1,("Unable to resolve server name\n")); @@ -404,6 +404,8 @@ static struct functable net_func[] = { *p2 = 0; } + strupper(global_myname); + load_interfaces(); rc = net_run_function(argc_new-1, argv_new+1, net_func, net_usage); diff --git a/source3/utils/net.h b/source3/utils/net.h index bdc4a08868..e912efe09e 100644 --- a/source3/utils/net.h +++ b/source3/utils/net.h @@ -26,13 +26,13 @@ For example, localhost is insane for a 'join' operation. */ -#define NET_FLAGS_LOCALHOST_DEFAULT_INSANE 3 +#define NET_FLAGS_LOCALHOST_DEFAULT_INSANE 4 /* We want to find the PDC only */ -#define NET_FLAGS_PDC 4 +#define NET_FLAGS_PDC 8 /* We want an anonymous connection */ -#define NET_FLAGS_ANONYMOUS 5 +#define NET_FLAGS_ANONYMOUS 16 extern int opt_maxusers; diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index c956d9bb65..cecfb6a4d0 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -166,7 +166,7 @@ static int net_ads_join(int argc, const char **argv) } - tmp_password = generate_random_str(15); + tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); password = strdup(tmp_password); if (!(ads = ads_startup())) return -1; diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index b1a9ad4aa9..97a1a1d342 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -81,11 +81,11 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli) } -static int run_rpc_command(const char *pipe_name, +static int run_rpc_command(const char *pipe_name, int conn_flags, rpc_command_fn fn, int argc, const char **argv) { - struct cli_state *cli = net_make_ipc_connection(0); + struct cli_state *cli = net_make_ipc_connection(conn_flags); TALLOC_CTX *mem_ctx; NTSTATUS nt_status; DOM_SID *domain_sid = net_get_remote_domain_sid(cli); @@ -103,6 +103,8 @@ static int run_rpc_command(const char *pipe_name, nt_status = fn(domain_sid, cli, mem_ctx, argc, argv); + DEBUG(5, ("rpc command function returned %s\n", get_nt_error_msg(nt_status))); + if (cli->nt_pipe_fnum) cli_nt_session_close(cli); @@ -160,9 +162,62 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, struct cli_sta return result; } +static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) { + + return trust_pw_find_change_and_store_it(cli, mem_ctx, opt_target_workgroup); +} + +static int rpc_changetrustpw(int argc, const char **argv) +{ + return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_changetrustpw_internals, + argc, argv); +} + +static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) { + + extern pstring global_myname; + fstring trust_passwd; + unsigned char orig_trust_passwd_hash[16]; + + fstrcpy(trust_passwd, global_myname); + strlower(trust_passwd); + E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash); + + return trust_pw_change_and_store_it(cli, mem_ctx, orig_trust_passwd_hash); +} + +static int rpc_join_oldstyle(int argc, const char **argv) +{ + return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_join_oldstyle_internals, + argc, argv); +} + +static int rpc_join_usage(int argc, const char **argv) +{ + d_printf(" net rpc join \t to join a domain with admin username & password\n"); + d_printf(" net rpc join oldstyle \t to join a domain created in server manager\n"); + return -1; +} + +static int rpc_join(int argc, const char **argv) +{ + struct functable func[] = { + {"oldstyle", rpc_join_oldstyle}, + {NULL, NULL} + }; + + if (argc == 0) { + return net_rpc_join(argc, argv); + } + + return net_run_function(argc, argv, func, rpc_join_usage); +} + static int rpc_user_add(int argc, const char **argv) { - return run_rpc_command(PIPE_SAMR, rpc_user_add_internals, + return run_rpc_command(PIPE_SAMR, 0, rpc_user_add_internals, argc, argv); } @@ -188,15 +243,18 @@ static int rpc_user(int argc, const char **argv) int net_rpc_usage(int argc, const char **argv) { - d_printf(" net rpc join \tto join a domin \n"); + 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"); return -1; } int net_rpc(int argc, const char **argv) { struct functable func[] = { - {"join", net_rpc_join}, + {"join", rpc_join}, {"user", rpc_user}, + {"changetrustpw", rpc_changetrustpw}, {NULL, NULL} }; return net_run_function(argc, argv, func, net_rpc_usage); diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index 463de61b05..2b73117c38 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -191,7 +191,7 @@ int net_rpc_join(int argc, const char **argv) { char *str; - str = generate_random_str(15); + str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); clear_trust_password = strdup(str); } @@ -256,8 +256,6 @@ int net_rpc_join(int argc, const char **argv) strupper(domain); - secrets_init(); - if (!secrets_store_domain_sid(domain, &domain_sid)) { DEBUG(0, ("error storing domain sid for %s\n", domain)); goto done; @@ -284,7 +282,7 @@ int net_rpc_join(int argc, const char **argv) goto done; } - CHECK_RPC_ERR(cli_nt_setup_creds(cli, stored_md4_trust_password), + CHECK_RPC_ERR(new_cli_nt_setup_creds(cli, stored_md4_trust_password), "error in domain join verification"); retval = 0; /* Success! */ diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c index 92136bea7a..e076687c4f 100644 --- a/source3/utils/smbpasswd.c +++ b/source3/utils/smbpasswd.c @@ -50,7 +50,6 @@ static void usage(void) printf("extra options when run by root or in local mode:\n"); printf(" -L local mode (must be first option)\n"); printf(" -R ORDER name resolve order\n"); - printf(" -j DOMAIN join domain name\n"); printf(" -a add user\n"); printf(" -x delete user\n"); printf(" -d disable user\n"); @@ -61,67 +60,6 @@ static void usage(void) exit(1); } -/********************************************************* -Join a domain. -**********************************************************/ -static int join_domain(char *domain, char *remote) -{ - pstring remote_machine; - fstring trust_passwd; - unsigned char orig_trust_passwd_hash[16]; - BOOL ret; - - pstrcpy(remote_machine, remote ? remote : ""); - fstrcpy(trust_passwd, global_myname); - strlower(trust_passwd); - E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash); - - /* Ensure that we are not trying to join a - domain if we are locally set up as a domain - controller. */ - - if(strequal(remote, global_myname)) { - fprintf(stderr, "Cannot join domain %s as the domain controller name is our own. We cannot be a domain controller for a domain and also be a domain member.\n", domain); - return 1; - } - - /* - * Write the old machine account password. - */ - - if(!secrets_store_trust_account_password(domain, orig_trust_passwd_hash)) { - fprintf(stderr, "Unable to write the machine account password for \ -machine %s in domain %s.\n", global_myname, domain); - return 1; - } - - /* - * If we are given a remote machine assume this is the PDC. - */ - - if(remote == NULL) { - pstrcpy(remote_machine, lp_passwordserver()); - } - - if(!*remote_machine) { - fprintf(stderr, "No password server list given in smb.conf - \ -unable to join domain.\n"); - return 1; - } - - ret = change_trust_account_password( domain, remote_machine); - - if(!ret) { - trust_password_delete(domain); - fprintf(stderr,"Unable to join domain %s.\n",domain); - } else { - printf("Joined domain %s.\n",domain); - } - - return (int)ret; -} - - static void set_line_buffering(FILE *f) { setvbuf(f, NULL, _IOLBF, 0); @@ -241,11 +179,10 @@ static int process_root(int argc, char *argv[]) { struct passwd *pwd; int result = 0, ch; - BOOL joining_domain = False, got_pass = False, got_username = False; + BOOL got_pass = False, got_username = False; int local_flags = LOCAL_SET_PASSWORD; BOOL stdin_passwd_get = False; fstring user_name, user_password; - char *new_domain = NULL; char *new_passwd = NULL; char *old_passwd = NULL; char *remote_machine = NULL; @@ -255,7 +192,7 @@ static int process_root(int argc, char *argv[]) user_name[0] = '\0'; - while ((ch = getopt(argc, argv, "axdehmnj:r:sR:D:U:L")) != EOF) { + while ((ch = getopt(argc, argv, "axdehmnjr:sR:D:U:L")) != EOF) { switch(ch) { case 'L': local_mode = True; @@ -278,14 +215,9 @@ static int process_root(int argc, char *argv[]) case 'm': local_flags |= LOCAL_TRUST_ACCOUNT; break; - case 'n': - local_flags |= LOCAL_SET_NO_PASSWORD; - local_flags &= ~LOCAL_SET_PASSWORD; - break; case 'j': - new_domain = optarg; - strupper(new_domain); - joining_domain = True; + d_printf("See 'net rpc join' for this functionality\n"); + exit(1); break; case 'r': remote_machine = optarg; @@ -334,48 +266,16 @@ static int process_root(int argc, char *argv[]) */ if(((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) == (LOCAL_ADD_USER|LOCAL_DELETE_USER)) || ((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) && - ((remote_machine != NULL) || joining_domain))) { + (remote_machine != NULL))) { usage(); } /* Only load interfaces if we are doing network operations. */ - if (joining_domain || remote_machine) { + if (remote_machine) { load_interfaces(); } - /* Join a domain */ - - if (joining_domain) { - - if (argc != 0) - usage(); - - /* Are we joining by specifing an admin username and - password? */ - - if (user_name[0]) { - - /* Get administrator password if not specified */ - - if (!got_pass) { - char *pass = getpass("Password: "); - - if (pass) - pstrcpy(user_password, pass); - } - - d_printf("use net rpc join to do this now.\n"); - return 1; - - } else { - - /* Or just with the server manager? */ - - return join_domain(new_domain, remote_machine); - } - } - /* * Deal with root - can add a user, but only locally. */ @@ -435,45 +335,46 @@ static int process_root(int argc, char *argv[]) slprintf(buf, sizeof(buf)-1, "%s$", user_name); fstrcpy(user_name, buf); - } - - if (remote_machine != NULL) { - old_passwd = get_pass("Old SMB password:",stdin_passwd_get); - } - - if (!(local_flags & LOCAL_SET_PASSWORD)) { - - /* - * If we are trying to enable a user, first we need to find out - * if they are using a modern version of the smbpasswd file that - * disables a user by just writing a flag into the file. If so - * then we can re-enable a user without prompting for a new - * password. If not (ie. they have a no stored password in the - * smbpasswd file) then we need to prompt for a new password. - */ - - if(local_flags & LOCAL_ENABLE_USER) { - SAM_ACCOUNT *sampass = NULL; - BOOL ret; + } else { + + if (remote_machine != NULL) { + old_passwd = get_pass("Old SMB password:",stdin_passwd_get); + } + + if (!(local_flags & LOCAL_SET_PASSWORD)) { + + /* + * If we are trying to enable a user, first we need to find out + * if they are using a modern version of the smbpasswd file that + * disables a user by just writing a flag into the file. If so + * then we can re-enable a user without prompting for a new + * password. If not (ie. they have a no stored password in the + * smbpasswd file) then we need to prompt for a new password. + */ - pdb_init_sam(&sampass); - ret = pdb_getsampwnam(sampass, user_name); - if((sampass != False) && (pdb_get_lanman_passwd(sampass) == NULL)) { - local_flags |= LOCAL_SET_PASSWORD; + if(local_flags & LOCAL_ENABLE_USER) { + SAM_ACCOUNT *sampass = NULL; + BOOL ret; + + pdb_init_sam(&sampass); + ret = pdb_getsampwnam(sampass, user_name); + if((sampass != False) && (pdb_get_lanman_passwd(sampass) == NULL)) { + local_flags |= LOCAL_SET_PASSWORD; + } + pdb_free_sam(&sampass); } - pdb_free_sam(&sampass); } - } - - if(local_flags & LOCAL_SET_PASSWORD) { - new_passwd = prompt_for_new_password(stdin_passwd_get); - if(!new_passwd) { - fprintf(stderr, "Unable to get new password.\n"); - exit(1); + if(local_flags & LOCAL_SET_PASSWORD) { + new_passwd = prompt_for_new_password(stdin_passwd_get); + + if(!new_passwd) { + fprintf(stderr, "Unable to get new password.\n"); + exit(1); + } } } - + if (!password_change(remote_machine, user_name, old_passwd, new_passwd, local_flags)) { fprintf(stderr,"Failed to modify password entry for user %s\n", user_name); result = 1; -- cgit