123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- --- a/source3/Makefile.in
- +++ b/source3/Makefile.in
- @@ -1025,7 +1025,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) \
- @@ -1813,7 +1813,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;\
- @@ -1822,7 +1822,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,249 @@
- +/*
- + * Copyright (C) 2012 Felix Fietkau <nbd@nbd.name>
- + * 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", user);
- + 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);
- + fseek(fp, -len, SEEK_CUR);
- + fgetpos(fp, &w_pos);
- + fsetpos(fp, &r_pos);
- +
- + while (fgets(buf, sizeof(buf) - 1, fp)) {
- + int cur_len = strlen(buf);
- +
- + fsetpos(fp, &w_pos);
- + fputs(buf, fp);
- + fgetpos(fp, &w_pos);
- +
- + fsetpos(fp, &r_pos);
- + fseek(fp, cur_len, SEEK_CUR);
- + fgetpos(fp, &r_pos);
- + }
- +
- + fsetpos(fp, &w_pos);
- + ftruncate(fileno(fp), ftello(fp));
- +}
- +
- +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;
- +}
|