summaryrefslogtreecommitdiff
path: root/source3/winbindd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/winbindd')
-rw-r--r--source3/winbindd/winbindd_dual.c184
-rw-r--r--source3/winbindd/winbindd_proto.h6
2 files changed, 190 insertions, 0 deletions
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 53a5bc47a4..1a0d0688ae 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -190,6 +190,190 @@ int wb_child_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
return 0;
}
+struct wb_domain_request_state {
+ struct tevent_context *ev;
+ struct winbindd_domain *domain;
+ struct winbindd_request *request;
+ struct winbindd_request *init_req;
+ struct winbindd_response *response;
+};
+
+static void wb_domain_request_gotdc(struct tevent_req *subreq);
+static void wb_domain_request_initialized(struct tevent_req *subreq);
+static void wb_domain_request_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_domain *domain,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_domain_request_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct wb_domain_request_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ if (domain->initialized) {
+ subreq = wb_child_request_send(state, ev, &domain->child,
+ request);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_domain_request_done, req);
+ return req;
+ }
+
+ state->domain = domain;
+ state->ev = ev;
+ state->request = request;
+
+ state->init_req = talloc_zero(state, struct winbindd_request);
+ if (tevent_req_nomem(state->init_req, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ if (IS_DC || domain->primary || domain->internal) {
+ /* The primary domain has to find the DC name itself */
+ state->init_req->cmd = WINBINDD_INIT_CONNECTION;
+ fstrcpy(state->init_req->domain_name, domain->name);
+ state->init_req->data.init_conn.is_primary =
+ domain->primary ? true : false;
+ fstrcpy(state->init_req->data.init_conn.dcname, "");
+
+ subreq = wb_child_request_send(state, ev, &domain->child,
+ state->init_req);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_domain_request_initialized,
+ req);
+ return req;
+ }
+
+ /*
+ * Ask our DC for a DC name
+ */
+ domain = find_our_domain();
+
+ /* This is *not* the primary domain, let's ask our DC about a DC
+ * name */
+
+ state->init_req->cmd = WINBINDD_GETDCNAME;
+ fstrcpy(state->init_req->domain_name, domain->name);
+
+ subreq = wb_child_request_send(state, ev, &domain->child, request);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_domain_request_gotdc, req);
+ return req;
+}
+
+static void wb_domain_request_gotdc(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_domain_request_state *state = tevent_req_data(
+ req, struct wb_domain_request_state);
+ struct winbindd_response *response;
+ int ret, err;
+
+ ret = wb_child_request_recv(subreq, talloc_tos(), &response, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+ state->init_req->cmd = WINBINDD_INIT_CONNECTION;
+ fstrcpy(state->init_req->domain_name, state->domain->name);
+ state->init_req->data.init_conn.is_primary = False;
+ fstrcpy(state->init_req->data.init_conn.dcname,
+ response->data.dc_name);
+
+ TALLOC_FREE(response);
+
+ subreq = wb_child_request_send(state, state->ev, &state->domain->child,
+ state->init_req);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_domain_request_initialized, req);
+}
+
+static void wb_domain_request_initialized(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_domain_request_state *state = tevent_req_data(
+ req, struct wb_domain_request_state);
+ struct winbindd_response *response;
+ int ret, err;
+
+ ret = wb_child_request_recv(subreq, talloc_tos(), &response, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+
+ if (!string_to_sid(&state->domain->sid,
+ response->data.domain_info.sid)) {
+ DEBUG(1,("init_child_recv: Could not convert sid %s "
+ "from string\n", response->data.domain_info.sid));
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+ fstrcpy(state->domain->name, response->data.domain_info.name);
+ fstrcpy(state->domain->alt_name, response->data.domain_info.alt_name);
+ state->domain->native_mode = response->data.domain_info.native_mode;
+ state->domain->active_directory =
+ response->data.domain_info.active_directory;
+ state->domain->initialized = true;
+
+ TALLOC_FREE(response);
+
+ subreq = wb_child_request_send(state, state->ev, &state->domain->child,
+ state->request);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_domain_request_done, req);
+}
+
+static void wb_domain_request_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_domain_request_state *state = tevent_req_data(
+ req, struct wb_domain_request_state);
+ int ret, err;
+
+ ret = wb_child_request_recv(subreq, talloc_tos(), &state->response,
+ &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+int wb_domain_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_response **presponse, int *err)
+{
+ struct wb_domain_request_state *state = tevent_req_data(
+ req, struct wb_domain_request_state);
+
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
+ }
+ *presponse = talloc_move(mem_ctx, &state->response);
+ return 0;
+}
+
/*
* Machinery for async requests sent to children. You set up a
* winbindd_request, select a child to query, and issue a async_request
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index 8380e40cb1..a44f7b6d73 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -271,6 +271,12 @@ struct tevent_req *wb_child_request_send(TALLOC_CTX *mem_ctx,
struct winbindd_request *request);
int wb_child_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
struct winbindd_response **presponse, int *err);
+struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_domain *domain,
+ struct winbindd_request *request);
+int wb_domain_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_response **presponse, int *err);
void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
struct winbindd_request *request,