static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const unsigned char orig_trust_passwd_hash[16], const char *new_trust_pwd_cleartext, const unsigned char new_trust_passwd_hash[16], uint32 sec_channel_type) { NTSTATUS result; uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; result = rpccli_netlogon_setup_creds(cli, cli->cli->desthost, /* server name */ lp_workgroup(), /* domain */ global_myname(), /* client name */ global_myname(), /* machine account name */ orig_trust_passwd_hash, sec_channel_type, &neg_flags); if (!NT_STATUS_IS_OK(result)) { DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n", nt_errstr(result))); return result; } if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) { result = rpccli_net_srv_pwset2(cli, mem_ctx, global_myname(), new_trust_pwd_cleartext); } else { result = rpccli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash); } if (!NT_STATUS_IS_OK(result)) { DEBUG(0,("just_change_the_password: unable to change password (%s)!\n", nt_errstr(result))); } return result; }
int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv) { /* libsmb variables */ struct cli_state *cli; TALLOC_CTX *mem_ctx; uint32 acb_info = ACB_WSTRUST; uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; enum netr_SchannelType sec_channel_type; struct rpc_pipe_client *pipe_hnd = NULL; struct dcerpc_binding_handle *b = NULL; /* rpc variables */ struct policy_handle lsa_pol, sam_pol, domain_pol, user_pol; struct dom_sid *domain_sid; uint32 user_rid; /* Password stuff */ char *clear_trust_password = NULL; struct samr_CryptPassword crypt_pwd; uchar md4_trust_password[16]; union samr_UserInfo set_info; /* Misc */ NTSTATUS status, result; int retval = 1; const char *domain = NULL; char *acct_name; struct lsa_String lsa_acct_name; uint32 acct_flags=0; uint32_t access_granted = 0; union lsa_PolicyInformation *info = NULL; struct samr_Ids user_rids; struct samr_Ids name_types; /* check what type of join */ if (argc >= 0) { sec_channel_type = get_sec_channel_type(argv[0]); } else { sec_channel_type = get_sec_channel_type(NULL); } switch (sec_channel_type) { case SEC_CHAN_WKSTA: acb_info = ACB_WSTRUST; break; case SEC_CHAN_BDC: acb_info = ACB_SVRTRUST; break; #if 0 case SEC_CHAN_DOMAIN: acb_info = ACB_DOMTRUST; break; #endif default: DEBUG(0,("secure channel type %d not yet supported\n", sec_channel_type)); break; } /* Make authenticated connection to remote machine */ status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli); if (!NT_STATUS_IS_OK(status)) { return 1; } if (!(mem_ctx = talloc_init("net_rpc_join_newstyle"))) { DEBUG(0, ("Could not initialise talloc context\n")); goto done; } /* Fetch domain sid */ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n", nt_errstr(status) )); goto done; } b = pipe_hnd->binding_handle; CHECK_RPC_ERR(rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true, SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol), "error opening lsa policy handle"); CHECK_DCERPC_ERR(dcerpc_lsa_QueryInfoPolicy(b, mem_ctx, &lsa_pol, LSA_POLICY_INFO_ACCOUNT_DOMAIN, &info, &result), "error querying info policy"); domain = info->account_domain.name.string; domain_sid = info->account_domain.sid; dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result); TALLOC_FREE(pipe_hnd); /* Done with this pipe */ /* Bail out if domain didn't get set. */ if (!domain) { DEBUG(0, ("Could not get domain name.\n")); goto done; } /* Create domain user */ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n", nt_errstr(status) )); goto done; } b = pipe_hnd->binding_handle; CHECK_DCERPC_ERR(dcerpc_samr_Connect2(b, mem_ctx, pipe_hnd->desthost, SAMR_ACCESS_ENUM_DOMAINS | SAMR_ACCESS_LOOKUP_DOMAIN, &sam_pol, &result), "could not connect to SAM database"); CHECK_DCERPC_ERR(dcerpc_samr_OpenDomain(b, mem_ctx, &sam_pol, SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 | SAMR_DOMAIN_ACCESS_CREATE_USER | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT, domain_sid, &domain_pol, &result), "could not open domain"); /* Create domain user */ if ((acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname())) == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } strlower_m(acct_name); init_lsa_String(&lsa_acct_name, acct_name); acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE | SEC_STD_WRITE_DAC | SEC_STD_DELETE | SAMR_USER_ACCESS_SET_PASSWORD | SAMR_USER_ACCESS_GET_ATTRIBUTES | SAMR_USER_ACCESS_SET_ATTRIBUTES; DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); status = dcerpc_samr_CreateUser2(b, mem_ctx, &domain_pol, &lsa_acct_name, acb_info, acct_flags, &user_pol, &access_granted, &user_rid, &result); if (!NT_STATUS_IS_OK(status)) { goto done; } if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, NT_STATUS_USER_EXISTS)) { status = result; d_fprintf(stderr,_("Creation of workstation account failed\n")); /* If NT_STATUS_ACCESS_DENIED then we have a valid username/password combo but the user does not have administrator access. */ if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) d_fprintf(stderr, _("User specified does not have " "administrator privileges\n")); goto done; } /* We *must* do this.... don't ask... */ if (NT_STATUS_IS_OK(result)) { dcerpc_samr_Close(b, mem_ctx, &user_pol, &result); } CHECK_DCERPC_ERR_DEBUG(dcerpc_samr_LookupNames(b, mem_ctx, &domain_pol, 1, &lsa_acct_name, &user_rids, &name_types, &result), ("error looking up rid for user %s: %s/%s\n", acct_name, nt_errstr(status), nt_errstr(result))); if (user_rids.count != 1) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto done; } if (name_types.count != 1) { status = NT_STATUS_INVALID_NETWORK_RESPONSE; goto done; } if (name_types.ids[0] != SID_NAME_USER) { DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types.ids[0])); goto done; } user_rid = user_rids.ids[0]; /* Open handle on user */ CHECK_DCERPC_ERR_DEBUG( dcerpc_samr_OpenUser(b, mem_ctx, &domain_pol, SEC_FLAG_MAXIMUM_ALLOWED, user_rid, &user_pol, &result), ("could not re-open existing user %s: %s/%s\n", acct_name, nt_errstr(status), nt_errstr(result))); /* Create a random machine account password */ clear_trust_password = generate_random_str(talloc_tos(), DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); E_md4hash(clear_trust_password, md4_trust_password); /* Set password on machine account */ init_samr_CryptPassword(clear_trust_password, &cli->user_session_key, &crypt_pwd); set_info.info24.password = crypt_pwd; set_info.info24.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON; CHECK_DCERPC_ERR(dcerpc_samr_SetUserInfo2(b, mem_ctx, &user_pol, 24, &set_info, &result), "error setting trust account password"); /* Why do we have to try to (re-)set the ACB to be the same as what we passed in the samr_create_dom_user() call? When a NT workstation is joined to a domain by an administrator the acb_info is set to 0x80. For a normal user with "Add workstations to the domain" rights the acb_info is 0x84. I'm not sure whether it is supposed to make a difference or not. NT seems to cope with either value so don't bomb out if the set userinfo2 level 0x10 fails. -tpot */ set_info.info16.acct_flags = acb_info; /* Ignoring the return value is necessary for joining a domain as a normal user with "Add workstation to domain" privilege. */ status = dcerpc_samr_SetUserInfo(b, mem_ctx, &user_pol, 16, &set_info, &result); dcerpc_samr_Close(b, mem_ctx, &user_pol, &result); TALLOC_FREE(pipe_hnd); /* Done with this pipe */ /* Now check the whole process from top-to-bottom */ status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id, &pipe_hnd); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n", nt_errstr(status) )); goto done; } status = rpccli_netlogon_setup_creds(pipe_hnd, cli->desthost, /* server name */ domain, /* domain */ global_myname(), /* client name */ global_myname(), /* machine account name */ md4_trust_password, sec_channel_type, &neg_flags); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error in domain join verification (credential setup failed): %s\n\n", nt_errstr(status))); if ( NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && (sec_channel_type == SEC_CHAN_BDC) ) { d_fprintf(stderr, _("Please make sure that no computer " "account\nnamed like this machine " "(%s) exists in the domain\n"), global_myname()); } goto done; } /* We can only check the schannel connection if the client is allowed to do this and the server supports it. If not, just assume success (after all the rpccli_netlogon_setup_creds() succeeded, and we'll do the same again (setup creds) in net_rpc_join_ok(). JRA. */ if (lp_client_schannel() && (neg_flags & NETLOGON_NEG_SCHANNEL)) { struct rpc_pipe_client *netlogon_schannel_pipe; status = cli_rpc_pipe_open_schannel_with_key( cli, &ndr_table_netlogon.syntax_id, NCACN_NP, DCERPC_AUTH_LEVEL_PRIVACY, domain, &pipe_hnd->dc, &netlogon_schannel_pipe); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Error in domain join verification (schannel setup failed): %s\n\n", nt_errstr(status))); if ( NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && (sec_channel_type == SEC_CHAN_BDC) ) { d_fprintf(stderr, _("Please make sure that no " "computer account\nnamed " "like this machine (%s) " "exists in the domain\n"), global_myname()); } goto done; } TALLOC_FREE(netlogon_schannel_pipe); } TALLOC_FREE(pipe_hnd); /* Now store the secret in the secrets database */ strupper_m(CONST_DISCARD(char *, domain)); if (!secrets_store_domain_sid(domain, domain_sid)) { DEBUG(0, ("error storing domain sid for %s\n", domain)); goto done; } if (!secrets_store_machine_password(clear_trust_password, domain, sec_channel_type)) { DEBUG(0, ("error storing plaintext domain secrets for %s\n", domain)); } /* double-check, connection from scratch */ status = net_rpc_join_ok(c, domain, cli->desthost, &cli->dest_ss); retval = NT_STATUS_IS_OK(status) ? 0 : -1; done: /* Display success or failure */ if (domain) { if (retval != 0) { fprintf(stderr,_("Unable to join domain %s.\n"),domain); } else { printf(_("Joined domain %s.\n"),domain); } } cli_shutdown(cli); TALLOC_FREE(clear_trust_password); return retval; }
static NTSTATUS check_netlogond_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { TALLOC_CTX *frame = talloc_stackframe(); struct netr_SamInfo3 *info3 = NULL; struct rpc_pipe_client *p = NULL; struct pipe_auth_data *auth = NULL; uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; uint8_t machine_password[16]; struct netlogon_creds_CredentialState *creds; NTSTATUS schannel_bind_result, status; struct named_mutex *mutex = NULL; const char *ncalrpcsock; DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); ncalrpcsock = lp_parm_const_string( GLOBAL_SECTION_SNUM, "auth_netlogond", "socket", NULL); if (ncalrpcsock == NULL) { ncalrpcsock = talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_NCALRPCDIR(), "DEFAULT"); } if (ncalrpcsock == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } creds = secrets_fetch_local_schannel_creds(talloc_tos()); if (creds == NULL) { goto new_key; } status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock, creds, user_info, &info3, &schannel_bind_result); DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status))); if (NT_STATUS_IS_OK(status)) { goto okay; } if (NT_STATUS_IS_OK(schannel_bind_result)) { /* * This is a real failure from the DC */ goto done; } new_key: mutex = grab_named_mutex(talloc_tos(), "LOCAL_SCHANNEL_KEY", 60); if (mutex == NULL) { DEBUG(10, ("Could not get mutex LOCAL_SCHANNEL_KEY\n")); status = NT_STATUS_ACCESS_DENIED; goto done; } DEBUG(10, ("schannel bind failed, setting up new key\n")); status = rpc_pipe_open_ncalrpc(talloc_tos(), ncalrpcsock, &ndr_table_netlogon.syntax_id, &p); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("rpc_pipe_open_ncalrpc failed: %s\n", nt_errstr(status))); goto done; } status = rpccli_anon_bind_data(p, &auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("rpccli_anon_bind_data failed: %s\n", nt_errstr(status))); goto done; } status = rpc_pipe_bind(p, auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("rpc_pipe_bind failed: %s\n", nt_errstr(status))); goto done; } status = mymachinepw(machine_password); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("mymachinepw failed: %s\n", nt_errstr(status))); goto done; } DEBUG(10, ("machinepw ")); dump_data(10, machine_password, 16); status = rpccli_netlogon_setup_creds( p, global_myname(), lp_workgroup(), global_myname(), global_myname(), machine_password, SEC_CHAN_BDC, &neg_flags); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("rpccli_netlogon_setup_creds failed: %s\n", nt_errstr(status))); goto done; } secrets_store_local_schannel_creds(p->dc); /* * Retry the authentication with the mutex held. This way nobody else * can step on our toes. */ status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock, p->dc, user_info, &info3, &schannel_bind_result); TALLOC_FREE(p); DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status))); if (!NT_STATUS_IS_OK(status)) { goto done; } okay: status = make_server_info_info3(mem_ctx, user_info->client.account_name, user_info->mapped.domain_name, server_info, info3); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("make_server_info_info3 failed: %s\n", nt_errstr(status))); TALLOC_FREE(frame); return status; } status = NT_STATUS_OK; done: TALLOC_FREE(frame); return status; }
static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS status = NT_STATUS_UNSUCCESSFUL; NTSTATUS result; const char *server_name = cli->desthost; uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; struct netr_Authenticator clnt_creds, srv_cred; struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL; unsigned char trust_passwd_hash[16]; enum netr_SchannelType sec_channel_type = 0; struct netr_ChangeLogEntry e; uint32_t rid = 500; struct dcerpc_binding_handle *b = cli->binding_handle; if (argc > 2) { fprintf(stderr, "Usage: %s <user rid>\n", argv[0]); return NT_STATUS_OK; } if (argc == 2) { sscanf(argv[1], "%d", &rid); } if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, NULL, &sec_channel_type)) { return NT_STATUS_UNSUCCESSFUL; } status = rpccli_netlogon_setup_creds(cli, server_name, /* server name */ lp_workgroup(), /* domain */ lp_netbios_name(), /* client name */ lp_netbios_name(), /* machine account name */ trust_passwd_hash, sec_channel_type, &neg_flags); if (!NT_STATUS_IS_OK(status)) { return status; } netlogon_creds_client_authenticator(cli->dc, &clnt_creds); ZERO_STRUCT(e); e.object_rid = rid; e.db_index = SAM_DATABASE_DOMAIN; e.delta_type = NETR_DELTA_USER; status = dcerpc_netr_DatabaseRedo(b, mem_ctx, server_name, lp_netbios_name(), &clnt_creds, &srv_cred, e, 0, /* is calculated automatically */ &delta_enum_array, &result); if (!NT_STATUS_IS_OK(status)) { return status; } if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) { DEBUG(0,("credentials chain check failed\n")); return NT_STATUS_ACCESS_DENIED; } return result; }
NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *account_name, const unsigned char orig_trust_passwd_hash[16], const char *new_trust_pwd_cleartext, const unsigned char new_trust_passwd_hash[16], enum netr_SchannelType sec_channel_type) { NTSTATUS result, status; struct netr_Authenticator clnt_creds, srv_cred; struct dcerpc_binding_handle *b = cli->binding_handle; if (!cli->dc) { uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; result = rpccli_netlogon_setup_creds(cli, cli->desthost, /* server name */ lp_workgroup(), /* domain */ lp_netbios_name(), /* client name */ account_name, /* machine account name */ orig_trust_passwd_hash, sec_channel_type, &neg_flags); if (!NT_STATUS_IS_OK(result)) { DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n", nt_errstr(result))); return result; } } netlogon_creds_client_authenticator(cli->dc, &clnt_creds); if (cli->dc->negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) { struct netr_CryptPassword new_password; uint32_t old_timeout; init_netr_CryptPassword(new_trust_pwd_cleartext, cli->dc, &new_password); old_timeout = dcerpc_binding_handle_set_timeout(b, 600000); status = dcerpc_netr_ServerPasswordSet2(b, mem_ctx, cli->srv_name_slash, cli->dc->account_name, sec_channel_type, cli->dc->computer_name, &clnt_creds, &srv_cred, &new_password, &result); dcerpc_binding_handle_set_timeout(b, old_timeout); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("dcerpc_netr_ServerPasswordSet2 failed: %s\n", nt_errstr(status))); return status; } } else { struct samr_Password new_password; uint32_t old_timeout; memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash)); netlogon_creds_des_encrypt(cli->dc, &new_password); old_timeout = dcerpc_binding_handle_set_timeout(b, 600000); status = dcerpc_netr_ServerPasswordSet(b, mem_ctx, cli->srv_name_slash, cli->dc->account_name, sec_channel_type, cli->dc->computer_name, &clnt_creds, &srv_cred, &new_password, &result); dcerpc_binding_handle_set_timeout(b, old_timeout); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("dcerpc_netr_ServerPasswordSet failed: %s\n", nt_errstr(status))); return status; } } /* Always check returned credentials. */ if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) { DEBUG(0,("credentials chain check failed\n")); return NT_STATUS_ACCESS_DENIED; } if (!NT_STATUS_IS_OK(result)) { DEBUG(0,("dcerpc_netr_ServerPasswordSet{2} failed: %s\n", nt_errstr(result))); return result; } return result; }