Added load_interfaces in smbpasswd to allow name resolution by broadcast and
[samba.git] / source3 / utils / smbpasswd.c
index 167eb2ed5f3695458f584caa5a51cae545454c4c..157583925b4af98d199c72842498088df0aaa058 100644 (file)
@@ -1,8 +1,6 @@
-#ifdef SMB_PASSWD
-
 /*
  * Unix SMB/Netbios implementation. Version 1.9. smbpasswd module. Copyright
- * (C) Jeremy Allison 1995.
+ * (C) Jeremy Allison 1995-1998
  * 
  * 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
  */
 
 #include "includes.h"
-#include "des.h"
 
-/* Static buffers we will return. */
-static struct smb_passwd pw_buf;
-static pstring  user_name;
-static unsigned char smbpwd[16];
-static unsigned char smbntpwd[16];
+extern pstring myhostname;
+extern pstring global_myname;
+extern int DEBUGLEVEL;
 
-static int gethexpwd(char *p, char *pwd)
+/*
+ * Next two lines needed for SunOS and don't
+ * hurt anything else...
+ */
+extern char *optarg;
+extern int optind;
+
+/*********************************************************
+a strdup with exit
+**********************************************************/
+static char *xstrdup(char *s)
 {
-       int i;
-       unsigned char   lonybble, hinybble;
-       char           *hexchars = "0123456789ABCDEF";
-       char           *p1, *p2;
-       for (i = 0; i < 32; i += 2) {
-               hinybble = toupper(p[i]);
-               lonybble = toupper(p[i + 1]);
+       s = strdup(s);
+       if (!s) {
+               fprintf(stderr,"out of memory\n");
+               exit(1);
+       }
+       return s;
+}
 
-               p1 = strchr(hexchars, hinybble);
-               p2 = strchr(hexchars, lonybble);
-               if (!p1 || !p2)
-                       return (False);
 
-               hinybble = PTR_DIFF(p1, hexchars);
-               lonybble = PTR_DIFF(p2, hexchars);
+/*********************************************************
+ Print command usage on stderr and die.
+**********************************************************/
+static void usage(void)
+{
+       if (getuid() == 0) {
+               printf("smbpasswd [options] [username] [password]\n");
+       } else {
+               printf("smbpasswd [options] [password]\n");
+       }
+       printf("options:\n");
+       printf("  -s                   use stdin for password prompt\n");
+       printf("  -D LEVEL             debug level\n");
+       printf("  -U USER              remote username\n");
+       printf("  -r MACHINE           remote machine\n");
 
-               pwd[i / 2] = (hinybble << 4) | lonybble;
+       if (getuid() == 0) {
+               printf("  -R ORDER             name resolve order\n");
+               printf("  -j DOMAIN            join domain name\n");
+               printf("  -a                   add user\n");
+               printf("  -d                   disable user\n");
+               printf("  -e                   enable user\n");
+               printf("  -n                   set no password\n");
+               printf("  -m                   machine trust account\n");
        }
-       return (True);
+       exit(1);
 }
 
-struct smb_passwd *
-_my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd, 
-               BOOL *got_valid_nt_entry, long *pwd_seekpos)
+/*********************************************************
+Join a domain.
+**********************************************************/
+static int join_domain(char *domain, char *remote)
 {
-       char            linebuf[256];
-       unsigned char   c;
-       unsigned char  *p;
-       long            uidval;
-       long            linebuf_len;
+       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;
+       }
+
+       /*
+        * Create the machine account password file.
+        */
+       if(!trust_password_lock( domain, global_myname, True)) {
+               fprintf(stderr, "unable to open the machine account password file for \
+machine %s in domain %s.\n", global_myname, domain); 
+               return 1;
+       }
+
+       /*
+        * Write the old machine account password.
+        */
+       
+       if(!set_trust_account_password( orig_trust_passwd_hash)) {              
+               fprintf(stderr, "unable to write the machine account password for \
+machine %s in domain %s.\n", global_myname, domain);
+               trust_password_unlock();
+               return 1;
+       }
+       
        /*
-        * Scan the file, a line at a time and check if the name matches.
+        * If we are given a remote machine assume this is the PDC.
         */
