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