samba36: integrate a cleanup/rewrite of the smbpasswd utility from samba 3.0
authorFelix Fietkau <nbd@openwrt.org>
Tue, 14 Feb 2012 03:34:15 +0000 (03:34 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 14 Feb 2012 03:34:15 +0000 (03:34 +0000)
SVN-Revision: 30517

net/samba36/patches/111-owrt_smbpasswd.patch [new file with mode: 0644]

diff --git a/net/samba36/patches/111-owrt_smbpasswd.patch b/net/samba36/patches/111-owrt_smbpasswd.patch
new file mode 100644 (file)
index 0000000..d8089a3
--- /dev/null
@@ -0,0 +1,277 @@
+--- a/source3/Makefile.in
++++ b/source3/Makefile.in
+@@ -1016,7 +1016,7 @@ TEST_LP_LOAD_OBJ = param/test_lp_load.o 
+ PASSWD_UTIL_OBJ = utils/passwd_util.o
+-SMBPASSWD_OBJ = utils/smbpasswd.o $(PASSWD_UTIL_OBJ) $(PASSCHANGE_OBJ) \
++SMBPASSWD_OBJ = utils/owrt_smbpasswd.o $(PASSWD_UTIL_OBJ) $(PASSCHANGE_OBJ) \
+               $(PARAM_OBJ) $(LIBSMB_OBJ) $(PASSDB_OBJ) \
+               $(GROUPDB_OBJ) $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
+               $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) \
+@@ -1788,7 +1788,7 @@ nmbd/nmbd_multicall.o: nmbd/nmbd.c nmbd/
+               echo "$(COMPILE_CC_PATH)" 1>&2;\
+               $(COMPILE_CC_PATH) >/dev/null 2>&1
+-utils/smbpasswd_multicall.o: utils/smbpasswd.c utils/smbpasswd.o
++utils/smbpasswd_multicall.o: utils/owrt_smbpasswd.c utils/owrt_smbpasswd.o
+       @echo Compiling $<.c
+       @$(COMPILE_CC_PATH) -Dmain=smbpasswd_main && exit 0;\
+               echo "The following command failed:" 1>&2;\
+@@ -1797,7 +1797,7 @@ utils/smbpasswd_multicall.o: utils/smbpa
+ SMBD_MULTI_O = $(patsubst smbd/server.o,smbd/server_multicall.o,$(SMBD_OBJ))
+ NMBD_MULTI_O = $(patsubst nmbd/nmbd.o,nmbd/nmbd_multicall.o,$(filter-out $(LIB_DUMMY_OBJ),$(NMBD_OBJ)))
+-SMBPASSWD_MULTI_O = $(patsubst utils/smbpasswd.o,utils/smbpasswd_multicall.o,$(filter-out $(LIB_DUMMY_OBJ),$(SMBPASSWD_OBJ)))
++SMBPASSWD_MULTI_O = $(patsubst utils/owrt_smbpasswd.o,utils/smbpasswd_multicall.o,$(filter-out $(LIB_DUMMY_OBJ),$(SMBPASSWD_OBJ)))
+ MULTI_O = multi.o
+ MULTICALL_O = $(sort $(SMBD_MULTI_O) $(NMBD_MULTI_O) $(SMBPASSWD_MULTI_O) $(MULTI_O))
+--- /dev/null
++++ b/source3/utils/owrt_smbpasswd.c
+@@ -0,0 +1,245 @@
++/*
++ * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
++ * Copyright (C) 2008 John Crispin <blogic@openwrt.org>
++ *
++ * 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 Software Foundation; either version 2 of the License, or (at your
++ * option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 675
++ * Mass Ave, Cambridge, MA 02139, USA.  */
++
++#include "includes.h"
++#include <endian.h>
++#include <stdio.h>
++
++static char buf[256];
++
++static void md4hash(const char *passwd, uchar p16[16])
++{
++      int len;
++      smb_ucs2_t wpwd[129];
++      int i;
++
++      len = strlen(passwd);
++      for (i = 0; i < len; i++) {
++#if __BYTE_ORDER == __LITTLE_ENDIAN
++              wpwd[i] = (unsigned char)passwd[i];
++#else
++              wpwd[i] = (unsigned char)passwd[i] << 8;
++#endif
++      }
++      wpwd[i] = 0;
++
++      len = len * sizeof(int16);
++      mdfour(p16, (unsigned char *)wpwd, len);
++      ZERO_STRUCT(wpwd);
++}
++
++
++static bool find_passwd_line(FILE *fp, const char *user, char **next)
++{
++      char *p1;
++
++      while (!feof(fp)) {
++              if(!fgets(buf, sizeof(buf) - 1, fp))
++                      continue;
++
++              p1 = strchr(buf, ':');
++
++              if (p1 - buf != strlen(user))
++                      continue;
++
++              if (strncmp(buf, user, p1 - buf) != 0)
++                      continue;
++
++              if (next)
++                      *next = p1;
++              return true;
++      }
++      return false;
++}
++
++/* returns -1 if user is not present in /etc/passwd*/
++static int find_uid_for_user(const char *user)
++{
++      FILE *fp;
++      char *p1, *p2, *p3;
++      int ret = -1;
++
++      fp = fopen("/etc/passwd", "r");
++      if (!fp) {
++              printf("failed to open /etc/passwd");
++              goto out;
++      }
++
++      if (!find_passwd_line(fp, user, &p1)) {
++              printf("User %s not found or invalid in /etc/passwd\n");
++              goto out;
++      }
++
++      p2 = strchr(p1 + 1, ':');
++      if (!p2)
++              goto out;
++
++      p2++;
++      p3 = strchr(p2, ':');
++      if (!p1)
++              goto out;
++
++      *p3 = '\0';
++      ret = atoi(p2);
++
++out:
++      if(fp)
++              fclose(fp);
++      return ret;
++}
++
++static void smbpasswd_write_user(FILE *fp, const char *user, int uid, const char *password)
++{
++      static uchar nt_p16[NT_HASH_LEN];
++      int len = 0;
++      int i;
++
++      md4hash(strdup(password), nt_p16);
++
++      len += snprintf(buf + len, sizeof(buf) - len, "%s:%u:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:", user, uid);
++      for(i = 0; i < NT_HASH_LEN; i++)
++              len += snprintf(buf + len, sizeof(buf) - len, "%02X", nt_p16[i]);
++
++      snprintf(buf + len, sizeof(buf) - len, ":[U          ]:LCT-00000001:\n");
++      fputs(buf, fp);
++}
++
++static void smbpasswd_delete_user(FILE *fp)
++{
++      fpos_t r_pos, w_pos;
++      int len = strlen(buf);
++
++      fgetpos(fp, &r_pos);
++      w_pos = r_pos;
++      w_pos.__pos -= len;
++
++      while (fgets(buf, sizeof(buf) - 1, fp)) {
++              int cur_len = strlen(buf);
++
++              fsetpos(fp, &w_pos);
++              fputs(buf, fp);
++              r_pos.__pos += cur_len;
++              w_pos.__pos += cur_len;
++              fsetpos(fp, &r_pos);
++      }
++
++      ftruncate(fileno(fp), w_pos.__pos);
++}
++
++static int usage(const char *progname)
++{
++      fprintf(stderr,
++              "Usage: %s [options] <username>\n"
++              "\n"
++              "Options:\n"
++              "  -s           read password from stdin\n"
++              "  -a           add user\n"
++              "  -x           delete user\n",
++              progname);
++      return 1;
++}
++
++int main(int argc, char **argv)
++{
++      const char *prog = argv[0];
++      const char *user;
++      char *pw1, *pw2;
++      FILE *fp;
++      bool add = false, delete = false, get_stdin = false, found;
++      int ch;
++      int uid;
++
++      TALLOC_CTX *frame = talloc_stackframe();
++
++      while ((ch = getopt(argc, argv, "asx")) != EOF) {
++              switch (ch) {
++              case 's':
++                      get_stdin = true;
++                      break;
++              case 'a':
++                      add = true;
++                      break;
++              case 'x':
++                      delete = true;
++                      break;
++              default:
++                      return usage(prog);
++              }
++      }
++
++      if (add && delete)
++              return usage(prog);
++
++      argc -= optind;
++      argv += optind;
++
++      if (!argc)
++              return usage(prog);
++
++      user = argv[0];
++      if (!delete) {
++              uid = find_uid_for_user(user);
++              if (uid < 0) {
++                      fprintf(stderr, "Could not find user '%s' in /etc/passwd\n", user);
++                      return 2;
++              }
++      }
++
++      fp = fopen("/etc/samba/smbpasswd", "r+");
++      if(!fp) {
++              fprintf(stderr, "Failed to open /etc/samba/smbpasswd");
++              return 3;
++      }
++
++      found = find_passwd_line(fp, user, NULL);
++      if (!add && !found) {
++              fprintf(stderr, "Could not find user '%s' in /etc/samba/smbpasswd\n", user);
++              return 3;
++      }
++
++      if (delete) {
++              smbpasswd_delete_user(fp);
++              goto out;
++      }
++
++      pw1 = get_pass("New SMB password:", get_stdin);
++      if (!pw1)
++              pw1 = strdup("");
++
++      pw2 = get_pass("Retype SMB password:", get_stdin);
++      if (!pw2)
++              pw2 = strdup("");
++
++      if (strcmp(pw1, pw2) != 0) {
++              fprintf(stderr, "Mismatch - password unchanged.\n");
++              goto out_free;
++      }
++
++      if (found)
++              fseek(fp, -strlen(buf), SEEK_CUR);
++      smbpasswd_write_user(fp, user, uid, pw2);
++
++out_free:
++      free(pw1);
++      free(pw2);
++out:
++      fclose(fp);
++      TALLOC_FREE(frame);
++
++      return 0;
++}