1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

loadparm.c: Added machine password timeout parameter - set to 7 days be default.

password.c: Added code to tell server.c when machine password needs changing.
server.c: Change machine password in idle cycles if it needs it.
smbpassfile.c: Fixed up length calculations for machine password file.
smbpasswd.c: Moved domain joining code/machine password changing code.
lib/rpc/client/cli_netlogon.c: And this is where it now lives.
Jeremy.
(This used to be commit b8fedca619)
This commit is contained in:
Jeremy Allison 1998-05-27 00:30:52 +00:00
parent 1d16f75051
commit 9bd7e1e887
8 changed files with 266 additions and 173 deletions

View File

@ -250,6 +250,7 @@ BOOL cli_net_srv_pwset(struct cli_state *cli, uint8 hashed_mach_pwd[16]);
BOOL cli_net_sam_logon(struct cli_state *cli, NET_ID_INFO_CTR *ctr,
NET_USER_INFO_3 *user_info3);
BOOL cli_net_sam_logoff(struct cli_state *cli, NET_ID_INFO_CTR *ctr);
BOOL change_trust_account_password( char *domain, char *remote_machine_list);
/*The following definitions come from lib/rpc/client/cli_pipe.c */
@ -1017,6 +1018,7 @@ int lp_client_code_page(void);
int lp_announce_as(void);
int lp_lm_announce(void);
int lp_lm_interval(void);
int lp_machine_password_timeout(void);
int lp_ldap_port(void);
char *lp_preexec(int );
char *lp_postexec(int );

View File

