client/client.c:
authorJeremy Allison <jra@samba.org>
Fri, 25 Feb 2000 22:25:25 +0000 (22:25 +0000)
committerJeremy Allison <jra@samba.org>
Fri, 25 Feb 2000 22:25:25 +0000 (22:25 +0000)
libsmb/clientgen.c: Fixes for Win2k smbclient browsing.
Other fixes implement smbpasswd -x user to delete users. Also allows swat
to do the same.
Jeremy.
(This used to be commit 9f6ad046761adecafba59040baa3abc9f0959e65)

source3/client/client.c
source3/include/proto.h
source3/include/smb.h
source3/libsmb/clientgen.c
source3/passdb/ldap.c
source3/passdb/nispass.c
source3/passdb/passdb.c
source3/passdb/smbpass.c
source3/passdb/smbpasschange.c
source3/utils/smbpasswd.c
source3/web/swat.c

index 6beff70c9bc739f305ada1fdbda05df44f2995d9..ea029d4df7f6d77bc4d2a47cf72b62ec6d9c093e 100644 (file)
@@ -1560,10 +1560,15 @@ try and browse available connections on a host
 ****************************************************************************/
 static BOOL browse_host(BOOL sort)
 {
+       int ret;
+
         printf("\n\tSharename      Type      Comment\n");
         printf("\t---------      ----      -------\n");
 
-       return cli_RNetShareEnum(cli, browse_fn);
+       if((ret = cli_RNetShareEnum(cli, browse_fn)) == -1)
+               printf("Error returning browse list: %s\n", cli_errstr(cli));
+
+       return (ret != -1);
 }
 
 /****************************************************************************
index 934ec5a4c82b4e78f0315ebaeec8119ce08946ab..830e7bc5b1fd3735cfe6b2a4cce0769ebc13604a 100644 (file)
@@ -573,7 +573,7 @@ BOOL cli_api(struct cli_state *cli,
             char **rparam, int *rprcnt,
             char **rdata, int *rdrcnt);
 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation);
-BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *));
+int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *));
 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
                       void (*fn)(const char *, uint32, const char *));
 BOOL cli_session_setup(struct cli_state *cli, 
@@ -1426,6 +1426,7 @@ void endsmbpwent(void *vp);
 struct smb_passwd *getsmbpwent(void *vp);
 BOOL add_smbpwd_entry(struct smb_passwd *newpwd);
 BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override);
+BOOL del_smbpwd_entry(const char *name);
 struct smb_passwd *getsmbpwnam(char *name);
 struct smb_passwd *getsmbpwrid(uint32 user_rid);
 struct smb_passwd *getsmbpwuid(uid_t smb_userid);
@@ -1464,12 +1465,12 @@ BOOL lookup_local_name(char *domain, char *user, DOM_SID *psid, uint8 *psid_name
 
 /*The following definitions come from  passdb/smbpass.c  */
 
+char *format_new_smbpasswd_entry(struct smb_passwd *newpwd);
 struct passdb_ops *file_initialize_password_db(void);
 
 /*The following definitions come from  passdb/smbpasschange.c  */
 
