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 netlogond_validate(TALLOC_CTX *mem_ctx, const struct auth_context *auth_context, const char *ncalrpc_sockname, struct netlogon_creds_CredentialState *creds, const struct auth_usersupplied_info *user_info, struct netr_SamInfo3 **pinfo3, NTSTATUS *schannel_bind_result) { struct rpc_pipe_client *p = NULL; struct pipe_auth_data *auth = NULL; struct netr_SamInfo3 *info3 = NULL; NTSTATUS status; *schannel_bind_result = NT_STATUS_OK; status = rpc_pipe_open_ncalrpc(talloc_tos(), ncalrpc_sockname, &ndr_table_netlogon.syntax_id, &p); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("rpc_pipe_open_ncalrpc failed: %s\n", nt_errstr(status))); return status; } p->dc = creds; status = rpccli_schannel_bind_data(p, lp_workgroup(), DCERPC_AUTH_LEVEL_PRIVACY, p->dc, &auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("rpccli_schannel_bind_data failed: %s\n", nt_errstr(status))); TALLOC_FREE(p); return status; } status = rpc_pipe_bind(p, auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("rpc_pipe_bind failed: %s\n", nt_errstr(status))); TALLOC_FREE(p); *schannel_bind_result = status; return status; } status = rpccli_netlogon_sam_network_logon_ex( p, p, user_info->logon_parameters, /* flags such as 'allow * workstation logon' */ global_myname(), /* server name */ user_info->client.account_name, /* user name logging on. */ user_info->client.domain_name, /* domain name */ user_info->workstation_name, /* workstation name */ (uchar *)auth_context->challenge.data, /* 8 byte challenge. */ 3, /* validation level */ user_info->password.response.lanman, /* lanman 24 byte response */ user_info->password.response.nt, /* nt 24 byte response */ &info3); /* info3 out */ DEBUG(10, ("rpccli_netlogon_sam_network_logon_ex returned %s\n", nt_errstr(status))); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(p); return status; } *pinfo3 = talloc_move(mem_ctx, &info3); TALLOC_FREE(p); return NT_STATUS_OK; }
static NTSTATUS ep_register(TALLOC_CTX *mem_ctx, const struct ndr_interface_table *iface, const struct dcerpc_binding_vector *bind_vec, const struct GUID *object_guid, const char *annotation, uint32_t replace, uint32_t unregister, struct dcerpc_binding_handle **pbh) { struct rpc_pipe_client *cli = NULL; struct dcerpc_binding_handle *h; struct pipe_auth_data *auth; const char *ncalrpc_sock; const char *rpcsrv_type; struct epm_entry_t *entries; uint32_t num_ents, i; TALLOC_CTX *tmp_ctx; uint32_t result = EPMAPPER_STATUS_OK; NTSTATUS status; if (iface == NULL) { return NT_STATUS_INVALID_PARAMETER; } if (bind_vec == NULL || bind_vec->count == 0) { return NT_STATUS_INVALID_PARAMETER; } tmp_ctx = talloc_stackframe(); if (tmp_ctx == NULL) { return NT_STATUS_NO_MEMORY; } rpcsrv_type = lp_parm_const_string(GLOBAL_SECTION_SNUM, "rpc_server", "epmapper", "none"); if (strcasecmp_m(rpcsrv_type, "embedded") == 0) { struct tsocket_address *local; int rc; rc = tsocket_address_inet_from_strings(tmp_ctx, "ip", "127.0.0.1", 0, &local); if (rc < 0) { return NT_STATUS_NO_MEMORY; } status = rpcint_binding_handle(tmp_ctx, &ndr_table_epmapper, local, get_session_info_system(), server_messaging_context(), &h); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("dcerpc_ep_register: Could not connect to " "epmapper (%s)", nt_errstr(status))); goto done; } } else if (strcasecmp_m(rpcsrv_type, "daemon") == 0) { /* Connect to the endpoint mapper locally */ ncalrpc_sock = talloc_asprintf(tmp_ctx, "%s/%s", lp_ncalrpc_dir(), "EPMAPPER"); if (ncalrpc_sock == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } status = rpc_pipe_open_ncalrpc(tmp_ctx, ncalrpc_sock, &ndr_table_epmapper.syntax_id, &cli); if (!NT_STATUS_IS_OK(status)) { goto done; } status = rpccli_ncalrpc_bind_data(cli, &auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to initialize anonymous bind.\n")); goto done; } status = rpc_pipe_bind(cli, auth); if (!NT_STATUS_IS_OK(status)) { DEBUG(2, ("Failed to bind ncalrpc socket.\n")); goto done; } h = cli->binding_handle; } else { status = NT_STATUS_INVALID_PARAMETER; goto done; } num_ents = bind_vec->count; entries = talloc_array(tmp_ctx, struct epm_entry_t, num_ents); for (i = 0; i < num_ents; i++) { struct dcerpc_binding *map_binding = &bind_vec->bindings[i]; struct epm_twr_t *map_tower; map_tower = talloc_zero(entries, struct epm_twr_t); if (map_tower == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } status = dcerpc_binding_build_tower(entries, map_binding, &map_tower->tower); if (!NT_STATUS_IS_OK(status)) { goto done; } entries[i].tower = map_tower; if (annotation == NULL) { entries[i].annotation = talloc_strdup(entries, ""); } else { entries[i].annotation = talloc_strndup(entries, annotation, EPM_MAX_ANNOTATION_SIZE); } if (entries[i].annotation == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } if (object_guid != NULL) { entries[i].object = *object_guid; } else { entries[i].object = map_binding->object.uuid; } } if (unregister) { status = dcerpc_epm_Delete(h, tmp_ctx, num_ents, entries, &result); } else { status = dcerpc_epm_Insert(h, tmp_ctx, num_ents, entries, replace, &result); } if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("dcerpc_ep_register: Could not insert tower (%s)\n", nt_errstr(status))); goto done; } if (result != EPMAPPER_STATUS_OK) { DEBUG(0, ("dcerpc_ep_register: Could not insert tower (0x%.8x)\n", result)); status = NT_STATUS_UNSUCCESSFUL; goto done; } if (pbh != NULL) { *pbh = talloc_move(mem_ctx, &h); talloc_steal(*pbh, cli); } done: talloc_free(tmp_ctx); return status; }