Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : async implementation of WINBINDD_PING_DC
4 : Copyright (C) Volker Lendecke 2009
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "winbindd.h"
22 : #include "librpc/gen_ndr/ndr_winbind_c.h"
23 :
24 : struct winbindd_ping_dc_state {
25 : const char *dcname;
26 : NTSTATUS result;
27 : };
28 :
29 : static void winbindd_ping_dc_done(struct tevent_req *subreq);
30 :
31 57 : struct tevent_req *winbindd_ping_dc_send(TALLOC_CTX *mem_ctx,
32 : struct tevent_context *ev,
33 : struct winbindd_cli_state *cli,
34 : struct winbindd_request *request)
35 : {
36 0 : struct tevent_req *req, *subreq;
37 0 : struct winbindd_ping_dc_state *state;
38 0 : struct winbindd_domain *domain;
39 :
40 57 : req = tevent_req_create(mem_ctx, &state,
41 : struct winbindd_ping_dc_state);
42 57 : if (req == NULL) {
43 0 : return NULL;
44 : }
45 :
46 57 : if (request->domain_name[0] == '\0') {
47 : /* preserve old behavior, when no domain name is given */
48 4 : domain = find_our_domain();
49 : } else {
50 53 : domain = find_trust_from_name_noinit(request->domain_name);
51 : }
52 57 : if (domain == NULL) {
53 4 : tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN);
54 4 : return tevent_req_post(req, ev);
55 : }
56 53 : if (domain->internal) {
57 26 : const char *d = lp_dnsdomain();
58 26 : const char *n = lp_netbios_name();
59 :
60 : /*
61 : * Internal domains are passdb based, we can always
62 : * contact them.
63 : */
64 :
65 26 : if (d != NULL) {
66 0 : char *h;
67 26 : h = strlower_talloc(mem_ctx, n);
68 26 : if (tevent_req_nomem(h, req)) {
69 0 : return tevent_req_post(req, ev);
70 : }
71 :
72 26 : state->dcname = talloc_asprintf(state, "%s.%s", h, d);
73 26 : TALLOC_FREE(h);
74 :
75 26 : if (tevent_req_nomem(state->dcname, req)) {
76 0 : return tevent_req_post(req, ev);
77 : }
78 : } else {
79 0 : state->dcname = talloc_strdup(state, n);
80 0 : if (tevent_req_nomem(state->dcname, req)) {
81 0 : return tevent_req_post(req, ev);
82 : }
83 : }
84 :
85 26 : tevent_req_done(req);
86 26 : return tevent_req_post(req, ev);
87 : }
88 :
89 27 : subreq = dcerpc_wbint_PingDc_send(state, ev, dom_child_handle(domain),
90 27 : &state->dcname);
91 27 : if (tevent_req_nomem(subreq, req)) {
92 0 : return tevent_req_post(req, ev);
93 : }
94 27 : tevent_req_set_callback(subreq, winbindd_ping_dc_done, req);
95 27 : return req;
96 : }
97 :
98 27 : static void winbindd_ping_dc_done(struct tevent_req *subreq)
99 : {
100 27 : struct tevent_req *req = tevent_req_callback_data(
101 : subreq, struct tevent_req);
102 27 : struct winbindd_ping_dc_state *state = tevent_req_data(
103 : req, struct winbindd_ping_dc_state);
104 0 : NTSTATUS status, result;
105 :
106 27 : status = dcerpc_wbint_PingDc_recv(subreq, state, &result);
107 27 : state->result = result;
108 27 : if (any_nt_status_not_ok(status, result, &status)) {
109 4 : tevent_req_nterror(req, status);
110 4 : return;
111 : }
112 23 : tevent_req_done(req);
113 : }
114 :
115 57 : NTSTATUS winbindd_ping_dc_recv(struct tevent_req *req,
116 : struct winbindd_response *presp)
117 : {
118 57 : struct winbindd_ping_dc_state *state = tevent_req_data(
119 : req, struct winbindd_ping_dc_state);
120 0 : NTSTATUS status;
121 :
122 57 : if (tevent_req_is_nterror(req, &status)) {
123 8 : return status;
124 : }
125 :
126 49 : if (!NT_STATUS_IS_OK(state->result)) {
127 0 : set_auth_errors(presp, state->result);
128 : }
129 :
130 49 : if (state->dcname) {
131 49 : presp->extra_data.data = talloc_strdup(presp, state->dcname);
132 49 : if (presp->extra_data.data == NULL) {
133 0 : return NT_STATUS_NO_MEMORY;
134 : }
135 49 : presp->length += strlen((char *)presp->extra_data.data) + 1;
136 : }
137 :
138 49 : tevent_req_received(req);
139 49 : return NT_STATUS_OK;
140 : }
|