-BOOL local_password_change(char *user_name, BOOL trust_account, BOOL add_user,
-                          BOOL enable_user, BOOL disable_user, BOOL set_no_password,
+BOOL local_password_change(char *user_name, int local_flags,
                           char *new_passwd, 
                           char *err_str, size_t err_str_len,
                           char *msg_str, size_t msg_str_len);
index 18b2cb154248507af923828dbc58d4d15656576c..54fb4d5cc7ccf66affe926cce8b3d80ad4148485 100644 (file)
@@ -747,6 +747,7 @@ struct passdb_ops {
    */
   BOOL (*add_smbpwd_entry)(struct smb_passwd *);
   BOOL (*mod_smbpwd_entry)(struct smb_passwd *, BOOL);
+  BOOL (*del_smbpwd_entry)(const char *);
 
   /*
    * Functions that manupulate a struct sam_passwd.
@@ -783,6 +784,17 @@ struct passdb_ops {
 #endif
 };
 
+/*
+ * Flags for local user manipulation.
+ */
+
+#define LOCAL_ADD_USER 0x1
+#define LOCAL_DELETE_USER 0x2
+#define LOCAL_DISABLE_USER 0x4
+#define LOCAL_ENABLE_USER 0x8
+#define LOCAL_TRUST_ACCOUNT 0x10
+#define LOCAL_SET_NO_PASSWORD 0x20
+
 /* key and data in the connections database - used in smbstatus and smbd */
 struct connections_key {
        pid_t pid;
index df3df0b4ba3289454d981923dedaf91934566626..8d7dbec8590c77816a0fb2167ca383f9006a2a04 100644 (file)
@@ -600,7 +600,7 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
 /****************************************************************************
 call a NetShareEnum - try and browse available connections on a host
 ****************************************************************************/
-BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *))
+int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *))
 {
   char *rparam = NULL;
   char *rdata = NULL;
@@ -618,12 +618,16 @@ BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, c
   pstrcpy(p,"B13BWz");
   p = skip_string(p,1);
   SSVAL(p,0,1);
-  SSVAL(p,2,0xFFFF);
+  /*
+   * Win2k needs a *smaller* buffer than 0xFFFF here -
+   * it returns "out of server memory" with 0xFFFF !!! JRA.
+   */
+  SSVAL(p,2,0xFFE0);
   p += 4;
 
   if (cli_api(cli, 
               param, PTR_DIFF(p,param), 1024,  /* Param, length, maxlen */
-              NULL, 0, 0xFFFF,            /* data, length, maxlen */
+              NULL, 0, 0xFFE0,            /* data, length, maxlen - Win2k needs a small buffer here too ! */
               &rparam, &rprcnt,                /* return params, length */
               &rdata, &rdrcnt))                /* return data, length */
     {
index 43fea00a64443c142acba8ad61ba8b3114458d93..54566e454b93c256b476b8c57ef640e6f1eb78a0 100644 (file)
@@ -970,6 +970,11 @@ static BOOL mod_ldappwd_entry(struct smb_passwd* pwd, BOOL override)
   return mod_ldap21pwd_entry(pdb_smb_to_sam(pwd), override);
 }
 
+static BOOL del_ldappwd_entry(const char *name)
+{
+  return False; /* Dummy... */
+}
+
 static struct sam_disp_info *getldapdispnam(char *name)
 {
        return pdb_sam_to_dispinfo(getldap21pwnam(name));
@@ -1002,6 +1007,7 @@ static struct passdb_ops ldap_ops =
        getldappwent,
        add_ldappwd_entry,
        mod_ldappwd_entry,
+       del_ldappwd_entry,
        getldap21pwent,
        iterate_getsam21pwnam,       /* From passdb.c */
        iterate_getsam21pwuid,       /* From passdb.c */
index 27409eca4cd4fdfbcb1ba85b495765d06ec756f5..4b4e281c29d57bd450b59c4d9f4f58b2544c6bdc 100644 (file)
@@ -1005,6 +1005,11 @@ static BOOL mod_nisppwd_entry(struct smb_passwd* pwd, BOOL override)
        return mod_nisp21pwd_entry(pdb_smb_to_sam(pwd), override);
 }
 
+static BOOL del_nisppwd_entry(const char *name)
+{
+       return False; /* Dummy. */
+}
+
 static struct smb_passwd *getnisppwnam(char *name)
 {
        return pdb_sam_to_smb(getnisp21pwnam(name));
@@ -1051,6 +1056,7 @@ static struct passdb_ops nispasswd_ops = {
   getnisppwent,
   add_nisppwd_entry,
   mod_nisppwd_entry,
+  del_nisppwd_entry,
   getnisp21pwent,
   getnisp21pwnam,
   getnisp21pwuid,
index f6502c238c424d746f1bcdc5e815b0c09080614b..30ea1d9bd6e98bc37fd4460170fab1529f33d368 100644 (file)
@@ -225,6 +225,15 @@ BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
        return pdb_ops->mod_smbpwd_entry(pwd, override);
 }
 
+/************************************************************************
+ Routine to delete an entry from the smb passwd file.
+*************************************************************************/
+
+BOOL del_smbpwd_entry(const char *name)
+{
+       return pdb_ops->del_smbpwd_entry(name);
+}
+
 /************************************************************************
  Routine to search smb passwd by name.
 *************************************************************************/
index 4cfac6d94845727e4002e88bcbd80e96469b70e2..4ca37a92965798af52ad5cab2d93c349c90617eb 100644 (file)
@@ -28,39 +28,127 @@ extern BOOL sam_logon_in_ssb;
 static char s_readbuf[1024];
 static int pw_file_lock_depth;
 
+enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE };
+
 /***************************************************************
- Start to enumerate the smbpasswd list. Returns a void pointer
- to ensure no modification outside this module.
+ Internal fn to enumerate the smbpasswd list. Returns a void pointer
+ to ensure no modification outside this module. Checks for atomic
+ rename of smbpasswd file on update or create once the lock has
+ been granted to prevent race conditions. JRA.
 ****************************************************************/
 
-static void *startsmbfilepwent(BOOL update)
+static void *startsmbfilepwent_internal(const char *pfile, enum pwf_access_type type, int *lock_depth)
 {
   FILE *fp = NULL;
-  char *pfile = lp_smb_passwd_file();
+  const char *open_mode = NULL;
+  int race_loop = 0;
+  int lock_type;
 
   if (!*pfile) {
     DEBUG(0, ("startsmbfilepwent: No SMB password file set\n"));
     return (NULL);
   }
-  DEBUG(10, ("startsmbfilepwent: opening file %s\n", pfile));
 
-  fp = sys_fopen(pfile, update ? "r+b" : "rb");
+  switch(type) {
+  case PWF_READ:
+    open_mode = "rb";
+    lock_type = F_RDLCK;
+    break;
+  case PWF_UPDATE:
+    open_mode = "r+b";
+    lock_type = F_WRLCK;
+    break;
+  case PWF_CREATE:
+    /*
+     * Ensure atomic file creation.
+     */
+    {
+      int i, fd = -1;
 
-  if (fp == NULL) {
-    DEBUG(0, ("startsmbfilepwent: unable to open file %s\n", pfile));
-    return NULL;
+      for(i = 0; i < 5; i++) {
+       if((fd = sys_open(pfile, O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600))!=-1)
+         break;
+       sys_usleep(200); /* Spin, spin... */
+      }
+      if(fd == -1) {
+       DEBUG(0,("startsmbfilepwent_internal: too many race conditions creating file %s\n", pfile));
+       return NULL;
+      }
+      close(fd);
+      open_mode = "r+b";
+      lock_type = F_WRLCK;
+      break;
+    }
   }
+                      
+  for(race_loop = 0; race_loop < 5; race_loop++) {
+    DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile));
 
-  /* Set a buffer to do more efficient reads */
-  setvbuf(fp, s_readbuf, _IOFBF, sizeof(s_readbuf));
+    if((fp = sys_fopen(pfile, open_mode)) == NULL) {
+      DEBUG(0, ("startsmbfilepwent_internal: unable to open file %s. Error was %s\n", pfile, strerror(errno) ));
+      return NULL;
+    }
 
-  if (!pw_file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, &pw_file_lock_depth))
-  {
-    DEBUG(0, ("startsmbfilepwent: unable to lock file %s\n", pfile));
-    fclose(fp);
+    if (!pw_file_lock(fileno(fp), lock_type, 5, lock_depth)) {
+      DEBUG(0, ("startsmbfilepwent_internal: unable to lock file %s. Error was %s\n", pfile, strerror(errno) ));
+      fclose(fp);
+      return NULL;
+    }
+
+    /*
+     * Only check for replacement races on update or create.
+     * For read we don't mind if the data is one record out of date.
+     */
+
+    if(type == PWF_READ) {
+      break;
+    } else {
+      SMB_STRUCT_STAT sbuf1, sbuf2;
+
+      /*
+       * Avoid the potential race condition between the open and the lock
+       * by doing a stat on the filename and an fstat on the fd. If the
+       * two inodes differ then someone did a rename between the open and
+       * the lock. Back off and try the open again. Only do this 5 times to
+       * prevent infinate loops. JRA.
+       */
+
+      if (sys_stat(pfile,&sbuf1) != 0) {
+       DEBUG(0, ("startsmbfilepwent_internal: unable to stat file %s. Error was %s\n", pfile, strerror(errno)));
+       pw_file_unlock(fileno(fp), lock_depth);
+       fclose(fp);
+       return False;
+      }
+
+      if (sys_fstat(fileno(fp),&sbuf2) != 0) {
+       DEBUG(0, ("startsmbfilepwent_internal: unable to fstat file %s. Error was %s\n", pfile, strerror(errno)));
+       pw_file_unlock(fileno(fp), lock_depth);
+       fclose(fp);
+       return False;
+      }
+
+      if( sbuf1.st_ino == sbuf2.st_ino) {
+       /* No race. */
+       break;
+      }
+
+      /*
+       * Race occurred - back off and try again...
+       */
+
+      pw_file_unlock(fileno(fp), lock_depth);
+      fclose(fp);
+    }
+  }
+
+  if(race_loop == 5) {
+    DEBUG(0, ("startsmbfilepwent_internal: too many race conditions opening file %s\n", pfile));
     return NULL;
   }
 
+  /* Set a buffer to do more efficient reads */
+  setvbuf(fp, s_readbuf, _IOFBF, sizeof(s_readbuf));
+
   /* Make sure it is only rw by the owner */
   chmod(pfile, 0600);
 
@@ -68,22 +156,43 @@ static void *startsmbfilepwent(BOOL update)
   return (void *)fp;
 }
 
