1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2020 Tintri by DDN, Inc. All rights reserved.
14 */
15
16 /*
17 * Test NetrSamLogon and NetrSamLogonEx, uses for NTLM pass-thru auth.
18 */
19
20 #include <smbsrv/libmlsvc.h>
21 #include <smbsrv/netrauth.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include <util_common.h>
26
27 extern void netr_initialize(void);
28 extern uint32_t netlogon_logon(smb_logon_t *, smb_token_t *, smb_domainex_t *);
29
30 boolean_t
compare_tokens(const smb_token_t * src,const smb_token_t * dst)31 compare_tokens(const smb_token_t *src, const smb_token_t *dst)
32 {
33 int i;
34 const smb_ids_t *src_wgrps, *dst_wgrps;
35 smb_id_t *src_grp, *dst_grp;
36 char src_sid[SMB_SID_STRSZ] = "NULL", dst_sid[SMB_SID_STRSZ] = "NULL";
37
38 if (strcmp(src->tkn_domain_name, dst->tkn_domain_name) != 0) {
39 fprintf(stderr, "src domain %s does not match dst %s\n",
40 src->tkn_domain_name, dst->tkn_domain_name);
41 return (B_FALSE);
42 }
43
44 if (strcmp(src->tkn_account_name, dst->tkn_account_name) != 0) {
45 fprintf(stderr, "src account %s does not match dst %s\n",
46 src->tkn_account_name, dst->tkn_account_name);
47 return (B_FALSE);
48 }
49
50 if (src->tkn_user.i_attrs != dst->tkn_user.i_attrs) {
51 fprintf(stderr, "src attrs 0x%x does not match dst 0x%x\n",
52 src->tkn_user.i_attrs, dst->tkn_user.i_attrs);
53 return (B_FALSE);
54 }
55
56 if (!smb_sid_cmp(src->tkn_user.i_sid, dst->tkn_user.i_sid)) {
57 smb_sid_tostr(src->tkn_user.i_sid, src_sid);
58 smb_sid_tostr(dst->tkn_user.i_sid, dst_sid);
59 fprintf(stderr, "src usersid %s does not match dst %s\n",
60 src_sid, dst_sid);
61 return (B_FALSE);
62 }
63
64 /* tkn_owner can be NULL if we haven't called smb_token_setup_common */
65 if (src->tkn_owner.i_sid != dst->tkn_owner.i_sid &&
66 !smb_sid_cmp(src->tkn_owner.i_sid, dst->tkn_owner.i_sid)) {
67 smb_sid_tostr(src->tkn_owner.i_sid, src_sid);
68 smb_sid_tostr(dst->tkn_owner.i_sid, dst_sid);
69 fprintf(stderr, "src ownersid %s does not match dst %s\n",
70 src_sid, dst_sid);
71 return (B_FALSE);
72 }
73
74 if (!smb_sid_cmp(src->tkn_primary_grp.i_sid,
75 dst->tkn_primary_grp.i_sid)) {
76 smb_sid_tostr(src->tkn_primary_grp.i_sid, src_sid);
77 smb_sid_tostr(dst->tkn_primary_grp.i_sid, dst_sid);
78 fprintf(stderr, "src primarysid %s does not match dst %s\n",
79 src_sid, dst_sid);
80 return (B_FALSE);
81 }
82
83 src_wgrps = &src->tkn_win_grps;
84 dst_wgrps = &dst->tkn_win_grps;
85
86 if ((src_wgrps->i_ids == NULL && dst_wgrps->i_ids != NULL) ||
87 (src_wgrps->i_ids != NULL && dst_wgrps->i_ids == NULL)) {
88 fprintf(stderr,
89 "src wingrp nullness 0x%p does not match dst 0x%p\n",
90 src_wgrps->i_ids, dst_wgrps->i_ids);
91 return (B_FALSE);
92 }
93
94 if (src_wgrps->i_ids != NULL) {
95 src_grp = &src_wgrps->i_ids[0];
96 dst_grp = &dst_wgrps->i_ids[0];
97 if (src_wgrps->i_cnt != dst_wgrps->i_cnt) {
98 fprintf(stderr,
99 "src wingrp count %d does not match dst %d\n",
100 src_wgrps->i_cnt, dst_wgrps->i_cnt);
101 return (B_FALSE);
102 }
103
104 for (i = 0; i < src_wgrps->i_cnt; i++, src_grp++, dst_grp++) {
105 if ((src_grp->i_sid == NULL &&
106 dst_grp->i_sid != NULL) ||
107 (src_grp->i_sid != NULL &&
108 dst_grp->i_sid == NULL)) {
109 fprintf(stderr,
110 "src wgrp %d nullness 0x%p does not "
111 "match dst 0x%p\n",
112 i, src_grp->i_sid, dst_grp->i_sid);
113 return (B_FALSE);
114 }
115
116
117 if (src_grp->i_sid != NULL &&
118 !smb_sid_cmp(src_grp->i_sid, dst_grp->i_sid)) {
119 smb_sid_tostr(src_grp->i_sid, src_sid);
120 smb_sid_tostr(dst_grp->i_sid, dst_sid);
121 fprintf(stderr, "src wingrp %d sid %s "
122 "does not match dst %s\n",
123 i, src_sid, dst_sid);
124 return (B_FALSE);
125 }
126 }
127 }
128
129 if ((src->tkn_posix_grps == NULL && dst->tkn_posix_grps != NULL) ||
130 (src->tkn_posix_grps != NULL && dst->tkn_posix_grps == NULL)) {
131 fprintf(stderr, "src pgrp nullness 0x%p does not match "
132 "dst 0x%p\n",
133 src->tkn_posix_grps, dst->tkn_posix_grps);
134 return (B_FALSE);
135 }
136
137 if (src->tkn_posix_grps != NULL) {
138 if (src->tkn_posix_grps->pg_ngrps !=
139 dst->tkn_posix_grps->pg_ngrps) {
140 fprintf(stderr,
141 "src pgrp count %d does not match dst %d\n",
142 src->tkn_posix_grps->pg_ngrps,
143 dst->tkn_posix_grps->pg_ngrps);
144 return (B_FALSE);
145 }
146
147 for (i = 0; i < src->tkn_posix_grps->pg_ngrps; i++) {
148 if (src->tkn_posix_grps->pg_grps[i] !=
149 dst->tkn_posix_grps->pg_grps[i]) {
150 fprintf(stderr,
151 "src pgrp num %d %d does not match "
152 "dst %d\n", i,
153 src->tkn_posix_grps->pg_grps[i],
154 dst->tkn_posix_grps->pg_grps[i]);
155 return (B_FALSE);
156 }
157 }
158 }
159
160 return (B_TRUE);
161 }
162
163 enum SAMLOGON_RC {
164 SL_SUCCESS = 0,
165 SL_ARGC,
166 SL_DC_FQDN,
167 SL_NB_DOMAIN,
168 SL_CHALLENGE,
169 SL_NT_PASS,
170 SL_LM_PASS,
171 SL_TOKEN_ALLOC,
172 SL_NETLOGON,
173 SL_TOKEN_COMP,
174 SL_NETLOGON_LOOP,
175 SL_NETLOGON_SAMLOGON,
176 SL_NETLOGON_NOVERIFY
177 };
178
179 int
main(int argc,char * argv[])180 main(int argc, char *argv[])
181 {
182 smb_logon_t user_info = {
183 .lg_secmode = SMB_SECMODE_DOMAIN,
184 .lg_domain_type = SMB_DOMAIN_PRIMARY,
185 .lg_level = NETR_NETWORK_LOGON
186 };
187 smb_token_t *token = NULL;
188 smb_token_t cmp_token;
189 smb_domainex_t di = {0};
190 char *nb_domain, *dc_name, *user_name, *workstation, *chall_file;
191 char *nt_file, *lm_file;
192 uint32_t status;
193 int i;
194
195 if (argc < 8) {
196 fprintf(stderr, "usage: %s <NETBIOS domain> <DC FQDN> "
197 "<user name> "
198 "<client computer name> <Binary Challenge File> "
199 "<Binary NT response file> <Binary LM response file>\n",
200 argv[0]);
201 return (-SL_ARGC);
202 }
203
204 nb_domain = argv[1];
205 dc_name = argv[2];
206 user_name = argv[3];
207 workstation = argv[4];
208 chall_file = argv[5];
209 nt_file = argv[6];
210 lm_file = argv[7];
211
212 if (strlcpy(di.d_dci.dc_name, dc_name, sizeof (di.d_dci.dc_name)) >=
213 sizeof (di.d_dci.dc_name)) {
214 fprintf(stderr, "DC FQDN %s is too long\n", dc_name);
215 return (-SL_DC_FQDN);
216 }
217 if (strlcpy(di.d_primary.di_nbname, nb_domain,
218 sizeof (di.d_primary.di_nbname)) >=
219 sizeof (di.d_primary.di_nbname)) {
220 fprintf(stderr, "Netbios Domain %s is too long\n", nb_domain);
221 return (-SL_NB_DOMAIN);
222 }
223
224 user_info.lg_domain = nb_domain;
225 user_info.lg_e_domain = user_info.lg_domain;
226 user_info.lg_username = user_name;
227 user_info.lg_workstation = workstation;
228
229 user_info.lg_challenge_key.val =
230 read_buf_from_file(chall_file, &user_info.lg_challenge_key.len);
231 if (user_info.lg_challenge_key.val == NULL) {
232 fprintf(stderr, "failed to get challenge\n");
233 return (-SL_CHALLENGE);
234 }
235
236 user_info.lg_nt_password.val =
237 read_buf_from_file(nt_file, &user_info.lg_nt_password.len);
238 if (user_info.lg_nt_password.val == NULL) {
239 fprintf(stderr, "failed to get NT pass\n");
240 return (-SL_NT_PASS);
241 }
242
243 user_info.lg_lm_password.val =
244 read_buf_from_file(lm_file, &user_info.lg_lm_password.len);
245 if (user_info.lg_lm_password.val == NULL) {
246 fprintf(stderr, "failed to get LM pass\n");
247 return (-SL_LM_PASS);
248 }
249
250 /* Initialize only those bits on which netlogon_logon depends */
251 (void) smb_lgrp_start();
252 smb_ipc_init();
253 netr_initialize();
254
255 token = calloc(1, sizeof (*token));
256 if (token == NULL) {
257 fprintf(stderr, "failed to allocate token\n");
258 return (-SL_TOKEN_ALLOC);
259 }
260 status = netlogon_logon(&user_info, token, &di);
261
262 if (status != NT_STATUS_SUCCESS) {
263 fprintf(stderr, "netlogon_logon failed: 0x%x\n", status);
264 return (-SL_NETLOGON);
265 }
266 smb_token_log(token);
267
268 /* struct copy */
269 cmp_token = *token;
270
271 for (i = 0; i < 10; i++) {
272 token = calloc(1, sizeof (*token));
273 if (token == NULL) {
274 fprintf(stderr, "iter %d: failed to allocate token\n",
275 i);
276 return (-SL_TOKEN_ALLOC);
277 }
278 status = netlogon_logon(&user_info, token, &di);
279
280 if (status != NT_STATUS_SUCCESS) {
281 fprintf(stderr,
282 "iter %d: netlogon_logon failed: 0x%x\n",
283 i, status);
284 return (-SL_NETLOGON_LOOP);
285 }
286 if (!compare_tokens(&cmp_token, token)) {
287 fprintf(stderr, "iter %d: tokens didn't match\n", i);
288 smb_token_log(token);
289 return (-SL_TOKEN_COMP);
290 }
291 if (i != 9)
292 smb_token_destroy(token);
293 }
294 smb_token_log(token);
295 smb_token_destroy(token);
296
297 token = calloc(1, sizeof (*token));
298 if (token == NULL) {
299 fprintf(stderr, "failed to allocate token\n");
300 return (-SL_TOKEN_ALLOC);
301 }
302
303 /* Turn off SamLogonEx */
304 netlogon_init_global(0x00000004);
305 status = netlogon_logon(&user_info, token, &di);
306 if (status != NT_STATUS_SUCCESS) {
307 fprintf(stderr, "NoSamLogonEx: netlogon_logon failed: 0x%x\n",
308 status);
309 return (-SL_NETLOGON_SAMLOGON);
310 }
311 smb_token_log(token);
312 if (!compare_tokens(&cmp_token, token)) {
313 fprintf(stderr, "tokens didn't match\n");
314 return (-SL_TOKEN_COMP);
315 }
316 smb_token_destroy(token);
317
318 token = calloc(1, sizeof (*token));
319 if (token == NULL) {
320 fprintf(stderr, "failed to allocate token\n");
321 return (-SL_TOKEN_ALLOC);
322 }
323
324 /* Don't verify responses */
325 netlogon_init_global(0x00000002);
326 status = netlogon_logon(&user_info, token, &di);
327
328 if (status != NT_STATUS_SUCCESS) {
329 fprintf(stderr, "NoVerify: netlogon_logon failed: 0x%x\n",
330 status);
331 return (-SL_NETLOGON_NOVERIFY);
332 }
333 smb_token_log(token);
334
335 if (!compare_tokens(&cmp_token, token)) {
336 fprintf(stderr, "tokens didn't match\n");
337 return (-SL_TOKEN_COMP);
338 }
339 smb_token_destroy(token);
340 return (SL_SUCCESS);
341 }
342