@ -172,6 +172,7 @@ typedef struct
int shmem_size;
int client_code_page;
int announce_as; /* This is initialised in init_globals */
int machine_password_timeout;
#ifdef USE_LDAP
int ldap_port;
#endif /* USE_LDAP */
@ -591,6 +592,7 @@ static struct parm_struct parm_table[] =
{"domain allow hosts",P_STRING, P_GLOBAL, &Globals.szDomainHostsallow, NULL, NULL, 0},
{"domain hosts deny", P_STRING, P_GLOBAL, &Globals.szDomainHostsdeny, NULL, NULL, 0},
{"domain deny hosts", P_STRING, P_GLOBAL, &Globals.szDomainHostsdeny, NULL, NULL, 0},
{"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, 0},
{"Logon Options", P_SEP, P_SEPARATOR},
{"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, 0},
@ -758,6 +760,7 @@ static void init_globals(void)
Globals.max_ttl = 60*60*24*3; /* 3 days default */
Globals.max_wins_ttl = 60*60*24*6; /* 6 days default */
Globals.min_wins_ttl = 60*60*6; /* 6 hours default */
Globals.machine_password_timeout = 60*60*24*7; /* 7 days default */
Globals.ReadSize = 16*1024;
Globals.lm_announce = 2; /* = Auto: send only if LM clients found */
Globals.lm_interval = 60;
@ -1050,6 +1053,7 @@ FN_GLOBAL_INTEGER(lp_client_code_page,&Globals.client_code_page)
FN_GLOBAL_INTEGER(lp_announce_as,&Globals.announce_as)
FN_GLOBAL_INTEGER(lp_lm_announce,&Globals.lm_announce)
FN_GLOBAL_INTEGER(lp_lm_interval,&Globals.lm_interval)
FN_GLOBAL_INTEGER(lp_machine_password_timeout,&Globals.machine_password_timeout)
#ifdef USE_LDAP
FN_GLOBAL_INTEGER(lp_ldap_port,&Globals.ldap_port)

View File

@ -1101,4 +1101,3 @@ BOOL pdb_rid_is_user(uint32 rid)
*/
return True;
}

View File

@ -27,6 +27,7 @@ int pw_file_lock_depth = 0;
/***************************************************************
Signal function to tell us we timed out.
****************************************************************/
static void gotalarm_sig(void)
{
gotalarm = 1;
@ -36,6 +37,7 @@ static void gotalarm_sig(void)
Lock or unlock a fd for a known lock type. Abandon after waitsecs
seconds.
****************************************************************/
BOOL do_file_lock(int fd, int waitsecs, int type)
{
struct flock lock;
@ -68,6 +70,7 @@ BOOL do_file_lock(int fd, int waitsecs, int type)
/***************************************************************
Lock an fd. Abandon after waitsecs seconds.
****************************************************************/
BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
{
if (fd < 0)
@ -89,6 +92,7 @@ BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
/***************************************************************
Unlock an fd. Abandon after waitsecs seconds.
****************************************************************/
BOOL pw_file_unlock(int fd, int *plock_depth)
{
BOOL ret=True;
@ -110,6 +114,7 @@ static FILE *mach_passwd_fp;
/************************************************************************
Routine to get the name for a trust account file.
************************************************************************/
static void get_trust_account_file_name( char *domain, char *name, char *mac_file)
{
unsigned int mac_file_len;
@ -138,6 +143,7 @@ static void get_trust_account_file_name( char *domain, char *name, char *mac_fil
/************************************************************************
Routine to lock the trust account password file for a domain.
************************************************************************/
BOOL trust_password_lock( char *domain, char *name, BOOL update)
{
pstring mac_file;
@ -176,6 +182,7 @@ BOOL trust_password_lock( char *domain, char *name, BOOL update)
/************************************************************************
Routine to unlock the trust account password file for a domain.
************************************************************************/
BOOL trust_password_unlock(void)
{
BOOL ret = pw_file_unlock(fileno(mach_passwd_fp), &mach_passwd_lock_depth);
@ -187,6 +194,7 @@ BOOL trust_password_unlock(void)
/************************************************************************
Routine to delete the trust account password file for a domain.
************************************************************************/
BOOL trust_password_delete( char *domain, char *name )
{
pstring mac_file;
@ -199,6 +207,7 @@ BOOL trust_password_delete( char *domain, char *name )
Routine to get the trust account password for a domain.
The user of this function must have locked the trust password file.
************************************************************************/
BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_time)
{
char linebuf[256];
@ -223,13 +232,17 @@ BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_t
return False;
}
if(linebuf[strlen(linebuf)-1] == '\n')
linebuf[strlen(linebuf)-1] = '\0';
/*
* The length of the line read
* must be 45 bytes ( <---XXXX 32 bytes-->:TLC-12345678
*/
if(strlen(linebuf) != 45) {
DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length).\n"));
DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length \
- was %d, should be 45).\n", strlen(linebuf)));
#ifdef DEBUG_PASSWORD
DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
#endif
@ -279,6 +292,7 @@ BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_t
Routine to get the trust account password for a domain.
The user of this function must have locked the trust password file.
************************************************************************/
BOOL set_trust_account_password( unsigned char *md4_new_pwd)
{
char linebuf[64];
@ -295,7 +309,7 @@ BOOL set_trust_account_password( unsigned char *md4_new_pwd)
slprintf(&linebuf[32], 32, ":TLC-%08X\n", (unsigned)time(NULL));
if(fwrite( linebuf, 1, 45, mach_passwd_fp)!= 45) {
if(fwrite( linebuf, 1, 46, mach_passwd_fp)!= 46) {
DEBUG(0,("set_trust_account_password: Failed to write file. Warning - the trust \
account is now invalid. Please recreate. Error was %s.\n", strerror(errno) ));
return False;
@ -304,4 +318,3 @@ account is now invalid. Please recreate. Error was %s.\n", strerror(errno) ));
fflush(mach_passwd_fp);
return True;
}

View File

@ -463,3 +463,168 @@ password ?).\n", cli->desthost ));
return ok;
}
/*********************************************************
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])
{
struct in_addr dest_ip;
struct cli_state cli;
memset(&cli, '\0', sizeof(struct cli_state));
if(cli_initialise(&cli) == False) {
DEBUG(0,("modify_trust_password: unable to initialize client connection.\n"));
return False;
}
if(!resolve_name( remote_machine, &dest_ip)) {
DEBUG(0,("modify_trust_password: Can't resolve address for %s\n", remote_machine));
return False;
}
if (ismyip(dest_ip)) {
DEBUG(0,("modify_trust_password: Machine %s is one of our addresses. Cannot add \
to ourselves.\n", remote_machine));
return False;
}
if (!cli_connect(&cli, remote_machine, &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) ));
return False;
}
if (!cli_session_request(&cli, remote_machine, 0x20, global_myname)) {
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;
}
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 (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) == 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;
}
if(cli_nt_setup_creds(&cli, orig_trust_passwd_hash) == False) {
DEBUG(0,("modify_trust_password: unable to setup the PDC credentials 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;
}
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;
}
/************************************************************************
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)
{
fstring remote_machine;
unsigned char old_trust_passwd_hash[16];
unsigned char new_trust_passwd_hash[16];
time_t lct;
if(!get_trust_account_password( 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;
}
/*
* 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)) {
strupper(remote_machine);
if(modify_trust_password( domain, remote_machine,
old_trust_passwd_hash, new_trust_passwd_hash)) {
DEBUG(0,("%s : change_trust_account_password: Changed password for \
domain %s.\n", timestring(), domain));
/*
* Return the result of trying to write the new password
* back into the trust account file.
*/
return set_trust_account_password(new_trust_passwd_hash);
}
}
DEBUG(0,("%s : change_trust_account_password: Failed to change password for \
domain %s.\n", timestring(), domain));
return False;
}

View File

@ -28,6 +28,8 @@
extern int DEBUGLEVEL;
extern int Protocol;
BOOL global_machine_pasword_needs_changing;
/* users from session setup */
static pstring session_users="";
@ -1972,8 +1974,6 @@ BOOL domain_client_validate( char *user, char *domain,
}
}
become_root(False);
/*
* Get the machine account password.
*/
@ -1992,13 +1992,14 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup ));
trust_password_unlock();
unbecome_root(False);
/*
* Here we should check the last change time to see if the machine
* password needs changing..... TODO... JRA.
*/
if(time(NULL) > lct + lp_machine_password_timeout())
global_machine_pasword_needs_changing = True;
/*
* At this point, smb_apasswd points to the lanman response to
* the challenge in local_challenge, and smb_ntpasswd points to

View File

@ -50,6 +50,7 @@ extern BOOL use_mangled_map;
extern BOOL short_case_preserve;
extern BOOL case_mangle;
time_t smb_last_time=(time_t)0;
extern BOOL global_machine_pasword_needs_changing;
extern int smb_read_error;
@ -4950,6 +4951,52 @@ static void process(void)
DEBUG(2,("%s Closing idle connection 2\n",timestring()));
return;
}
if(global_machine_pasword_needs_changing)
{
unsigned char trust_passwd_hash[16];
time_t lct;
pstring remote_machine_list;
/*
* We're in domain level security, and the code that
* read the machine password flagged that the machine
* password needs changing.
*/
/*
* First, open the machine password file with an exclusive lock.
*/
if(!trust_password_lock( global_myworkgroup, global_myname, True)) {
DEBUG(0,("process: unable to open the machine account password file for \
machine %s in domain %s.\n", global_myname, global_myworkgroup ));
continue;
}
if(!get_trust_account_password( trust_passwd_hash, &lct)) {
DEBUG(0,("process: unable to read the machine account password for \
machine %s in domain %s.\n", global_myname, global_myworkgroup ));
trust_password_unlock();
continue;
}
/*
* Make sure someone else hasn't already done this.
*/
if(t < lct + lp_machine_password_timeout()) {
trust_password_unlock();
global_machine_pasword_needs_changing = False;
continue;
}
pstrcpy(remote_machine_list, lp_passwordserver());
change_trust_account_password( global_myworkgroup, remote_machine_list);
trust_password_unlock();
global_machine_pasword_needs_changing = False;
}
}
if(got_smb)