+/***************************************************************
+ Start to enumerate the smbpasswd list. Returns a void pointer
+ to ensure no modification outside this module.
+****************************************************************/
+
+static void *startsmbfilepwent(BOOL update)
+{
+  return startsmbfilepwent_internal(lp_smb_passwd_file(), update ? PWF_UPDATE : PWF_READ, &pw_file_lock_depth);
+}
+
 /***************************************************************
  End enumeration of the smbpasswd list.
 ****************************************************************/
 
-static void endsmbfilepwent(void *vp)
+static void endsmbfilepwent_internal(void *vp, int *lock_depth)
 {
   FILE *fp = (FILE *)vp;
 
-  pw_file_unlock(fileno(fp), &pw_file_lock_depth);
+  pw_file_unlock(fileno(fp), lock_depth);
   fclose(fp);
-  DEBUG(7, ("endsmbfilepwent: closed password file.\n"));
+  DEBUG(7, ("endsmbfilepwent_internal: closed password file.\n"));
+}
+
+/***************************************************************
+ End enumeration of the smbpasswd list - operate on the default
+ lock_depth.
+****************************************************************/
+
+static void endsmbfilepwent(void *vp)
+{
+  endsmbfilepwent_internal(vp, &pw_file_lock_depth);
 }
 
 /*************************************************************************
  Routine to return the next entry in the smbpasswd list.
  *************************************************************************/
+
 static struct smb_passwd *getsmbfilepwent(void *vp)
 {
   /* Static buffers we will return. */
@@ -431,6 +540,65 @@ static BOOL setsmbfilepwpos(void *vp, SMB_BIG_UINT tok)
   return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET);
 }
 