-       while (!feof(fp)) {
-               linebuf[0] = '\0';
-               *pwd_seekpos = ftell(fp);
+       
+       if(remote == NULL) {
+               pstrcpy(remote_machine, lp_passwordserver());
+       }
 
-               fgets(linebuf, 256, fp);
-               if (ferror(fp))
-                       return NULL;
+       if(!*remote_machine) {
+               fprintf(stderr, "No password server list given in smb.conf - \
+unable to join domain.\n");
+               trust_password_unlock();
+               return 1;
+       }
 
-               /*
-                * Check if the string is terminated with a newline - if not
-                * then we must keep reading and discard until we get one.
-                */
-               linebuf_len = strlen(linebuf);
-               if (linebuf[linebuf_len - 1] != '\n') {
-                       c = '\0';
-                       while (!ferror(fp) && !feof(fp)) {
-                               c = fgetc(fp);
-                               if (c == '\n')
-                                       break;
-                       }
-               } else
-                       linebuf[linebuf_len - 1] = '\0';
+       ret = change_trust_account_password( domain, remote_machine);
+       trust_password_unlock();
+       
+       if(!ret) {
+               trust_password_delete( domain, global_myname);
+               fprintf(stderr,"Unable to join domain %s.\n",domain);
+       } else {
+               printf("Joined domain %s.\n",domain);
+       }
+       
+       return (int)ret;
+}
 
