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 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 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