+/************************************************************************
+ Create a new smbpasswd entry - malloced space returned.
+*************************************************************************/
+
+char *format_new_smbpasswd_entry(struct smb_passwd *newpwd)
+{
+  int new_entry_length;
+  char *new_entry;
+  char *p;
+  int i;
+
+  new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2;
+
+  if((new_entry = (char *)malloc( new_entry_length )) == NULL) {
+    DEBUG(0, ("format_new_smbpasswd_entry: Malloc failed adding entry for user %s.\n", newpwd->smb_name ));
+    return NULL;
+  }
+
+  slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->smb_name, (unsigned)newpwd->smb_userid);
+  p = &new_entry[strlen(new_entry)];
+
+  if(newpwd->smb_passwd != NULL) {
+    for( i = 0; i < 16; i++) {
+      slprintf((char *)&p[i*2], new_entry_length - (p - new_entry) - 1, "%02X", newpwd->smb_passwd[i]);
+    }
+  } else {
+    i=0;
+    if(newpwd->acct_ctrl & ACB_PWNOTREQ)
+      safe_strcpy((char *)p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
+    else
+      safe_strcpy((char *)p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
+  }
+  
+  p += 32;
+
+  *p++ = ':';
+
+  if(newpwd->smb_nt_passwd != NULL) {
+    for( i = 0; i < 16; i++) {
+      slprintf((char *)&p[i*2], new_entry_length - 1 - (p - new_entry), "%02X", newpwd->smb_nt_passwd[i]);
+    }
+  } else {
+    if(newpwd->acct_ctrl & ACB_PWNOTREQ)
+      safe_strcpy((char *)p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
+    else
+      safe_strcpy((char *)p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
+  }
+
+  p += 32;
+
+  *p++ = ':';
+
+  /* Add the account encoding and the last change time. */
+  slprintf((char *)p, new_entry_length - 1 - (p - new_entry),  "%s:LCT-%08X:\n",
+           pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN), (uint32)time(NULL));
+
+  return new_entry;
+}
+
 /************************************************************************
  Routine to add an entry to the smbpasswd file.
 *************************************************************************/
@@ -440,15 +608,11 @@ static BOOL add_smbfilepwd_entry(struct smb_passwd *newpwd)
   char *pfile = lp_smb_passwd_file();
   struct smb_passwd *pwd = NULL;
   FILE *fp = NULL;
-
-  int i;
   int wr_len;
-
   int fd;
-  int new_entry_length;
+  size_t new_entry_length;
   char *new_entry;
   SMB_OFF_T offpos;
-  char *p;
 
   /* Open the smbpassword file - for update. */
   fp = startsmbfilepwent(True);
@@ -486,59 +650,21 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
     return False;
   }
 
-  new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2;
-
-  if((new_entry = (char *)malloc( new_entry_length )) == NULL) {
+  if((new_entry = format_new_smbpasswd_entry(newpwd)) == NULL) {
     DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
 Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
     endsmbfilepwent(fp);
     return False;
   }
 
-  slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->smb_name, (unsigned)newpwd->smb_userid);
-  p = &new_entry[strlen(new_entry)];
-
-  if(newpwd->smb_passwd != NULL) {
-    for( i = 0; i < 16; i++) {
-      slprintf((char *)&p[i*2], new_entry_length - (p - new_entry) - 1, "%02X", newpwd->smb_passwd[i]);
-    }
-  } else {
-    i=0;
-    if(newpwd->acct_ctrl & ACB_PWNOTREQ)
-      safe_strcpy((char *)p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
-    else
-      safe_strcpy((char *)p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
-  }
-  
-  p += 32;
-
-  *p++ = ':';
-
-  if(newpwd->smb_nt_passwd != NULL) {
-    for( i = 0; i < 16; i++) {
-      slprintf((char *)&p[i*2], new_entry_length - 1 - (p - new_entry), "%02X", newpwd->smb_nt_passwd[i]);
-    }
-  } else {
-    if(newpwd->acct_ctrl & ACB_PWNOTREQ)
-      safe_strcpy((char *)p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
-    else
-      safe_strcpy((char *)p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new_entry_length - 1 - (p - new_entry));
-  }
-
-  p += 32;
-
-  *p++ = ':';
-
-  /* Add the account encoding and the last change time. */
-  slprintf((char *)p, new_entry_length - 1 - (p - new_entry),  "%s:LCT-%08X:\n",
-           pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN), (uint32)time(NULL));
+  new_entry_length = strlen(new_entry);
 
 #ifdef DEBUG_PASSWORD
-  DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d entry_len %d made line |%s|", 
-                            fd, new_entry_length, strlen(new_entry), new_entry));
+  DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d made line |%s|", 
+                            fd, new_entry_length, new_entry));
 #endif
 
-  if ((wr_len = write(fd, new_entry, strlen(new_entry))) != strlen(new_entry)) {
+  if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length) {
     DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \
 Error was %s\n", wr_len, newpwd->smb_name, pfile, strerror(errno)));
 
@@ -960,6 +1086,105 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override)
   return True;
 }
 
