1/* 2 Samba Unix/Linux SMB client library 3 Distributed SMB/CIFS Server Management Utility 4 Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org) 5 Copyright (C) Tim Potter 2001 6 Copyright (C) 2008 Guenther Deschner 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21#include "includes.h" 22#include "utils/net.h" 23#include "../libcli/auth/libcli_auth.h" 24#include "../librpc/gen_ndr/cli_lsa.h" 25#include "../librpc/gen_ndr/cli_samr.h" 26 27/* Macro for checking RPC error codes to make things more readable */ 28 29#define CHECK_RPC_ERR(rpc, msg) \ 30 if (!NT_STATUS_IS_OK(result = rpc)) { \ 31 DEBUG(0, (msg ": %s\n", nt_errstr(result))); \ 32 goto done; \ 33 } 34 35#define CHECK_RPC_ERR_DEBUG(rpc, debug_args) \ 36 if (!NT_STATUS_IS_OK(result = rpc)) { \ 37 DEBUG(0, debug_args); \ 38 goto done; \ 39 } 40 41/** 42 * confirm that a domain join is still valid 43 * 44 * @return A shell status integer (0 for success) 45 * 46 **/ 47NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain, 48 const char *server, struct sockaddr_storage *pss) 49{ 50 enum security_types sec; 51 unsigned int conn_flags = NET_FLAGS_PDC; 52 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; 53 struct cli_state *cli = NULL; 54 struct rpc_pipe_client *pipe_hnd = NULL; 55 struct rpc_pipe_client *netlogon_pipe = NULL; 56 NTSTATUS ntret = NT_STATUS_UNSUCCESSFUL; 57 58 sec = (enum security_types)lp_security(); 59 60 if (sec == SEC_ADS) { 61 /* Connect to IPC$ using machine account's credentials. We don't use anonymous 62 connection here, as it may be denied by server's local policy. */ 63 net_use_machine_account(c); 64 65 } else { 66 /* some servers (e.g. WinNT) don't accept machine-authenticated 67 smb connections */ 68 conn_flags |= NET_FLAGS_ANONYMOUS; 69 } 70 71 /* Connect to remote machine */ 72 ntret = net_make_ipc_connection_ex(c, domain, server, pss, conn_flags, 73 &cli); 74 if (!NT_STATUS_IS_OK(ntret)) { 75 return ntret; 76 } 77 78 /* Setup the creds as though we're going to do schannel... */ 79 ntret = get_schannel_session_key(cli, domain, &neg_flags, 80 &netlogon_pipe); 81 82 /* We return NT_STATUS_INVALID_NETWORK_RESPONSE if the server is refusing 83 to negotiate schannel, but the creds were set up ok. That'll have to do. */ 84 85 if (!NT_STATUS_IS_OK(ntret)) { 86 if (NT_STATUS_EQUAL(ntret, NT_STATUS_INVALID_NETWORK_RESPONSE)) { 87 cli_shutdown(cli); 88 return NT_STATUS_OK; 89 } else { 90 DEBUG(0,("net_rpc_join_ok: failed to get schannel session " 91 "key from server %s for domain %s. Error was %s\n", 92 cli->desthost, domain, nt_errstr(ntret) )); 93 cli_shutdown(cli); 94 return ntret; 95 } 96 } 97 98 /* Only do the rest of the schannel test if the client is allowed to do this. */ 99 if (!lp_client_schannel()) { 100 cli_shutdown(cli); 101 /* We're good... */ 102 return ntret; 103 } 104 105 ntret = cli_rpc_pipe_open_schannel_with_key( 106 cli, &ndr_table_netlogon.syntax_id, NCACN_NP, 107 DCERPC_AUTH_LEVEL_PRIVACY, 108 domain, &netlogon_pipe->dc, &pipe_hnd); 109 110 if (!NT_STATUS_IS_OK(ntret)) { 111 DEBUG(0,("net_rpc_join_ok: failed to open schannel session " 112 "on netlogon pipe to server %s for domain %s. Error was %s\n", 113 cli->desthost, domain, nt_errstr(ntret) )); 114 /* 115 * Note: here, we have: 116 * (pipe_hnd != NULL) if and only if NT_STATUS_IS_OK(ntret) 117 */ 118 } 119 120 cli_shutdown(cli); 121 return ntret; 122} 123 124/** 125 * Join a domain using the administrator username and password 126 * 127 * @param argc Standard main() style argc 128 * @param argc Standard main() style argv. Initial components are already 129 * stripped. Currently not used. 130 * @return A shell status integer (0 for success) 131 * 132 **/ 133 134int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) 135{ 136 137 /* libsmb variables */ 138 139 struct cli_state *cli; 140 TALLOC_CTX *mem_ctx; 141 uint32 acb_info = ACB_WSTRUST; 142 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; 143 enum netr_SchannelType sec_channel_type; 144 struct rpc_pipe_client *pipe_hnd = NULL; 145 146 /* rpc variables */ 147 148 struct policy_handle lsa_pol, sam_pol, domain_pol, user_pol; 149 DOM_SID *domain_sid; 150 uint32 user_rid; 151 152 /* Password stuff */ 153 154 char *clear_trust_password = NULL; 155 struct samr_CryptPassword crypt_pwd; 156 uchar md4_trust_password[16]; 157 union samr_UserInfo set_info; 158 159 /* Misc */ 160 161 NTSTATUS result; 162 int retval = 1; 163 const char *domain = NULL; 164 char *acct_name; 165 struct lsa_String lsa_acct_name; 166 uint32 acct_flags=0; 167 uint32_t access_granted = 0; 168 union lsa_PolicyInformation *info = NULL; 169 struct samr_Ids user_rids; 170 struct samr_Ids name_types; 171 172 /* check what type of join */ 173 if (argc >= 0) { 174 sec_channel_type = get_sec_channel_type(argv[0]); 175 } else { 176 sec_channel_type = get_sec_channel_type(NULL); 177 } 178 179 switch (sec_channel_type) { 180 case SEC_CHAN_WKSTA: 181 acb_info = ACB_WSTRUST; 182 break; 183 case SEC_CHAN_BDC: 184 acb_info = ACB_SVRTRUST; 185 break; 186#if 0 187 case SEC_CHAN_DOMAIN: 188 acb_info = ACB_DOMTRUST; 189 break; 190#endif 191 default: 192 DEBUG(0,("secure channel type %d not yet supported\n", 193 sec_channel_type)); 194 break; 195 } 196 197 /* Make authenticated connection to remote machine */ 198 199 result = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli); 200 if (!NT_STATUS_IS_OK(result)) { 201 return 1; 202 } 203 204 if (!(mem_ctx = talloc_init("net_rpc_join_newstyle"))) { 205 DEBUG(0, ("Could not initialise talloc context\n")); 206 goto done; 207 } 208 209 /* Fetch domain sid */ 210 211 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, 212 &pipe_hnd); 213 if (!NT_STATUS_IS_OK(result)) { 214 DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n", 215 nt_errstr(result) )); 216 goto done; 217 } 218 219 220 CHECK_RPC_ERR(rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true, 221 SEC_FLAG_MAXIMUM_ALLOWED, 222 &lsa_pol), 223 "error opening lsa policy handle"); 224 225 CHECK_RPC_ERR(rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx, 226 &lsa_pol, 227 LSA_POLICY_INFO_ACCOUNT_DOMAIN, 228 &info), 229 "error querying info policy"); 230 231 domain = info->account_domain.name.string; 232 domain_sid = info->account_domain.sid; 233 234 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol); 235 TALLOC_FREE(pipe_hnd); /* Done with this pipe */ 236 237 /* Bail out if domain didn't get set. */ 238 if (!domain) { 239 DEBUG(0, ("Could not get domain name.\n")); 240 goto done; 241 } 242 243 /* Create domain user */ 244 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, 245 &pipe_hnd); 246 if (!NT_STATUS_IS_OK(result)) { 247 DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n", 248 nt_errstr(result) )); 249 goto done; 250 } 251 252 CHECK_RPC_ERR(rpccli_samr_Connect2(pipe_hnd, mem_ctx, 253 pipe_hnd->desthost, 254 SAMR_ACCESS_ENUM_DOMAINS 255 | SAMR_ACCESS_LOOKUP_DOMAIN, 256 &sam_pol), 257 "could not connect to SAM database"); 258 259 260 CHECK_RPC_ERR(rpccli_samr_OpenDomain(pipe_hnd, mem_ctx, 261 &sam_pol, 262 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 263 | SAMR_DOMAIN_ACCESS_CREATE_USER 264 | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, 265 domain_sid, 266 &domain_pol), 267 "could not open domain"); 268 269 /* Create domain user */ 270 if ((acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname())) == NULL) { 271 result = NT_STATUS_NO_MEMORY; 272 goto done; 273 } 274 strlower_m(acct_name); 275 276 init_lsa_String(&lsa_acct_name, acct_name); 277 278 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE | 279 SEC_STD_WRITE_DAC | SEC_STD_DELETE | 280 SAMR_USER_ACCESS_SET_PASSWORD | 281 SAMR_USER_ACCESS_GET_ATTRIBUTES | 282 SAMR_USER_ACCESS_SET_ATTRIBUTES; 283 284 DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); 285 286 result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx, 287 &domain_pol, 288 &lsa_acct_name, 289 acb_info, 290 acct_flags, 291 &user_pol, 292 &access_granted, 293 &user_rid); 294 295 if (!NT_STATUS_IS_OK(result) && 296 !NT_STATUS_EQUAL(result, NT_STATUS_USER_EXISTS)) { 297 d_fprintf(stderr,_("Creation of workstation account failed\n")); 298 299 /* If NT_STATUS_ACCESS_DENIED then we have a valid 300 username/password combo but the user does not have 301 administrator access. */ 302 303 if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) 304 d_fprintf(stderr, _("User specified does not have " 305 "administrator privileges\n")); 306 307 goto done; 308 } 309 310 /* We *must* do this.... don't ask... */ 311 312 if (NT_STATUS_IS_OK(result)) { 313 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol); 314 } 315 316 CHECK_RPC_ERR_DEBUG(rpccli_samr_LookupNames(pipe_hnd, mem_ctx, 317 &domain_pol, 318 1, 319 &lsa_acct_name, 320 &user_rids, 321 &name_types), 322 ("error looking up rid for user %s: %s\n", 323 acct_name, nt_errstr(result))); 324 325 if (name_types.ids[0] != SID_NAME_USER) { 326 DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types.ids[0])); 327 goto done; 328 } 329 330 user_rid = user_rids.ids[0]; 331 332 /* Open handle on user */ 333 334 CHECK_RPC_ERR_DEBUG( 335 rpccli_samr_OpenUser(pipe_hnd, mem_ctx, 336 &domain_pol, 337 SEC_FLAG_MAXIMUM_ALLOWED, 338 user_rid, 339 &user_pol), 340 ("could not re-open existing user %s: %s\n", 341 acct_name, nt_errstr(result))); 342 343 /* Create a random machine account password */ 344 345 clear_trust_password = generate_random_str(talloc_tos(), DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); 346 E_md4hash(clear_trust_password, md4_trust_password); 347 348 /* Set password on machine account */ 349 350 init_samr_CryptPassword(clear_trust_password, 351 &cli->user_session_key, 352 &crypt_pwd); 353 354 set_info.info24.password = crypt_pwd; 355 set_info.info24.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON; 356 357 CHECK_RPC_ERR(rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx, 358 &user_pol, 359 24, 360 &set_info), 361 "error setting trust account password"); 362 363 /* Why do we have to try to (re-)set the ACB to be the same as what 364 we passed in the samr_create_dom_user() call? When a NT 365 workstation is joined to a domain by an administrator the 366 acb_info is set to 0x80. For a normal user with "Add 367 workstations to the domain" rights the acb_info is 0x84. I'm 368 not sure whether it is supposed to make a difference or not. NT 369 seems to cope with either value so don't bomb out if the set 370 userinfo2 level 0x10 fails. -tpot */ 371 372 set_info.info16.acct_flags = acb_info; 373 374 /* Ignoring the return value is necessary for joining a domain 375 as a normal user with "Add workstation to domain" privilege. */ 376 377 result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx, 378 &user_pol, 379 16, 380 &set_info); 381 382 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol); 383 TALLOC_FREE(pipe_hnd); /* Done with this pipe */ 384 385 /* Now check the whole process from top-to-bottom */ 386 387 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, 388 &pipe_hnd); 389 if (!NT_STATUS_IS_OK(result)) { 390 DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n", 391 nt_errstr(result) )); 392 goto done; 393 } 394 395 result = rpccli_netlogon_setup_creds(pipe_hnd, 396 cli->desthost, /* server name */ 397 domain, /* domain */ 398 global_myname(), /* client name */ 399 global_myname(), /* machine account name */ 400 md4_trust_password, 401 sec_channel_type, 402 &neg_flags); 403 404 if (!NT_STATUS_IS_OK(result)) { 405 DEBUG(0, ("Error in domain join verification (credential setup failed): %s\n\n", 406 nt_errstr(result))); 407 408 if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && 409 (sec_channel_type == SEC_CHAN_BDC) ) { 410 d_fprintf(stderr, _("Please make sure that no computer " 411 "account\nnamed like this machine " 412 "(%s) exists in the domain\n"), 413 global_myname()); 414 } 415 416 goto done; 417 } 418 419 /* We can only check the schannel connection if the client is allowed 420 to do this and the server supports it. If not, just assume success 421 (after all the rpccli_netlogon_setup_creds() succeeded, and we'll 422 do the same again (setup creds) in net_rpc_join_ok(). JRA. */ 423 424 if (lp_client_schannel() && (neg_flags & NETLOGON_NEG_SCHANNEL)) { 425 struct rpc_pipe_client *netlogon_schannel_pipe; 426 427 result = cli_rpc_pipe_open_schannel_with_key( 428 cli, &ndr_table_netlogon.syntax_id, NCACN_NP, 429 DCERPC_AUTH_LEVEL_PRIVACY, domain, &pipe_hnd->dc, 430 &netlogon_schannel_pipe); 431 432 if (!NT_STATUS_IS_OK(result)) { 433 DEBUG(0, ("Error in domain join verification (schannel setup failed): %s\n\n", 434 nt_errstr(result))); 435 436 if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && 437 (sec_channel_type == SEC_CHAN_BDC) ) { 438 d_fprintf(stderr, _("Please make sure that no " 439 "computer account\nnamed " 440 "like this machine (%s) " 441 "exists in the domain\n"), 442 global_myname()); 443 } 444 445 goto done; 446 } 447 TALLOC_FREE(netlogon_schannel_pipe); 448 } 449 450 TALLOC_FREE(pipe_hnd); 451 452 /* Now store the secret in the secrets database */ 453 454 strupper_m(CONST_DISCARD(char *, domain)); 455 456 if (!secrets_store_domain_sid(domain, domain_sid)) { 457 DEBUG(0, ("error storing domain sid for %s\n", domain)); 458 goto done; 459 } 460 461 if (!secrets_store_machine_password(clear_trust_password, domain, sec_channel_type)) { 462 DEBUG(0, ("error storing plaintext domain secrets for %s\n", domain)); 463 } 464 465 /* double-check, connection from scratch */ 466 result = net_rpc_join_ok(c, domain, cli->desthost, &cli->dest_ss); 467 retval = NT_STATUS_IS_OK(result) ? 0 : -1; 468 469done: 470 471 /* Display success or failure */ 472 473 if (domain) { 474 if (retval != 0) { 475 fprintf(stderr,_("Unable to join domain %s.\n"),domain); 476 } else { 477 printf(_("Joined domain %s.\n"),domain); 478 } 479 } 480 481 cli_shutdown(cli); 482 483 TALLOC_FREE(clear_trust_password); 484 485 return retval; 486} 487 488/** 489 * check that a join is OK 490 * 491 * @return A shell status integer (0 for success) 492 * 493 **/ 494int net_rpc_testjoin(struct net_context *c, int argc, const char **argv) 495{ 496 NTSTATUS nt_status; 497 498 if (c->display_usage) { 499 d_printf(_("Usage\n" 500 "net rpc testjoin\n" 501 " Test if a join is OK\n")); 502 return 0; 503 } 504 505 /* Display success or failure */ 506 nt_status = net_rpc_join_ok(c, c->opt_target_workgroup, NULL, NULL); 507 if (!NT_STATUS_IS_OK(nt_status)) { 508 fprintf(stderr, _("Join to domain '%s' is not valid: %s\n"), 509 c->opt_target_workgroup, nt_errstr(nt_status)); 510 return -1; 511 } 512 513 printf(_("Join to '%s' is OK\n"), c->opt_target_workgroup); 514 return 0; 515} 516