View File

@ -43,157 +43,30 @@ static void usage(char *name, BOOL is_root)
Join a domain.
**********************************************************/
static int setup_account( char *domain, char *remote_machine,
unsigned char orig_trust_passwd_hash[16],
unsigned char new_trust_passwd_hash[16])
{
struct in_addr dest_ip;
struct cli_state cli;
memset(&cli, '\0', sizeof(struct cli_state));
if(cli_initialise(&cli) == False) {
fprintf(stderr, "%s: unable to initialize client connection.\n", prog_name);
return 1;
}
if(!resolve_name( remote_machine, &dest_ip)) {
fprintf(stderr, "%s: Can't resolve address for %s\n", prog_name, remote_machine);
return 1;
}
if (ismyip(dest_ip)) {
fprintf(stderr,"%s: Machine %s is one of our addresses. Cannot add to ourselves.\n", prog_name,
remote_machine);
return 1;
}
if (!cli_connect(&cli, remote_machine, &dest_ip)) {
fprintf(stderr, "%s: unable to connect to SMB server on \
machine %s. Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli) );
return 1;
}
if (!cli_session_request(&cli, remote_machine, 0x20, global_myname)) {
fprintf(stderr, "%s: machine %s rejected the session setup. \
Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli) );
cli_shutdown(&cli);
return 1;
}
cli.protocol = PROTOCOL_NT1;
if (!cli_negprot(&cli)) {
fprintf(stderr, "%s: machine %s rejected the negotiate protocol. \
Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli) );
cli_shutdown(&cli);
return 1;
}
if (cli.protocol != PROTOCOL_NT1) {
fprintf(stderr, "%s: machine %s didn't negotiate NT protocol.\n", prog_name, remote_machine);
cli_shutdown(&cli);
return 1;
}
/*
* Do an anonymous session setup.
*/
if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
fprintf(stderr, "%s: machine %s rejected the session setup. \
Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli) );
cli_shutdown(&cli);
return 1;
}
if (!(cli.sec_mode & 1)) {
fprintf(stderr, "%s: machine %s isn't in user level security mode\n", prog_name, remote_machine);
cli_shutdown(&cli);
return 1;
}
if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
fprintf(stderr, "%s: machine %s rejected the tconX on the IPC$ share. \
Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli) );
cli_shutdown(&cli);
return 1;
}
/*
* 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) == False) {
fprintf(stderr, "%s: unable to open the domain client session to \
machine %s. Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli));
cli_nt_session_close(&cli);
cli_ulogoff(&cli);
cli_shutdown(&cli);
return 1;
}
if(cli_nt_setup_creds(&cli, orig_trust_passwd_hash) == False) {
fprintf(stderr, "%s: unable to setup the PDC credentials to machine \
%s. Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli));
cli_nt_session_close(&cli);
cli_ulogoff(&cli);
cli_shutdown(&cli);
return 1;
}
if( cli_nt_srv_pwset( &cli,new_trust_passwd_hash ) == False) {
fprintf(stderr, "%s: unable to change password for machine %s in domain \
%s to Domain controller %s. Error was %s.\n", prog_name, global_myname, domain, remote_machine,
cli_errstr(&cli));
cli_close(&cli, cli.nt_pipe_fnum);
cli_ulogoff(&cli);
cli_shutdown(&cli);
return 1;
}
cli_nt_session_close(&cli);
cli_ulogoff(&cli);
cli_shutdown(&cli);
return 0;
}
/*********************************************************
Join a domain.
**********************************************************/
static int join_domain( char *domain, char *remote)
{
fstring remote_machine;
char *p;
pstring remote_machine;
fstring trust_passwd;
unsigned char trust_passwd_hash[16];
unsigned char new_trust_passwd_hash[16];
int ret = 1;
unsigned char orig_trust_passwd_hash[16];
BOOL ret;
fstrcpy(remote_machine, remote ? remote : "");
pstrcpy(remote_machine, remote ? remote : "");
fstrcpy(trust_passwd, global_myname);
strlower(trust_passwd);
E_md4hash( (uchar *)trust_passwd, trust_passwd_hash);
generate_random_buffer( new_trust_passwd_hash, 16, True);
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(lp_domain_controller() && strequal(lp_workgroup(), domain)) {
fprintf(stderr, "%s: Cannot join domain %s as we already configured as domain controller \
for that domain.\n", prog_name, domain);
fprintf(stderr, "%s: Cannot join domain %s as we already configured as \
domain controller for that domain.\n", prog_name, domain);
return 1;
}
/*
* Write the new machine password.
*/
/*
* Get the machine account password.
* Create the machine account password file.
*/
if(!trust_password_lock( domain, global_myname, True)) {
fprintf(stderr, "%s: unable to open the machine account password file for \
@ -201,53 +74,42 @@ machine %s in domain %s.\n", prog_name, global_myname, domain);
return 1;
}
if(!set_trust_account_password( new_trust_passwd_hash)) {
fprintf(stderr, "%s: unable to read the machine account password for \
/*
* Write the old machine account password.
*/
if(!set_trust_account_password( orig_trust_passwd_hash)) {
fprintf(stderr, "%s: unable to write the machine account password for \
machine %s in domain %s.\n", prog_name, global_myname, domain);
trust_password_unlock();
return 1;
}
trust_password_unlock();
/*
* If we are given a remote machine assume this is the PDC.
*/
if(remote != NULL) {
strupper(remote_machine);
ret = setup_account( domain, remote_machine, trust_passwd_hash, new_trust_passwd_hash);
if(ret == 0)
printf("%s: Joined domain %s.\n", prog_name, domain);
} else {
/*
* Treat each name in the 'password server =' line as a potential
* PDC/BDC. Contact each in turn and try and authenticate and
* change the machine account password.
*/
if(remote == NULL)
pstrcpy(remote_machine, lp_passwordserver());
p = lp_passwordserver();
if(!*p)
fprintf(stderr, "%s: No password server list given in smb.conf - \
if(!*remote_machine) {
fprintf(stderr, "%s: No password server list given in smb.conf - \
unable to join domain.\n", prog_name);
while(p && next_token( &p, remote_machine, LIST_SEP)) {
strupper(remote_machine);
if(setup_account( domain, remote_machine, trust_passwd_hash, new_trust_passwd_hash) == 0) {
printf("%s: Joined domain %s.\n", prog_name, domain);
return 0;
}
}
trust_password_unlock();
return 1;
}
if(ret) {
ret = change_trust_account_password( domain, remote_machine);
trust_password_unlock();
if(!ret) {
trust_password_delete( domain, global_myname);
fprintf(stderr,"%s: Unable to join domain %s.\n", prog_name, domain);
} else {
printf("%s: Joined domain %s.\n", prog_name, domain);
}
return ret;
return (int)ret;
}
/*********************************************************