summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/param/loadparm.c6
-rw-r--r--source3/passdb/smbpass.c81
-rw-r--r--source3/rpc_client/cli_login.c2
-rw-r--r--source3/rpc_server/srv_netlog.c2
-rw-r--r--source3/smbd/server.c16
-rw-r--r--source3/utils/smbpasswd.c282
7 files changed, 343 insertions, 47 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 15c25b01e7..76fb11c12e 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1773,6 +1773,7 @@ BOOL add_smbpwd_entry(struct smb_passwd *newpwd);
BOOL mod_smbpwd_entry(struct smb_passwd* pwd);
void *machine_password_lock( char *domain, char *name, BOOL update);
BOOL machine_password_unlock( void *token );
+BOOL machine_password_delete( char *domain, char *name );
BOOL get_machine_account_password( void *mach_tok, unsigned char *ret_pwd,
time_t *last_change_time);
BOOL set_machine_account_password( void *mach_tok, unsigned char *md4_new_pwd);
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index 2249c8b473..dda31f3efe 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -2144,8 +2144,7 @@ static void lp_add_auto_services(char *str)
{
char *s;
char *p;
- int homes = lp_servicenumber(HOMES_NAME);
- int printers = lp_servicenumber(PRINTERS_NAME);
+ int homes, printers;
if (!str)
return;
@@ -2153,6 +2152,9 @@ static void lp_add_auto_services(char *str)
s = strdup(str);
if (!s) return;
+ homes = lp_servicenumber(HOMES_NAME);
+ printers = lp_servicenumber(PRINTERS_NAME);
+
for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP))
{
char *home = get_home_dir(p);
diff --git a/source3/passdb/smbpass.c b/source3/passdb/smbpass.c
index aa3a694567..2ab21f78ef 100644
--- a/source3/passdb/smbpass.c
+++ b/source3/passdb/smbpass.c
@@ -80,7 +80,7 @@ static BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
(*plock_depth)++;
if(pw_file_lock_depth == 0) {
- if (do_pw_lock(fd, secs, type)) {
+ if (!do_pw_lock(fd, secs, type)) {
DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
strerror(errno)));
return False;
@@ -135,7 +135,7 @@ void *startsmbpwent(BOOL update)
/* Set a 16k buffer to do more efficient reads */
setvbuf(fp, s_readbuf, _IOFBF, sizeof(s_readbuf));
- if (!pw_file_lock(fileno(fp), F_RDLCK | (update ? F_WRLCK : 0), 5, &pw_file_lock_depth))
+ if (!pw_file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, &pw_file_lock_depth))
{
DEBUG(0, ("startsmbpwent: unable to lock file %s\n", pfile));
fclose(fp);
@@ -774,7 +774,7 @@ BOOL mod_smbpwd_entry(struct smb_passwd* pwd)
lockfd = fileno(fp);
- if (!pw_file_lock(lockfd, F_RDLCK | F_WRLCK, 5, &pw_file_lock_depth)) {
+ if (!pw_file_lock(lockfd, F_WRLCK, 5, &pw_file_lock_depth)) {
DEBUG(0, ("mod_smbpwd_entry: unable to lock file %s\n", pfile));
fclose(fp);
return False;
@@ -1076,48 +1076,63 @@ BOOL mod_smbpwd_entry(struct smb_passwd* pwd)
static int mach_passwd_lock_depth;
/************************************************************************
- Routine to lock the machine account password file for a domain.
+ Routine to get the name for a machine account file.
************************************************************************/
-void *machine_password_lock( char *domain, char *name, BOOL update)
+static void get_machine_account_file_name( char *domain, char *name, char *mac_file)
{
- FILE *fp;
- pstring mac_file;
unsigned int mac_file_len;
char *p;
- if(mach_passwd_lock_depth == 0) {
+ pstrcpy(mac_file, lp_smb_passwd_file());
+ p = strrchr(mac_file, '/');
+ if(p != NULL)
+ *++p = '\0';
- pstrcpy(mac_file, lp_smb_passwd_file());
- p = strrchr(mac_file, '/');
+ mac_file_len = strlen(mac_file);
- if(p != NULL)
- *++p = '\0';
+ if (sizeof(pstring) - mac_file_len - strlen(domain) - strlen(name) - 6 < 0)
+ {
+ DEBUG(0,("machine_password_lock: path %s too long to add machine details.\n",
+ mac_file));
+ return;
+ }
- mac_file_len = strlen(mac_file);
+ strcat(mac_file, domain);
+ strcat(mac_file, ".");
+ strcat(mac_file, name);
+ strcat(mac_file, ".mac");
+}
+
+/************************************************************************
+ Routine to lock the machine account password file for a domain.
+************************************************************************/
- if (sizeof(pstring) - mac_file_len - strlen(domain) - strlen(name) - 6 < 0)
- {
- DEBUG(0,("machine_password_lock: path %s too long to add machine details.\n",
- mac_file));
- return NULL;
- }
+void *machine_password_lock( char *domain, char *name, BOOL update)
+{
+ FILE *fp;
+ pstring mac_file;
+
+ if(mach_passwd_lock_depth == 0) {
- strcat(mac_file, domain);
- strcat(mac_file, ".");
- strcat(mac_file, name);
- strcat(mac_file, ".mac");
+ get_machine_account_file_name( domain, name, mac_file);
if((fp = fopen(mac_file, "r+b")) == NULL) {
- DEBUG(0,("machine_password_lock: cannot open file %s - Error was %s.\n",
- mac_file, strerror(errno) ));
- return NULL;
+ if(errno == ENOENT && update) {
+ fp = fopen(mac_file, "w+b");
+ }
+
+ if(fp == NULL) {
+ DEBUG(0,("machine_password_lock: cannot open file %s - Error was %s.\n",
+ mac_file, strerror(errno) ));
+ return NULL;
+ }
}
chmod(mac_file, 0600);
}
- if(!pw_file_lock(fileno(fp), F_RDLCK | (update ? F_WRLCK : 0),
+ if(!pw_file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK),
60, &mach_passwd_lock_depth))
{
DEBUG(0,("machine_password_lock: cannot lock file %s\n", mac_file));
@@ -1142,6 +1157,18 @@ BOOL machine_password_unlock( void *token )
}
/************************************************************************
+ Routine to delete the machine account password file for a domain.
+************************************************************************/
+
+BOOL machine_password_delete( char *domain, char *name )
+{
+ pstring mac_file;
+
+ get_machine_account_file_name( domain, name, mac_file);
+ return (unlink( mac_file ) == 0);
+}
+
+/************************************************************************
Routine to get the machine account password for a domain.
The user of this function must have locked the machine password file.
************************************************************************/
diff --git a/source3/rpc_client/cli_login.c b/source3/rpc_client/cli_login.c
index 80dca21149..b4cdf3ae50 100644
--- a/source3/rpc_client/cli_login.c
+++ b/source3/rpc_client/cli_login.c
@@ -90,7 +90,7 @@ BOOL cli_nt_srv_pwset(struct cli_state *cli, unsigned char *new_hashof_mach_pwd)
#endif
/* Process the new password. */
- cred_hash3( processed_new_pwd, new_hashof_mach_pwd, cli->sess_key, 0);
+ 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);
diff --git a/source3/rpc_server/srv_netlog.c b/source3/rpc_server/srv_netlog.c
index 1f76d545f6..743e4477a6 100644
--- a/source3/rpc_server/srv_netlog.c
+++ b/source3/rpc_server/srv_netlog.c
@@ -402,7 +402,7 @@ static void api_net_srv_pwset( int uid,
DEBUG(100,("%02X ", q_a.pwd[i]));
DEBUG(100,("\n"));
- cred_hash3( pwd, q_a.pwd, vuser->dc.sess_key, 1);
+ cred_hash3( pwd, q_a.pwd, vuser->dc.sess_key, 0);
/* lies! nt and lm passwords are _not_ the same: don't care */
smb_pass->smb_passwd = pwd;
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index ac18bb4038..83293a5787 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -26,6 +26,7 @@ pstring servicesf = CONFIGFILE;
extern pstring debugf;
extern pstring sesssetup_user;
extern fstring global_myworkgroup;
+extern pstring global_myname;
char *InBuffer = NULL;
char *OutBuffer = NULL;
@@ -4942,6 +4943,21 @@ static void init_structs(void )
int i;
get_myname(myhostname,NULL);
+ /*
+ * Set the machine NETBIOS name if not already
+ * set from the config file.
+ */
+
+ if (!*global_myname)
+ {
+ char *p;
+ fstrcpy( global_myname, myhostname );
+ p = strchr( global_myname, '.' );
+ if (p)
+ *p = 0;
+ }
+ strupper( global_myname );
+
for (i=0;i<MAX_CONNECTIONS;i++)
{
Connections[i].open = False;
diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c
index 8086253349..338c0d5650 100644
--- a/source3/utils/smbpasswd.c
+++ b/source3/utils/smbpasswd.c
@@ -19,7 +19,11 @@
#include "includes.h"
+extern pstring myhostname;
extern pstring global_myname;
+extern fstring global_myworkgroup;
+
+static char *prog_name;
/*********************************************************
Print command usage on stderr and die.
@@ -29,13 +33,225 @@ static void usage(char *name, BOOL is_root)
{
if(is_root)
fprintf(stderr, "Usage is : %s [-D DEBUGLEVEL] [-a] [-d] [-m] [-n] [username] [password]\n\
-%s: [-R <name resolve order>] [-D DEBUGLEVEL] [-r machine] [username] [password]\n%s: [-h]\n", name, name, name);
+%s: [-R <name resolve order>] [-D DEBUGLEVEL] [-j DOMAINNAME] [-r machine] [username] [password]\n%s: [-h]\n", name, name, name);
else
fprintf(stderr, "Usage is : %s [-h] [-D DEBUGLEVEL] [-r machine] [password]\n", name);
exit(1);
}
/*********************************************************
+Join a domain.
+**********************************************************/
+
+static int setup_account( char *domain, char *remote_machine,
+ unsigned char orig_machine_passwd_hash[16],
+ unsigned char new_machine_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_machine_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_machine_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;
+ fstring machine_passwd;
+ unsigned char machine_passwd_hash[16];
+ unsigned char new_machine_passwd_hash[16];
+ void *vp;
+ int ret = 1;
+
+ fstrcpy(remote_machine, remote ? remote : "");
+ fstrcpy(machine_passwd, global_myname);
+ strlower(machine_passwd);
+ E_md4hash( machine_passwd, machine_passwd_hash);
+
+ generate_random_buffer( new_machine_passwd_hash, 16, True);
+
+ /* 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);
+ return 1;
+ }
+
+ /*
+ * Write the new machine password.
+ */
+
+ /*
+ * Get the machine account password.
+ */
+ if((vp = machine_password_lock( domain, global_myname, True)) == NULL) {
+ fprintf(stderr, "%s: unable to open the machine account password file for \
+machine %s in domain %s.\n", prog_name, global_myname, domain);
+ return 1;
+ }
+
+ if(!set_machine_account_password( vp, new_machine_passwd_hash)) {
+ fprintf(stderr, "%s: unable to read the machine account password for \
+machine %s in domain %s.\n", prog_name, global_myname, domain);
+ machine_password_unlock(vp);
+ return 1;
+ }
+
+ machine_password_unlock(vp);
+
+ /*
+ * If we are given a remote machine assume this is the PDC.
+ */
+
+ if(remote != NULL) {
+ strupper(remote_machine);
+ ret = setup_account( domain, remote_machine, machine_passwd_hash, new_machine_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.
+ */
+
+ p = lp_passwordserver();
+
+ if(!*p)
+ 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, machine_passwd_hash, new_machine_passwd_hash) == 0) {
+ printf("%s: Joined domain %s.\n", prog_name, domain);
+ return 0;
+ }
+ }
+ }
+
+ if(ret) {
+ machine_password_delete( domain, global_myname);
+ fprintf(stderr,"%s: Unable to join domain %s.\n", prog_name, domain);
+ }
+
+ return ret;
+}
+
+/*********************************************************
Start here.
**********************************************************/
@@ -44,7 +260,6 @@ int main(int argc, char **argv)
extern char *optarg;
extern int optind;
extern int DEBUGLEVEL;
- char *prog_name;
int real_uid;
struct passwd *pwd;
fstring old_passwd;
@@ -59,11 +274,13 @@ int main(int argc, char **argv)
BOOL is_root = False;
pstring user_name;
char *remote_machine = NULL;
- BOOL add_user = False;
- BOOL got_new_pass = False;
- BOOL machine_account = False;
- BOOL disable_user = False;
- BOOL set_no_password = False;
+ BOOL add_user = False;
+ BOOL got_new_pass = False;
+ BOOL machine_account = False;
+ BOOL disable_user = False;
+ BOOL set_no_password = False;
+ BOOL joining_domain = False;
+ char *new_domain = NULL;
pstring servicesf = CONFIGFILE;
void *vp;
@@ -84,7 +301,26 @@ int main(int argc, char **argv)
if (!lp_load(servicesf,True,False,False)) {
fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n", prog_name, servicesf);
}
+
+ if(!get_myname(myhostname,NULL)) {
+ fprintf(stderr, "%s: unable to get my hostname.\n", prog_name );
+ exit(1);
+ }
+
+ /*
+ * Set the machine NETBIOS name if not already
+ * set from the config file.
+ */
+ if (!*global_myname)
+ {
+ fstrcpy( global_myname, myhostname );
+ p = strchr( global_myname, '.' );
+ if (p)
+ *p = 0;
+ }
+ strupper( global_myname );
+
codepage_initialise(lp_client_code_page());
/* Get the real uid */
@@ -98,7 +334,7 @@ int main(int argc, char **argv)
is_root = (real_uid == 0);
- while ((ch = getopt(argc, argv, "adhmnr:R:D:")) != EOF) {
+ while ((ch = getopt(argc, argv, "adhmnj:r:R:D:")) != EOF) {
switch(ch) {
case 'a':
if(is_root)
@@ -139,6 +375,14 @@ int main(int argc, char **argv)
} else
usage(prog_name, is_root);
break;
+ case 'j':
+ if(is_root) {
+ new_domain = optarg;
+ strupper(new_domain);
+ joining_domain = True;
+ } else
+ usage(prog_name, is_root);
+ break;
case 'h':
default:
usage(prog_name, is_root);
@@ -149,13 +393,24 @@ int main(int argc, char **argv)
argv += optind;
/*
- * Ensure add_user and remote machine are
+ * Ensure add_user and either remote machine or join domain are
* not both set.
*/
- if(add_user && (remote_machine != NULL))
+
+ if(add_user && ((remote_machine != NULL) || joining_domain))
+ usage(prog_name, True);
+
+ /*
+ * Deal with joining a domain.
+ */
+ if(joining_domain && argc != 0)
usage(prog_name, True);
- if( is_root ) {
+ if(joining_domain) {
+ return join_domain( new_domain, remote_machine);
+ }
+
+ if(is_root) {
/*
* Deal with root - can add a user, but only locally.
@@ -297,11 +552,6 @@ int main(int argc, char **argv)
struct cli_state cli;
struct in_addr ip;
- if(get_myname(global_myname,NULL) == False) {
- fprintf(stderr, "%s: unable to get my hostname.\n", prog_name );
- exit(1);
- }
-
if(!resolve_name( remote_machine, &ip)) {
fprintf(stderr, "%s: unable to find an IP address for machine %s.\n",
prog_name, remote_machine );