111-owrt_smbpasswd.patch 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. --- a/source3/Makefile.in
  2. +++ b/source3/Makefile.in
  3. @@ -1025,7 +1025,7 @@ TEST_LP_LOAD_OBJ = param/test_lp_load.o
  4. PASSWD_UTIL_OBJ = utils/passwd_util.o
  5. -SMBPASSWD_OBJ = utils/smbpasswd.o $(PASSWD_UTIL_OBJ) $(PASSCHANGE_OBJ) \
  6. +SMBPASSWD_OBJ = utils/owrt_smbpasswd.o $(PASSWD_UTIL_OBJ) $(PASSCHANGE_OBJ) \
  7. $(PARAM_OBJ) $(LIBSMB_OBJ) $(PASSDB_OBJ) \
  8. $(GROUPDB_OBJ) $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
  9. $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) \
  10. @@ -1813,7 +1813,7 @@ nmbd/nmbd_multicall.o: nmbd/nmbd.c nmbd/
  11. echo "$(COMPILE_CC_PATH)" 1>&2;\
  12. $(COMPILE_CC_PATH) >/dev/null 2>&1
  13. -utils/smbpasswd_multicall.o: utils/smbpasswd.c utils/smbpasswd.o
  14. +utils/smbpasswd_multicall.o: utils/owrt_smbpasswd.c utils/owrt_smbpasswd.o
  15. @echo Compiling $<.c
  16. @$(COMPILE_CC_PATH) -Dmain=smbpasswd_main && exit 0;\
  17. echo "The following command failed:" 1>&2;\
  18. @@ -1822,7 +1822,7 @@ utils/smbpasswd_multicall.o: utils/smbpa
  19. SMBD_MULTI_O = $(patsubst smbd/server.o,smbd/server_multicall.o,$(SMBD_OBJ))
  20. NMBD_MULTI_O = $(patsubst nmbd/nmbd.o,nmbd/nmbd_multicall.o,$(filter-out $(LIB_DUMMY_OBJ),$(NMBD_OBJ)))
  21. -SMBPASSWD_MULTI_O = $(patsubst utils/smbpasswd.o,utils/smbpasswd_multicall.o,$(filter-out $(LIB_DUMMY_OBJ),$(SMBPASSWD_OBJ)))
  22. +SMBPASSWD_MULTI_O = $(patsubst utils/owrt_smbpasswd.o,utils/smbpasswd_multicall.o,$(filter-out $(LIB_DUMMY_OBJ),$(SMBPASSWD_OBJ)))
  23. MULTI_O = multi.o
  24. MULTICALL_O = $(sort $(SMBD_MULTI_O) $(NMBD_MULTI_O) $(SMBPASSWD_MULTI_O) $(MULTI_O))
  25. --- /dev/null
  26. +++ b/source3/utils/owrt_smbpasswd.c
  27. @@ -0,0 +1,249 @@
  28. +/*
  29. + * Copyright (C) 2012 Felix Fietkau <nbd@nbd.name>
  30. + * Copyright (C) 2008 John Crispin <blogic@openwrt.org>
  31. + *
  32. + * This program is free software; you can redistribute it and/or modify it
  33. + * under the terms of the GNU General Public License as published by the
  34. + * Free Software Foundation; either version 2 of the License, or (at your
  35. + * option) any later version.
  36. + *
  37. + * This program is distributed in the hope that it will be useful, but WITHOUT
  38. + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  39. + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  40. + * more details.
  41. + *
  42. + * You should have received a copy of the GNU General Public License along with
  43. + * this program; if not, write to the Free Software Foundation, Inc., 675
  44. + * Mass Ave, Cambridge, MA 02139, USA. */
  45. +
  46. +#include "includes.h"
  47. +#include <endian.h>
  48. +#include <stdio.h>
  49. +
  50. +static char buf[256];
  51. +
  52. +static void md4hash(const char *passwd, uchar p16[16])
  53. +{
  54. + int len;
  55. + smb_ucs2_t wpwd[129];
  56. + int i;
  57. +
  58. + len = strlen(passwd);
  59. + for (i = 0; i < len; i++) {
  60. +#if __BYTE_ORDER == __LITTLE_ENDIAN
  61. + wpwd[i] = (unsigned char)passwd[i];
  62. +#else
  63. + wpwd[i] = (unsigned char)passwd[i] << 8;
  64. +#endif
  65. + }
  66. + wpwd[i] = 0;
  67. +
  68. + len = len * sizeof(int16);
  69. + mdfour(p16, (unsigned char *)wpwd, len);
  70. + ZERO_STRUCT(wpwd);
  71. +}
  72. +
  73. +
  74. +static bool find_passwd_line(FILE *fp, const char *user, char **next)
  75. +{
  76. + char *p1;
  77. +
  78. + while (!feof(fp)) {
  79. + if(!fgets(buf, sizeof(buf) - 1, fp))
  80. + continue;
  81. +
  82. + p1 = strchr(buf, ':');
  83. +
  84. + if (p1 - buf != strlen(user))
  85. + continue;
  86. +
  87. + if (strncmp(buf, user, p1 - buf) != 0)
  88. + continue;
  89. +
  90. + if (next)
  91. + *next = p1;
  92. + return true;
  93. + }
  94. + return false;
  95. +}
  96. +
  97. +/* returns -1 if user is not present in /etc/passwd*/
  98. +static int find_uid_for_user(const char *user)
  99. +{
  100. + FILE *fp;
  101. + char *p1, *p2, *p3;
  102. + int ret = -1;
  103. +
  104. + fp = fopen("/etc/passwd", "r");
  105. + if (!fp) {
  106. + printf("failed to open /etc/passwd");
  107. + goto out;
  108. + }
  109. +
  110. + if (!find_passwd_line(fp, user, &p1)) {
  111. + printf("User %s not found or invalid in /etc/passwd\n", user);
  112. + goto out;
  113. + }
  114. +
  115. + p2 = strchr(p1 + 1, ':');
  116. + if (!p2)
  117. + goto out;
  118. +
  119. + p2++;
  120. + p3 = strchr(p2, ':');
  121. + if (!p1)
  122. + goto out;
  123. +
  124. + *p3 = '\0';
  125. + ret = atoi(p2);
  126. +
  127. +out:
  128. + if(fp)
  129. + fclose(fp);
  130. + return ret;
  131. +}
  132. +
  133. +static void smbpasswd_write_user(FILE *fp, const char *user, int uid, const char *password)
  134. +{
  135. + static uchar nt_p16[NT_HASH_LEN];
  136. + int len = 0;
  137. + int i;
  138. +
  139. + md4hash(strdup(password), nt_p16);
  140. +
  141. + len += snprintf(buf + len, sizeof(buf) - len, "%s:%u:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:", user, uid);
  142. + for(i = 0; i < NT_HASH_LEN; i++)
  143. + len += snprintf(buf + len, sizeof(buf) - len, "%02X", nt_p16[i]);
  144. +
  145. + snprintf(buf + len, sizeof(buf) - len, ":[U ]:LCT-00000001:\n");
  146. + fputs(buf, fp);
  147. +}
  148. +
  149. +static void smbpasswd_delete_user(FILE *fp)
  150. +{
  151. + fpos_t r_pos, w_pos;
  152. + int len = strlen(buf);
  153. +
  154. + fgetpos(fp, &r_pos);
  155. + fseek(fp, -len, SEEK_CUR);
  156. + fgetpos(fp, &w_pos);
  157. + fsetpos(fp, &r_pos);
  158. +
  159. + while (fgets(buf, sizeof(buf) - 1, fp)) {
  160. + int cur_len = strlen(buf);
  161. +
  162. + fsetpos(fp, &w_pos);
  163. + fputs(buf, fp);
  164. + fgetpos(fp, &w_pos);
  165. +
  166. + fsetpos(fp, &r_pos);
  167. + fseek(fp, cur_len, SEEK_CUR);
  168. + fgetpos(fp, &r_pos);
  169. + }
  170. +
  171. + fsetpos(fp, &w_pos);
  172. + ftruncate(fileno(fp), ftello(fp));
  173. +}
  174. +
  175. +static int usage(const char *progname)
  176. +{
  177. + fprintf(stderr,
  178. + "Usage: %s [options] <username>\n"
  179. + "\n"
  180. + "Options:\n"
  181. + " -s read password from stdin\n"
  182. + " -a add user\n"
  183. + " -x delete user\n",
  184. + progname);
  185. + return 1;
  186. +}
  187. +
  188. +int main(int argc, char **argv)
  189. +{
  190. + const char *prog = argv[0];
  191. + const char *user;
  192. + char *pw1, *pw2;
  193. + FILE *fp;
  194. + bool add = false, delete = false, get_stdin = false, found;
  195. + int ch;
  196. + int uid;
  197. +
  198. + TALLOC_CTX *frame = talloc_stackframe();
  199. +
  200. + while ((ch = getopt(argc, argv, "asx")) != EOF) {
  201. + switch (ch) {
  202. + case 's':
  203. + get_stdin = true;
  204. + break;
  205. + case 'a':
  206. + add = true;
  207. + break;
  208. + case 'x':
  209. + delete = true;
  210. + break;
  211. + default:
  212. + return usage(prog);
  213. + }
  214. + }
  215. +
  216. + if (add && delete)
  217. + return usage(prog);
  218. +
  219. + argc -= optind;
  220. + argv += optind;
  221. +
  222. + if (!argc)
  223. + return usage(prog);
  224. +
  225. + user = argv[0];
  226. + if (!delete) {
  227. + uid = find_uid_for_user(user);
  228. + if (uid < 0) {
  229. + fprintf(stderr, "Could not find user '%s' in /etc/passwd\n", user);
  230. + return 2;
  231. + }
  232. + }
  233. +
  234. + fp = fopen("/etc/samba/smbpasswd", "r+");
  235. + if(!fp) {
  236. + fprintf(stderr, "Failed to open /etc/samba/smbpasswd");
  237. + return 3;
  238. + }
  239. +
  240. + found = find_passwd_line(fp, user, NULL);
  241. + if (!add && !found) {
  242. + fprintf(stderr, "Could not find user '%s' in /etc/samba/smbpasswd\n", user);
  243. + return 3;
  244. + }
  245. +
  246. + if (delete) {
  247. + smbpasswd_delete_user(fp);
  248. + goto out;
  249. + }
  250. +
  251. + pw1 = get_pass("New SMB password:", get_stdin);
  252. + if (!pw1)
  253. + pw1 = strdup("");
  254. +
  255. + pw2 = get_pass("Retype SMB password:", get_stdin);
  256. + if (!pw2)
  257. + pw2 = strdup("");
  258. +
  259. + if (strcmp(pw1, pw2) != 0) {
  260. + fprintf(stderr, "Mismatch - password unchanged.\n");
  261. + goto out_free;
  262. + }
  263. +
  264. + if (found)
  265. + fseek(fp, -strlen(buf), SEEK_CUR);
  266. + smbpasswd_write_user(fp, user, uid, pw2);
  267. +
  268. +out_free:
  269. + free(pw1);
  270. + free(pw2);
  271. +out:
  272. + fclose(fp);
  273. + TALLOC_FREE(frame);
  274. +
  275. + return 0;
  276. +}