+/************************************************************************
+ Routine to delete an entry in the smbpasswd file by name.
+*************************************************************************/
+
+static BOOL del_smbfilepwd_entry(const char *name)
+{
+  char *pfile = lp_smb_passwd_file();
+  pstring pfile2;
+  struct smb_passwd *pwd = NULL;
+  FILE *fp = NULL;
+  FILE *fp_write = NULL;
+  int pfile2_lockdepth = 0;
+
+  slprintf(pfile2, sizeof(pfile2)-1, "%s.%u", pfile, (unsigned)getpid() );
+
+  /*
+   * Open the smbpassword file - for update. It needs to be update
+   * as we need any other processes to wait until we have replaced
+   * it.
+   */
+
+  if((fp = startsmbfilepwent(True)) == NULL) {
+    DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
+    return False;
+  }
+
+  /*
+   * Create the replacement password file.
+   */
+  if((fp_write = startsmbfilepwent_internal(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) {
+    DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
+    endsmbfilepwent(fp);
+    return False;
+  }
+
+  /*
+   * Scan the file, a line at a time and check if the name matches.
+   */
+
+  while ((pwd = getsmbfilepwent(fp)) != NULL) {
+    char *new_entry;
+    size_t new_entry_length;
+
+    if (strequal(name, pwd->smb_name)) {
+      DEBUG(10, ("add_smbfilepwd_entry: found entry with name %s - deleting it.\n", name));
+      continue;
+    }
+
+    /*
+     * We need to copy the entry out into the second file.
+     */
+
+    if((new_entry = format_new_smbpasswd_entry(pwd)) == NULL) {
+      DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \
+Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
+      unlink(pfile2);
+      endsmbfilepwent(fp);
+      endsmbfilepwent_internal(fp_write,&pfile2_lockdepth);
+      return False;
+    }
+
+    new_entry_length = strlen(new_entry);
+
+    if(fwrite(new_entry, 1, new_entry_length, fp_write) != new_entry_length) {
+      DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \
+Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
+      unlink(pfile2);
+      endsmbfilepwent(fp);
+      endsmbfilepwent_internal(fp_write,&pfile2_lockdepth);
+      free(new_entry);
+      return False;
+    }
+
+    free(new_entry);
+  }
+
+  /*
+   * Ensure pfile2 is flushed before rename.
+   */
+
+  if(fflush(fp_write) != 0) {
+    DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno)));
+    endsmbfilepwent(fp);
+    endsmbfilepwent_internal(fp_write,&pfile2_lockdepth);
+    return False;
+  }
+
+  /*
+   * Do an atomic rename - then release the locks.
+   */
+
+  if(rename(pfile2,pfile) != 0) {
+    unlink(pfile2);
+  }
+  endsmbfilepwent(fp);
+  endsmbfilepwent_internal(fp_write,&pfile2_lockdepth);
+  return True;
+}
+       
 /*
  * Stub functions - implemented in terms of others.
  */