-               if ((linebuf[0] == 0) && feof(fp))
+
+static void set_line_buffering(FILE *f)
+{
+       setvbuf(f, NULL, _IOLBF, 0);
+}
+
+/*************************************************************
+ Utility function to prompt for passwords from stdin. Each
+ password entered must end with a newline.
+*************************************************************/
+static char *stdin_new_passwd(void)
+{
+       static fstring new_passwd;
+       size_t len;
+
+       ZERO_ARRAY(new_passwd);
+
+       /*
+        * if no error is reported from fgets() and string at least contains
+        * the newline that ends the password, then replace the newline with
+        * a null terminator.
+        */
+       if ( fgets(new_passwd, sizeof(new_passwd), stdin) != NULL) {
+               if ((len = strlen(new_passwd)) > 0) {
+                       if(new_passwd[len-1] == '\n')
+                               new_passwd[len - 1] = 0; 
+               }
+       }
+       return(new_passwd);
+}
+
+
+/*************************************************************
+ Utility function to get passwords via tty or stdin
+ Used if the '-s' option is set to silently get passwords
+ to enable scripting.
+*************************************************************/
+static char *get_pass( char *prompt, BOOL stdin_get)
+{
+       char *p;
+       if (stdin_get) {
+               p = stdin_new_passwd();
+       } else {
+               p = getpass(prompt);
+       }
+       return xstrdup(p);
+}
+
+/*************************************************************
+ Utility function to prompt for new password.
+*************************************************************/
+static char *prompt_for_new_password(BOOL stdin_get)
+{
+       char *p;
+       fstring new_passwd;
+
+       ZERO_ARRAY(new_passwd);
+       p = get_pass("New SMB password:", stdin_get);
+
+       fstrcpy(new_passwd, p);
+
+       p = get_pass("Retype new SMB password:", stdin_get);
+
+       if (strcmp(p, new_passwd)) {
+               fprintf(stderr, "Mismatch - password unchanged.\n");
+               return NULL;
+       }
+
+       return xstrdup(p);
+}
+
+
+/*************************************************************
+change a password either locally or remotely
+*************************************************************/
+static BOOL password_change(const char *remote_machine, char *user_name, 
+                           char *old_passwd, char *new_passwd, 
+                           BOOL add_user, BOOL enable_user, 
+                           BOOL disable_user, BOOL set_no_password,
+                           BOOL trust_account)
+{
+       BOOL ret;
+       pstring err_str;
+       pstring msg_str;
+
+       if (remote_machine != NULL) {
+               if (add_user || enable_user || disable_user || set_no_password || trust_account) {
+                       /* these things can't be done remotely yet */
+                       return False;
+               }
+               ret = remote_password_change(remote_machine, user_name, 
+                                                                        old_passwd, new_passwd, err_str, sizeof(err_str));
+               if(*err_str)
+                       fprintf(stderr, err_str);
+               return ret;
+       }
+       
+       ret = local_password_change(user_name, trust_account, add_user, enable_user, 
+                                    disable_user, set_no_password, new_passwd, 
+                                    err_str, sizeof(err_str), msg_str, sizeof(msg_str));
+
+       if(*msg_str)
+               printf(msg_str);
+       if(*err_str)
+               fprintf(stderr, err_str);
+
+       return ret;
+}
+
+
+/*************************************************************
+handle password changing for root
+*************************************************************/
+static int process_root(int argc, char *argv[])
+{
+       struct passwd  *pwd;
+       int ch;
+       BOOL joining_domain = False;
+       BOOL trust_account = False;
+       BOOL add_user = False;
+       BOOL disable_user = False;
+       BOOL enable_user = False;
+       BOOL set_no_password = False;
+       BOOL stdin_passwd_get = False;
+       char *user_name = NULL;
+       char *new_domain = NULL;
+       char *new_passwd = NULL;
+       char *old_passwd = NULL;
+       char *remote_machine = NULL;
+
+       while ((ch = getopt(argc, argv, "adehmnj:r:sR:D:U:")) != EOF) {
+               switch(ch) {
+               case 'a':
+                       add_user = True;
+                       break;
+               case 'd':
+                       disable_user = True;
+                       new_passwd = "XXXXXX";
+                       break;
+               case 'e':
+                       enable_user = True;
+                       break;
+               case 'D':
+                       DEBUGLEVEL = atoi(optarg);
+                       break;
+               case 'n':
+                       set_no_password = True;
+                       new_passwd = "NO PASSWORD";
+               case 'r':
+                       remote_machine = optarg;
+                       break;
+               case 's':
+                       set_line_buffering(stdin);
+                       set_line_buffering(stdout);
+                       set_line_buffering(stderr);
+                       stdin_passwd_get = True;
+                       break;
+               case 'R':
+                       lp_set_name_resolve_order(optarg);
+                       break;
+               case 'm':
+                       trust_account = True;
+                       break;
+               case 'j':
+                       new_domain = optarg;
+                       strupper(new_domain);
+                       joining_domain = True;
+                       break;
+               case 'U':
+                       user_name = optarg;
                        break;
+               default:
+                       usage();
+               }
+       }
+       
+       argc -= optind;
+       argv += optind;
+
+
+       /*
+        * Ensure add_user and either remote machine or join domain are
+        * not both set.
+        */     
+       if(add_user && ((remote_machine != NULL) || joining_domain)) {
+               usage();
+       }
+       
+       if(joining_domain) {
+               if (argc != 0) usage();
+               return join_domain(new_domain, remote_machine);
+       }
+
+       /*
+        * Deal with root - can add a user, but only locally.
+        */
+
+       switch(argc) {
+       case 0:
+               break;
+       case 1:
+               user_name = argv[0];
+               break;
+       case 2:
+               user_name = argv[0];
+               new_passwd = argv[1];
+               break;
+       default:
+               usage();
+       }
+
+       if (!user_name && (pwd = getpwuid(0))) {
+               user_name = xstrdup(pwd->pw_name);
+       } 
+
+       if (!user_name) {
+               fprintf(stderr,"You must specify a username\n");
+               exit(1);
+       }
+
+       if (trust_account) {
+               /* add the $ automatically */
+               static fstring buf;
+
                /*
-                * The line we have should be of the form :-
-                * 
-                * username:uid:[32hex bytes]:....other flags presently
-                * ignored....
-                * 
-                * or,
-                * 
-                * username:uid:[32hex bytes]:[32hex bytes]:....ignored....
-                * 
-                * if Windows NT compatible passwords are also present.
+                * Remove any trailing '$' before we
+                * generate the initial machine password.
                 */
 
-               if (linebuf[0] == '#' || linebuf[0] == '\0')
-                       continue;
-               p = (unsigned char *) strchr(linebuf, ':');
-               if (p == NULL)
-                       continue;
+               if (user_name[strlen(user_name)-1] == '$') {
+                       user_name[strlen(user_name)-1] = 0;
+               }
+
+               if (add_user) {
+                       new_passwd = xstrdup(user_name);
+                       strlower(new_passwd);
+               }
+
                /*
-                * As 256 is shorter than a pstring we don't need to check
-                * length here - if this ever changes....
+                * Now ensure the username ends in '$' for
+                * the machine add.
                 */
-               strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
-               user_name[PTR_DIFF(p, linebuf)] = '\0';
-               if (!strequal(user_name, name))
-                       continue;
 
-               /* User name matches - get uid and password */
-               p++;            /* Go past ':' */
-               if (!isdigit(*p))
-                       return (False);
+               slprintf(buf, sizeof(buf)-1, "%s$", user_name);
+               user_name = buf;
+       }
 
-               uidval = atoi((char *) p);
-               while (*p && isdigit(*p))
-                       p++;
+       if (!remote_machine && !Get_Pwnam(user_name, True)) {
+               fprintf(stderr, "User \"%s\" was not found in system password file.\n", 
+                       user_name);
+               exit(1);
+       }
 
-               if (*p != ':')
-                       return (False);
+       if (remote_machine != NULL) {
+               old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
+       }
+       
+       if (!new_passwd) {
 
                /*
-                * Now get the password value - this should be 32 hex digits
-                * which are the ascii representations of a 16 byte string.
-                * Get two at a time and put them into the 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.
                 */
-               p++;
-               *pwd_seekpos += PTR_DIFF(p, linebuf);   /* Save exact position
-                                                        * of passwd in file -
-                                                        * this is used by
-                                                        * smbpasswd.c */
-               if (*p == '*' || *p == 'X') {
-                       /* Password deliberately invalid - end here. */
-                       *valid_old_pwd = False;
-                       *got_valid_nt_entry = False;
-                       pw_buf.smb_nt_passwd = NULL;    /* No NT password (yet)*/
-
-                       /* Now check if the NT compatible password is
-                          available. */
-                       p += 33; /* Move to the first character of the line after 
-                                               the lanman password. */
-                       if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
-                               /* NT Entry was valid - even if 'X' or '*', can be overwritten */
-                               *got_valid_nt_entry = True;
-                               if (*p != '*' && *p != 'X') {
-                                       if(gethexpwd(p,smbntpwd))
-                                               pw_buf.smb_nt_passwd = smbntpwd;
-                               }
+
+               if(enable_user) {
+                       struct smb_passwd *smb_pass = getsmbpwnam(user_name);
+                       if((smb_pass != NULL) && (smb_pass->smb_passwd != NULL)) {
+                               new_passwd = "XXXX"; /* Don't care. */
                        }
-                       pw_buf.smb_name = user_name;
-                       pw_buf.smb_userid = uidval;
-                       pw_buf.smb_passwd = NULL;       /* No password */
-                       return (&pw_buf);
                }
-               if (linebuf_len < (PTR_DIFF(p, linebuf) + 33))
-                       return (False);
 
-               if (p[32] != ':')
-                       return (False);
+               if(!new_passwd)
+                       new_passwd = prompt_for_new_password(stdin_passwd_get);
+       }
+       
+       if (!password_change(remote_machine, user_name, old_passwd, new_passwd,
+                            add_user, enable_user, disable_user, set_no_password,
+                            trust_account)) {
+               fprintf(stderr,"Failed to change password entry for %s\n", user_name);
+               return 1;
+       } 
 
-               if (!strncasecmp(p, "NO PASSWORD", 11)) {
-                       pw_buf.smb_passwd = NULL;       /* No password */
-               } else {
-                       if(!gethexpwd(p,smbpwd))
-                               return False;
-                       pw_buf.smb_passwd = smbpwd;
+       if(disable_user) {
+               printf("User %s disabled.\n", user_name);
+       } else if(enable_user) {
+               printf("User %s enabled.\n", user_name);
+       } else if (set_no_password) {
+               printf("User %s - set to no password.\n", user_name);
+       } else {
+               printf("Password changed for user %s\n", user_name);
+       }
+       return 0;
+}
+
+
+/*************************************************************
+handle password changing for non-root
+*************************************************************/
+static int process_nonroot(int argc, char *argv[])
+{
+       struct passwd  *pwd = NULL;
+       int ch;
+       BOOL stdin_passwd_get = False;
+       char *old_passwd = NULL;
+       char *remote_machine = NULL;
+       char *user_name = NULL;
+       char *new_passwd = NULL;
+
+       while ((ch = getopt(argc, argv, "hD:r:sU:")) != EOF) {
+               switch(ch) {
+               case 'D':
+                       DEBUGLEVEL = atoi(optarg);
+                       break;
+               case 'r':
+                       remote_machine = optarg;
+                       break;
+               case 's':
+                       set_line_buffering(stdin);
+                       set_line_buffering(stdout);
+                       set_line_buffering(stderr);
+                       stdin_passwd_get = True;
+                       break;
+               case 'U':
+                       user_name = optarg;
+                       break;
+               default:
+                       usage();
                }
+       }
+       
+       argc -= optind;
+       argv += optind;
 
-               pw_buf.smb_name = user_name;
-               pw_buf.smb_userid = uidval;
-               pw_buf.smb_nt_passwd = NULL;
-               *got_valid_nt_entry = False;
-               *valid_old_pwd = True;
-
-               /* Now check if the NT compatible password is
-                  available. */
-               p += 33; /* Move to the first character of the line after 
-                                       the lanman password. */
-               if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
-                       /* NT Entry was valid - even if 'X' or '*', can be overwritten */
-                       *got_valid_nt_entry = True;
-                       if (*p != '*' && *p != 'X') {
-                               if(gethexpwd(p,smbntpwd))
-                                       pw_buf.smb_nt_passwd = smbntpwd;
-                       }
+       if(argc > 1) {
+               usage();
+       }
+       
+       if (argc == 1) {
+               new_passwd = argv[0];
+       }
+       
+       if (!user_name) {
+               pwd = getpwuid(getuid());
+               if (pwd) {
+                       user_name = xstrdup(pwd->pw_name);
+               } else {
+                       fprintf(stderr,"you don't exist - go away\n");
+                       exit(1);
                }
-               return &pw_buf;
        }
-       return NULL;
-}
+       
+       /*
+        * A non-root user is always setting a password
+        * via a remote machine (even if that machine is
+        * localhost).
+        */     
+       if (remote_machine == NULL) {
+               remote_machine = "127.0.0.1";
+       }
 
-/*
- * Print command usage on stderr and die.
- */
-void 
-usage(char *name)
-{
-       fprintf(stderr, "Usage is : %s [username]\n", name);
-       exit(1);
+
+       if (remote_machine != NULL) {
+               old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
+       }
+       
+       if (!new_passwd) {
+               new_passwd = prompt_for_new_password(stdin_passwd_get);
+       }
+       
+       if (!new_passwd) {
+               printf("unable to get new password\n");
+               exit(0);
+       }
+
+       if (!password_change(remote_machine, user_name, old_passwd, new_passwd,
+                            False, False, False, False, False)) {
+               fprintf(stderr,"Failed to change password for %s\n", user_name);
+               return 1;
+       }
+
+       printf("Password changed for user %s\n", user_name);
+       return 0;
 }
 
+
+
+/*********************************************************
+ Start here.
+**********************************************************/
 int main(int argc, char **argv)
-{
-  int             real_uid;
-  struct passwd  *pwd;
-  fstring         old_passwd;
-  uchar           old_p16[16];
-  uchar           old_nt_p16[16];
-  fstring         new_passwd;
-  uchar           new_p16[16];
-  uchar           new_nt_p16[16];
-  char           *p;
-  struct smb_passwd *smb_pwent;
-  FILE           *fp;
-  BOOL            valid_old_pwd = False;
-  BOOL                         got_valid_nt_entry = False;
-  long            seekpos;
-  int             pwfd;
-  char            ascii_p16[66];
-  char            c;
-  int             ret, i, err, writelen;
-  int             lockfd = -1;
-  char           *pfile = SMB_PASSWD_FILE;
-  char            readbuf[16 * 1024];
-  
-  setup_logging(argv[0],True);
-  
-  charset_initialise();
-  
-#ifndef DEBUG_PASSWORD
-  /* Check the effective uid */
-  if (geteuid() != 0) {
-    fprintf(stderr, "%s: Must be setuid root.\n", argv[0]);
-    exit(1);
-  }
-#endif
-  
-  /* Get the real uid */
-  real_uid = getuid();
-  
-  /* Deal with usage problems */
-  if (real_uid == 0) {
-    /* As root we can change anothers password. */
-    if (argc != 1 && argc != 2)
-      usage(argv[0]);
-  } else if (argc != 1)
-    usage(argv[0]);
-  
-  
-  if (real_uid == 0 && argc == 2) {
-    /* If we are root we can change anothers password. */
-    strncpy(user_name, argv[1], sizeof(user_name) - 1);
-    user_name[sizeof(user_name) - 1] = '\0';
-    pwd = getpwnam(user_name);
-  } else {
-    pwd = getpwuid(real_uid);
-  }
-  
-  if (pwd == 0) {
-    fprintf(stderr, "%s: Unable to get UNIX password entry for user.\n", argv[0]);
-    exit(1);
-  }
-  /* If we are root we don't ask for the old password. */
-  old_passwd[0] = '\0';
-  if (real_uid != 0) {
-    p = getpass("Old SMB password:");
-    strncpy(old_passwd, p, sizeof(fstring));
-    old_passwd[sizeof(fstring)-1] = '\0';
-  }
-  new_passwd[0] = '\0';
-  p = getpass("New SMB password:");
-  strncpy(new_passwd, p, sizeof(fstring));
-  new_passwd[sizeof(fstring)-1] = '\0';
-  p = getpass("Retype new SMB password:");
-  if (strcmp(p, new_passwd)) {
-    fprintf(stderr, "%s: Mismatch - password unchanged.\n", argv[0]);
-    exit(1);
-  }
-  
-  if (new_passwd[0] == '\0') {
-    printf("Password not set\n");
-    exit(0);
-  }
-  
-  /* Calculate the MD4 hash (NT compatible) of the old and new passwords */
-  memset(old_nt_p16, '\0', 16);
-  E_md4hash((uchar *)old_passwd, old_nt_p16);
-  
-  memset(new_nt_p16, '\0', 16);
-  E_md4hash((uchar *) new_passwd, new_nt_p16);
-  
-  /* Mangle the passwords into Lanman format */
-  old_passwd[14] = '\0';
-  strupper(old_passwd);
-  new_passwd[14] = '\0';
-  strupper(new_passwd);
-  
-  /*
-   * Calculate the SMB (lanman) hash functions of both old and new passwords.
-   */
-  
-  memset(old_p16, '\0', 16);
-  E_P16((uchar *) old_passwd, old_p16);
-  
-  memset(new_p16, '\0', 16);
-  E_P16((uchar *) new_passwd, new_p16);
-  
-  /*
-   * Open the smbpaswd file XXXX - we need to parse smb.conf to get the
-   * filename
-   */
-  if ((fp = fopen(pfile, "r+")) == NULL) {
-    err = errno;
-    fprintf(stderr, "%s: Failed to open password file %s.\n",
-           argv[0], pfile);
-    errno = err;
-    perror(argv[0]);
-    exit(err);
-  }
-  /* Set read buffer to 16k for effiecient reads */
-  setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
-  
-  /* make sure it is only rw by the owner */
-  chmod(pfile, 0600);
-  
-  /* Lock the smbpasswd file for write. */
-  if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) {
-    err = errno;
-    fprintf(stderr, "%s: Failed to lock password file %s.\n",
-           argv[0], pfile);
-    fclose(fp);
-    errno = err;
-    perror(argv[0]);
-    exit(err);
-  }
-  /* Get the smb passwd entry for this user */
-  smb_pwent = _my_get_smbpwnam(fp, pwd->pw_name, &valid_old_pwd, 
-                              &got_valid_nt_entry, &seekpos);
-  if (smb_pwent == NULL) {
-    fprintf(stderr, "%s: Failed to find entry for user %s in file %s.\n",
-           argv[0], pwd->pw_name, pfile);
-    fclose(fp);
-    pw_file_unlock(lockfd);
-    exit(1);
-  }
-  /* If we are root we don't need to check the old password. */
-  if (real_uid != 0) {
-    if ((valid_old_pwd == False) || (smb_pwent->smb_passwd == NULL)) {
-      fprintf(stderr, "%s: User %s is disabled, plase contact your administrator to enable it.\n", argv[0], pwd->pw_name);
-      fclose(fp);
-      pw_file_unlock(lockfd);
-      exit(1);
-    }
-    /* Check the old Lanman password */
-    if (memcmp(old_p16, smb_pwent->smb_passwd, 16)) {
-      fprintf(stderr, "%s: Couldn't change password.\n", argv[0]);
-      fclose(fp);
-      pw_file_unlock(lockfd);
-      exit(1);
-    }
-    /* Check the NT password if it exists */
-    if (smb_pwent->smb_nt_passwd != NULL) {
-      if (memcmp(old_nt_p16, smb_pwent->smb_nt_passwd, 16)) {
-       fprintf(stderr, "%s: Couldn't change password.\n", argv[0]);
-       fclose(fp);
-       pw_file_unlock(lockfd);
-       exit(1);
-      }
-    }
-  }
-  /*
-   * If we get here either we were root or the old password checked out
-   * ok.
-   */
-  /* Create the 32 byte representation of the new p16 */
-  for (i = 0; i < 16; i++) {
-    sprintf(&ascii_p16[i * 2], "%02X", (uchar) new_p16[i]);
-  }
-  if(got_valid_nt_entry) {
-    /* Add on the NT md4 hash */
-    ascii_p16[32] = ':';
-    for (i = 0; i < 16; i++) {
-      sprintf(&ascii_p16[(i * 2)+33], "%02X", (uchar) new_nt_p16[i]);
-    }
-  }
-  /*
-   * Do an atomic write into the file at the position defined by
-   * seekpos.
-   */
-  pwfd = fileno(fp);
-  ret = lseek(pwfd, seekpos - 1, SEEK_SET);
-  if (ret != seekpos - 1) {
-    err = errno;
-    fprintf(stderr, "%s: seek fail on file %s.\n",
-           argv[0], pfile);
-    fclose(fp);
-    errno = err;
-    perror(argv[0]);
-    pw_file_unlock(lockfd);
-    exit(1);
-  }
-  /* Sanity check - ensure the character is a ':' */
-  if (read(pwfd, &c, 1) != 1) {
-    err = errno;
-    fprintf(stderr, "%s: read fail on file %s.\n",
-           argv[0], pfile);
-    fclose(fp);
-    errno = err;
-    perror(argv[0]);
-    pw_file_unlock(lockfd);
-    exit(1);
-  }
-  if (c != ':') {
-    fprintf(stderr, "%s: sanity check on passwd file %s failed.\n",
-           argv[0], pfile);
-    fclose(fp);
-    pw_file_unlock(lockfd);
-    exit(1);
-  }
-  writelen = (got_valid_nt_entry) ? 65 : 32;
-  if (write(pwfd, ascii_p16, writelen) != writelen) {
-    err = errno;
-    fprintf(stderr, "%s: write fail in file %s.\n",
-           argv[0], pfile);
-    fclose(fp);
-    errno = err;
-    perror(argv[0]);
-    pw_file_unlock(lockfd);
-    exit(err);
-  }
-  fclose(fp);
-  pw_file_unlock(lockfd);
-  printf("Password changed\n");
-  return 0;
-}
+{      
+       static pstring servicesf = CONFIGFILE;
 
-#else
+       TimeInit();
+       
+       setup_logging("smbpasswd", True);
+       
+       charset_initialise();
+       
+       if (!lp_load(servicesf,True,False,False)) {
+               fprintf(stderr, "Can't load %s - run testparm to debug it\n", 
+                       servicesf);
+               exit(1);
+       }
 
-#include "includes.h"
+       if(!get_myname(myhostname,NULL)) {
+               fprintf(stderr, "unable to get my hostname.\n");
+               exit(1);
+       }
 
-int 
-main(int argc, char **argv)
-{
-  printf("smb password encryption not selected in Makefile\n");
-  return 0;
+       /*
+        * 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);
+
+       codepage_initialise(lp_client_code_page());
+
+       load_interfaces();
+
+       if(!pwdb_initialise(False))
+       {
+               fprintf(stderr, "Can't setup password database vectors.\n");
+               exit(1);
+       }
+
+       /* Check the effective uid - make sure we are not setuid */
+       if ((geteuid() == (uid_t)0) && (getuid() != (uid_t)0)) {
+               fprintf(stderr, "smbpasswd must *NOT* be setuid root.\n");
+               exit(1);
+       }
+
+       if (getuid() == 0) {
+               return process_root(argc, argv);
+       } 
+
+       return process_nonroot(argc, argv);
 }
-#endif