summaryrefslogtreecommitdiff
path: root/source3/utils/smbpasswd.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1998-04-29 22:27:26 +0000
committerJeremy Allison <jra@samba.org>1998-04-29 22:27:26 +0000
commit90177708aaf5bf17d689979701b5f0156b8a2fa4 (patch)
treedcca0199c3d534976a204b8cd936109fbe5e69d8 /source3/utils/smbpasswd.c
parente305c2c9e2e657974d34d1d58a8f9372921fdae2 (diff)
downloadsamba-90177708aaf5bf17d689979701b5f0156b8a2fa4.tar.gz
samba-90177708aaf5bf17d689979701b5f0156b8a2fa4.tar.bz2
samba-90177708aaf5bf17d689979701b5f0156b8a2fa4.zip
Makefile: Added files to smbpasswd.c.
loadparm.c: Patch from tim@quiknet.com for static string problems. server.c: Setup global_myname. smbpass.c: Fix up locking. Add machine_password_delete() call. smbpasswd.c: Added provisional code to add to a domain. lib/rpc/client/cli_login.c: Fixed incorrect cred_hash3 call when setting machine password. lib/rpc/server/srv_netlog.c: Fixed incorrect cred_hash3 call when setting machine password. Jeremy. (This used to be commit 6a7164233e3bf9d6bb57c44a53204068e454ae5c)
Diffstat (limited to 'source3/utils/smbpasswd.c')
-rw-r--r--source3/utils/smbpasswd.c282
1 files changed, 266 insertions, 16 deletions
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 );