@@ -1000,6 +1225,7 @@ static struct passdb_ops file_ops = {
   getsmbfilepwent,
   add_smbfilepwd_entry,
   mod_smbfilepwd_entry,
+  del_smbfilepwd_entry,
   getsmbfile21pwent,
   iterate_getsam21pwnam,
   iterate_getsam21pwuid,
index 9d0aecf8b8a296ad71e54f8482e70bfbb2c7ac38..0348a2b97b12042cdcb624481fb658af15f51e73 100644 (file)
@@ -25,8 +25,8 @@
 /*************************************************************
 add a new user to the local smbpasswd file
 *************************************************************/
-static BOOL add_new_user(char *user_name, uid_t uid, BOOL trust_account, 
-                        BOOL disable_user, BOOL set_no_password,
+
+static BOOL add_new_user(char *user_name, uid_t uid, int local_flags,
                         uchar *new_p16, uchar *new_nt_p16)
 {
        struct smb_passwd new_smb_pwent;
@@ -36,16 +36,17 @@ static BOOL add_new_user(char *user_name, uid_t uid, BOOL trust_account,
        new_smb_pwent.smb_name = user_name; 
        new_smb_pwent.smb_passwd = NULL;
        new_smb_pwent.smb_nt_passwd = NULL;
-       new_smb_pwent.acct_ctrl = (trust_account ? ACB_WSTRUST : ACB_NORMAL);
+       new_smb_pwent.acct_ctrl = ((local_flags & LOCAL_TRUST_ACCOUNT) ? ACB_WSTRUST : ACB_NORMAL);
        
-       if(disable_user) {
+       if(local_flags & LOCAL_DISABLE_USER) {
                new_smb_pwent.acct_ctrl |= ACB_DISABLED;
-       } else if (set_no_password) {
+       } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
                new_smb_pwent.acct_ctrl |= ACB_PWNOTREQ;
        } else {
                new_smb_pwent.smb_passwd = new_p16;
                new_smb_pwent.smb_nt_passwd = new_nt_p16;
        }
+
        
        return add_smbpwd_entry(&new_smb_pwent);
 }
@@ -55,13 +56,12 @@ static BOOL add_new_user(char *user_name, uid_t uid, BOOL trust_account,
 change a password entry in the local smbpasswd file
 *************************************************************/
 
-BOOL local_password_change(char *user_name, BOOL trust_account, BOOL add_user,
-                          BOOL enable_user, BOOL disable_user, BOOL set_no_password,
+BOOL local_password_change(char *user_name, int local_flags,
                           char *new_passwd, 
                           char *err_str, size_t err_str_len,
                           char *msg_str, size_t msg_str_len)
 {
-       struct passwd  *pwd;
+       struct passwd  *pwd = NULL;
        void *vp;
        struct smb_passwd *smb_pwent;
        uchar           new_p16[16];
@@ -70,17 +70,18 @@ BOOL local_password_change(char *user_name, BOOL trust_account, BOOL add_user,
        *err_str = '\0';
        *msg_str = '\0';
 
-       pwd = sys_getpwnam(user_name);
+       if (local_flags & LOCAL_ADD_USER) {
        
-       /*
-        * Check for a local account.
-        */
+               /*
+                * Check for a local account - if we're adding only.
+                */
        
-       if(!pwd) {
-               slprintf(err_str, err_str_len - 1, "User %s does not \
+               if(!(pwd = sys_getpwnam(user_name))) {
+                       slprintf(err_str, err_str_len - 1, "User %s does not \
 exist in system password file (usually /etc/passwd). Cannot add \
 account without a valid local system user.\n", user_name);
-               return False;
+                       return False;
+               }
        }
 
        /* Calculate the MD4 hash (NT compatible) of the new password. */
@@ -111,15 +112,14 @@ account without a valid local system user.\n", user_name);
        /* Get the smb passwd entry for this user */
        smb_pwent = getsmbpwnam(user_name);
        if (smb_pwent == NULL) {
-               if(add_user == False) {
+               if(!(local_flags & LOCAL_ADD_USER)) {
                        slprintf(err_str, err_str_len-1,
-                               "Failed to find entry for user %s.\n", pwd->pw_name);
+                               "Failed to find entry for user %s.\n", user_name);
                        endsmbpwent(vp);
                        return False;
                }
 
-               if (add_new_user(user_name, pwd->pw_uid, trust_account, disable_user,
-                                set_no_password, new_p16, new_nt_p16)) {
+               if (add_new_user(user_name, pwd->pw_uid, local_flags, new_p16, new_nt_p16)) {
                        slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
                        endsmbpwent(vp);
                        return True;
@@ -130,7 +130,7 @@ account without a valid local system user.\n", user_name);
                }
        } else {
                /* the entry already existed */
-               add_user = False;
+               local_flags &= ~LOCAL_ADD_USER;
        }
 
        /*
@@ -138,15 +138,15 @@ account without a valid local system user.\n", user_name);
         * and the valid last change time.
         */
 
-       if(disable_user) {
+       if(local_flags & LOCAL_DISABLE_USER) {
                smb_pwent->acct_ctrl |= ACB_DISABLED;
-       } else if (enable_user) {
+       } else if (local_flags & LOCAL_ENABLE_USER) {
                if(smb_pwent->smb_passwd == NULL) {
                        smb_pwent->smb_passwd = new_p16;
                        smb_pwent->smb_nt_passwd = new_nt_p16;
                }
                smb_pwent->acct_ctrl &= ~ACB_DISABLED;
-       } else if (set_no_password) {
+       } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
                smb_pwent->acct_ctrl |= ACB_PWNOTREQ;
                /* This is needed to preserve ACB_PWNOTREQ in mod_smbfilepwd_entry */
                smb_pwent->smb_passwd = NULL;
@@ -168,11 +168,25 @@ account without a valid local system user.\n", user_name);
                smb_pwent->smb_nt_passwd = new_nt_p16;
        }
        
-       if(mod_smbpwd_entry(smb_pwent,True) == False) {
-               slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n",
-                       pwd->pw_name);
-               endsmbpwent(vp);
-               return False;
+       if(local_flags & LOCAL_DELETE_USER) {
+               if (del_smbpwd_entry(user_name)==False) {
+                       slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
+                       endsmbpwent(vp);
+                       return False;
+               }
+               slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
+       } else {
+               if(mod_smbpwd_entry(smb_pwent,True) == False) {
+                       slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
+                       endsmbpwent(vp);
+                       return False;
+               }
+               if(local_flags & LOCAL_DISABLE_USER)
+                       slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
+               else if (local_flags & LOCAL_ENABLE_USER)
+                       slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name);
+               else if (local_flags & LOCAL_SET_NO_PASSWORD)
+                       slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name);
        }
 
        endsmbpwent(vp);
index ec6ce15f07df1abc90ca162b7488db7400025c23..dcfafaa8b927db24d9b749b41a77fc5e0beb6f72 100644 (file)
@@ -63,6 +63,7 @@ static void usage(void)
                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");
                printf("  -e                   enable user\n");
                printf("  -n                   set no password\n");
@@ -218,20 +219,19 @@ static char *prompt_for_new_password(BOOL stdin_get)
 
 
 /*************************************************************
-change a password either locally or remotely
+ 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)
+                           char *old_passwd, char *new_passwd, int local_flags)
 {
        BOOL ret;
        pstring err_str;
        pstring msg_str;
 
        if (remote_machine != NULL) {
-               if (add_user || enable_user || disable_user || set_no_password || trust_account) {
+               if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|
+                                                       LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) {
                        /* these things can't be done remotely yet */
                        return False;
                }
@@ -242,8 +242,7 @@ static BOOL password_change(const char *remote_machine, char *user_name,
                return ret;
        }
        
-       ret = local_password_change(user_name, trust_account, add_user, enable_user, 
-                                    disable_user, set_no_password, new_passwd, 
+       ret = local_password_change(user_name, local_flags, new_passwd, 
                                     err_str, sizeof(err_str), msg_str, sizeof(msg_str));
 
        if(*msg_str)
@@ -256,18 +255,15 @@ static BOOL password_change(const char *remote_machine, char *user_name,
 
 
 /*************************************************************
-handle password changing for root
+ 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;
+       int local_flags = 0;
        BOOL stdin_passwd_get = False;
        char *user_name = NULL;
        char *new_domain = NULL;
@@ -275,24 +271,37 @@ static int process_root(int argc, char *argv[])
        char *old_passwd = NULL;
        char *remote_machine = NULL;
 
-       while ((ch = getopt(argc, argv, "adehmnj:r:sR:D:U:")) != EOF) {
+       while ((ch = getopt(argc, argv, "a:x:d:e:mnj:r:sR:D:U:")) != EOF) {
                switch(ch) {
                case 'a':
-                       add_user = True;
+                       local_flags |= LOCAL_ADD_USER;
+                       user_name = optarg;
+                       break;
+               case 'x':
+                       local_flags |= LOCAL_DELETE_USER;
+                       user_name = optarg;
+                       new_passwd = "XXXXXX";
                        break;
                case 'd':
-                       disable_user = True;
+                       local_flags |= LOCAL_DISABLE_USER;
+                       user_name = optarg;
                        new_passwd = "XXXXXX";
                        break;
                case 'e':
-                       enable_user = True;
+                       local_flags |= LOCAL_ENABLE_USER;
+                       user_name = optarg;
                        break;
-               case 'D':
-                       DEBUGLEVEL = atoi(optarg);
+               case 'm':
+                       local_flags |= LOCAL_TRUST_ACCOUNT;
                        break;
                case 'n':
-                       set_no_password = True;
+                       local_flags |= LOCAL_SET_NO_PASSWORD;
                        new_passwd = "NO PASSWORD";
+               case 'j':
+                       new_domain = optarg;
+                       strupper(new_domain);
+                       joining_domain = True;
+                       break;
                case 'r':
                        remote_machine = optarg;
                        break;
@@ -305,13 +314,8 @@ static int process_root(int argc, char *argv[])
                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;
+               case 'D':
+                       DEBUGLEVEL = atoi(optarg);
                        break;
                case 'U':
                        user_name = optarg;
@@ -326,15 +330,16 @@ static int process_root(int argc, char *argv[])
 
 
        /*
-        * Ensure add_user and either remote machine or join domain are
+        * Ensure add/delete user and either remote machine or join domain are
         * not both set.
         */     
-       if(add_user && ((remote_machine != NULL) || joining_domain)) {
+       if((local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER)) && ((remote_machine != NULL) || joining_domain)) {
                usage();
        }
        
        if(joining_domain) {
-               if (argc != 0) usage();
+               if (argc != 0)
+                       usage();
                return join_domain(new_domain, remote_machine);
        }
 
@@ -365,7 +370,7 @@ static int process_root(int argc, char *argv[])
                exit(1);
        }
 
-       if (trust_account) {
+       if (local_flags & LOCAL_TRUST_ACCOUNT) {
                /* add the $ automatically */
                static fstring buf;
 
@@ -378,7 +383,7 @@ static int process_root(int argc, char *argv[])
                        user_name[strlen(user_name)-1] = 0;
                }
 
-               if (add_user) {
+               if (local_flags & LOCAL_ADD_USER) {
                        new_passwd = xstrdup(user_name);
                        strlower(new_passwd);
                }
@@ -392,12 +397,6 @@ static int process_root(int argc, char *argv[])
                user_name = buf;
        }
 
-       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 (remote_machine != NULL) {
                old_passwd = get_pass("Old SMB password:",stdin_passwd_get);
        }
@@ -413,7 +412,7 @@ static int process_root(int argc, char *argv[])
                 * smbpasswd file) then we need to prompt for a new password.
                 */
 
-               if(enable_user) {
+               if(local_flags & LOCAL_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. */
@@ -429,20 +428,12 @@ static int process_root(int argc, char *argv[])
                }
        }
        
-       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);
+       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);
                return 1;
        } 
 
-       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 {
+       if(!(local_flags & (LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|LOCAL_DELETE_USER|LOCAL_SET_NO_PASSWORD))) {
                struct smb_passwd *smb_pass = getsmbpwnam(user_name);
                printf("Password changed for user %s.", user_name );
                if((smb_pass != NULL) && (smb_pass->acct_ctrl & ACB_DISABLED ))
@@ -534,8 +525,7 @@ static int process_nonroot(int argc, char *argv[])
                exit(1);
        }
 
-       if (!password_change(remote_machine, user_name, old_passwd, new_passwd,
-                            False, False, False, False, False)) {
+       if (!password_change(remote_machine, user_name, old_passwd, new_passwd, 0)) {
                fprintf(stderr,"Failed to change password for %s\n", user_name);
                return 1;
        }
index 48c3ae07e25bc8c657b7cdd8e64fbea51e1e3c58..3c9858a3d388d0f911dc707cbfba980fb788f076 100644 (file)
@@ -44,6 +44,7 @@ static int iNumNonAutoPrintServices = 0;
 #define CHG_S_PASSWD_FLAG "chg_s_passwd_flag"
 #define CHG_R_PASSWD_FLAG "chg_r_passwd_flag"
 #define ADD_USER_FLAG "add_user_flag"
+#define DELETE_USER_FLAG "delete_user_flag"
 #define DISABLE_USER_FLAG "disable_user_flag"
 #define ENABLE_USER_FLAG "enable_user_flag"
 #define RHOST "remote_host"
@@ -617,7 +618,7 @@ change a password either locally or remotely
 *************************************************************/
 static BOOL change_password(const char *remote_machine, char *user_name, 
                            char *old_passwd, char *new_passwd, 
-                           BOOL add_user, BOOL enable_user, BOOL disable_user)
+                               int local_flags)
 {
        BOOL ret = False;
        pstring err_str;
@@ -641,8 +642,7 @@ static BOOL change_password(const char *remote_machine, char *user_name,
                return False;
        }
        
-       ret = local_password_change(user_name, False, add_user, enable_user, 
-                                    disable_user, False, new_passwd, err_str, sizeof(err_str),
+       ret = local_password_change(user_name, local_flags, new_passwd, err_str, sizeof(err_str),
                                         msg_str, sizeof(msg_str));
 
        if(*msg_str)
@@ -660,6 +660,7 @@ static void chg_passwd(void)
 {
        char *host;
        BOOL rslt;
+       int local_flags = 0;
 
        /* Make sure users name has been specified */
        if (strlen(cgi_variable(SWAT_USER)) == 0) {
@@ -668,10 +669,10 @@ static void chg_passwd(void)
        }
 
        /*
-        * smbpasswd doesn't require anything but the users name to disable or enable the user,
+        * smbpasswd doesn't require anything but the users name to delete, disable or enable the user,
         * so if that's what we're doing, skip the rest of the checks
         */
-       if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG)) {
+       if (!cgi_variable(DISABLE_USER_FLAG) && !cgi_variable(ENABLE_USER_FLAG) && !cgi_variable(DELETE_USER_FLAG)) {
 
                /*
                 * If current user is not root, make sure old password has been specified 
@@ -710,18 +711,27 @@ static void chg_passwd(void)
        } else {
                host = "127.0.0.1";
        }
+
+       /*
+        * Set up the local flags.
+        */
+
+       local_flags |= (cgi_variable(ADD_USER_FLAG) ? LOCAL_ADD_USER : 0);
+       local_flags |= (cgi_variable(DELETE_USER_FLAG) ? LOCAL_DELETE_USER : 0);
+       local_flags |= (cgi_variable(ENABLE_USER_FLAG) ? LOCAL_ENABLE_USER : 0);
+       local_flags |= (cgi_variable(DISABLE_USER_FLAG) ? LOCAL_DISABLE_USER : 0);
+
        rslt = change_password(host,
                               cgi_variable(SWAT_USER),
                               cgi_variable(OLD_PSWD), cgi_variable(NEW_PSWD),
-                              cgi_variable(ADD_USER_FLAG)? True : False,
-                              cgi_variable(ENABLE_USER_FLAG)? True : False,
-                              cgi_variable(DISABLE_USER_FLAG)? True : False);
+                                  local_flags);
 
-
-       if (rslt == True) {
-               printf("<p> The passwd for '%s' has been changed. \n", cgi_variable(SWAT_USER));
-       } else {
-               printf("<p> The passwd for '%s' has NOT been changed. \n",cgi_variable(SWAT_USER));
+       if(local_flags == 0) {
+               if (rslt == True) {
+                       printf("<p> The passwd for '%s' has been changed. \n", cgi_variable(SWAT_USER));
+               } else {
+                       printf("<p> The passwd for '%s' has NOT been changed. \n",cgi_variable(SWAT_USER));
+               }
        }
        
        return;
@@ -773,6 +783,8 @@ static void passwd_page(void)
        if (demo_mode || am_root()) {
                printf("<input type=submit name=%s value=\"Add New User\">\n",
                       ADD_USER_FLAG);
+               printf("<input type=submit name=%s value=\"Delete User\">\n",
+                      DELETE_USER_FLAG);
                printf("<input type=submit name=%s value=\"Disable User\">\n", 
                       DISABLE_USER_FLAG);
                printf("<input type=submit name=%s value=\"Enable User\">\n", 
@@ -784,7 +796,7 @@ static void passwd_page(void)
         * Do some work if change, add, disable or enable was
         * requested. It could be this is the first time through this
         * code, so there isn't anything to do.  */
-       if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) ||
+       if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
            (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
                chg_passwd();           
        }