This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
a composite API for finding a DC and its name
#include "libcli/composite/composite.h"
#include "winbind/wb_async_helpers.h"
-#include "librpc/gen_ndr/nbt.h"
-#include "librpc/gen_ndr/samr.h"
#include "lib/messaging/irpc.h"
#include "librpc/gen_ndr/irpc.h"
-#include "librpc/gen_ndr/ndr_irpc.h"
-
-struct finddcs_state {
- struct wb_finddcs *io;
- struct composite_context *creq;
-
- struct nbtd_getdcname *r;
- struct irpc_request *ireq;
+#include "auth/credentials/credentials.h"
+#include "libcli/security/security.h"
+#include "libcli/auth/libcli_auth.h"
+#include "librpc/gen_ndr/ndr_netlogon_c.h"
+#include "librpc/gen_ndr/ndr_lsa_c.h"
+#include "librpc/gen_ndr/ndr_samr_c.h"
+
+#include "winbind/wb_helper.h"
+
+struct lsa_lookupsids_state {
+ struct composite_context *ctx;
+ int num_sids;
+ struct lsa_LookupSids r;
+ struct lsa_SidArray sids;
+ struct lsa_TransNameArray names;
+ uint32_t count;
+ struct wb_sid_object **result;
};
-static void finddcs_getdc(struct irpc_request *ireq)
+static void lsa_lookupsids_recv_names(struct rpc_request *req);
+
+struct composite_context *wb_lsa_lookupsids_send(TALLOC_CTX *mem_ctx,
+ struct dcerpc_pipe *lsa_pipe,
+ struct policy_handle *handle,
+ int num_sids,
+ const struct dom_sid **sids)
{
- struct composite_context *c = talloc_get_type(ireq->async.private,
- struct composite_context);
- struct finddcs_state *state = talloc_get_type(c->private_data,
- struct finddcs_state);
+ struct composite_context *result;
+ struct rpc_request *req;
+ struct lsa_lookupsids_state *state;
+ int i;
- c->status = irpc_call_recv(ireq);
- if (!NT_STATUS_IS_OK(c->status)) {
- goto done;
- }
+ result = composite_create(mem_ctx, lsa_pipe->conn->event_ctx);
+ if (result == NULL) goto failed;
- state->io->out.dcs[0].name = talloc_steal(state->io->out.dcs,
- state->r->out.dcname);
+ state = talloc(result, struct lsa_lookupsids_state);
+ if (state == NULL) goto failed;
+ result->private_data = state;
+ state->ctx = result;
- c->status = NT_STATUS_OK;
- c->state = COMPOSITE_STATE_DONE;
+ state->sids.num_sids = num_sids;
+ state->sids.sids = talloc_array(state, struct lsa_SidPtr, num_sids);
+ if (state->sids.sids == NULL) goto failed;
- done:
- if (!NT_STATUS_IS_OK(c->status)) {
- c->state = COMPOSITE_STATE_ERROR;
- }
-
- if (c->state >= COMPOSITE_STATE_DONE &&
- c->async.fn) {
- c->async.fn(c);
+ for (i=0; i<num_sids; i++) {
+ state->sids.sids[i].sid = dom_sid_dup(state->sids.sids,
+ sids[i]);
+ if (state->sids.sids[i].sid == NULL) goto failed;
}
- talloc_free(ireq);
+
+ state->count = 0;
+ state->num_sids = num_sids;
+ state->names.count = 0;
+ state->names.names = NULL;
+
+ state->r.in.handle = handle;
+ state->r.in.sids = &state->sids;
+ state->r.in.names = &state->names;
+ state->r.in.level = 1;
+ state->r.in.count = &state->count;
+ state->r.out.names = &state->names;
+ state->r.out.count = &state->count;
+
+ req = dcerpc_lsa_LookupSids_send(lsa_pipe, state, &state->r);
+ if (req == NULL) goto failed;
+
+ req->async.callback = lsa_lookupsids_recv_names;
+ req->async.private_data = state;
+ return result;
+
+ failed:
+ talloc_free(result);
+ return NULL;
}
-/*
- called when name resolution is finished
-*/
-static void finddcs_resolve(struct composite_context *res_ctx)
+static void lsa_lookupsids_recv_names(struct rpc_request *req)
{
- struct composite_context *c = talloc_get_type(res_ctx->async.private_data,
- struct composite_context);
- struct finddcs_state *state = talloc_get_type(c->private_data,
- struct finddcs_state);
- uint32_t *nbt_servers;
-
- state->io->out.num_dcs = 1;
- state->io->out.dcs = talloc_array(state, struct nbt_dc_name,
- state->io->out.num_dcs);
- if (state->io->out.dcs == NULL) {
- c->status = NT_STATUS_NO_MEMORY;
- goto done;
+ struct lsa_lookupsids_state *state =
+ talloc_get_type(req->async.private_data,
+ struct lsa_lookupsids_state);
+ int i;
+
+ state->ctx->status = dcerpc_ndr_request_recv(req);
+ if (!composite_is_ok(state->ctx)) return;
+ state->ctx->status = state->r.out.result;
+ if (!NT_STATUS_IS_OK(state->ctx->status) &&
+ !NT_STATUS_EQUAL(state->ctx->status, STATUS_SOME_UNMAPPED)) {
+ composite_error(state->ctx, state->ctx->status);
+ return;
}
- c->status = resolve_name_recv(res_ctx, state->io->out.dcs,
- &state->io->out.dcs[0].address);
- if (!NT_STATUS_IS_OK(c->status)) {
- goto done;
+ state->result = talloc_array(state, struct wb_sid_object *,
+ state->num_sids);
+ if (composite_nomem(state->result, state->ctx)) return;
+
+ for (i=0; i<state->num_sids; i++) {
+ struct lsa_TranslatedName *name =
+ &state->r.out.names->names[i];
+ struct lsa_DomainInfo *dom;
+
+ state->result[i] = talloc_zero(state->result,
+ struct wb_sid_object);
+ if (composite_nomem(state->result[i], state->ctx)) return;
+
+ state->result[i]->type = name->sid_type;
+ if (state->result[i]->type == SID_NAME_UNKNOWN) {
+ continue;
+ }
+
+ if (name->sid_index >= state->r.out.domains->count) {
+ composite_error(state->ctx,
+ NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ dom = &state->r.out.domains->domains[name->sid_index];
+ state->result[i]->domain = talloc_reference(state->result[i],
+ dom->name.string);
+ if ((name->sid_type == SID_NAME_DOMAIN) ||
+ (name->name.string == NULL)) {
+ state->result[i]->name =
+ talloc_strdup(state->result[i], "");
+ } else {
+ state->result[i]->name =
+ talloc_steal(state->result[i],
+ name->name.string);
+ }
+
+ if (composite_nomem(state->result[i]->name, state->ctx)) {
+ return;
+ }
}
- nbt_servers = irpc_servers_byname(state->io->in.msg_ctx, "nbt_server");
- if ((nbt_servers == NULL) || (nbt_servers[0] == 0)) {
- c->status = NT_STATUS_NO_LOGON_SERVERS;
- goto done;
- }
+ composite_done(state->ctx);
+}
- state->r = talloc(state, struct nbtd_getdcname);
- if (state->r == NULL) {
- c->status = NT_STATUS_NO_MEMORY;
- goto done;
+NTSTATUS wb_lsa_lookupsids_recv(struct composite_context *c,
+ TALLOC_CTX *mem_ctx,
+ struct wb_sid_object ***names)
+{
+ NTSTATUS status = composite_wait(c);
+ if (NT_STATUS_IS_OK(status)) {
+ struct lsa_lookupsids_state *state =
+ talloc_get_type(c->private_data,
+ struct lsa_lookupsids_state);
+ *names = talloc_steal(mem_ctx, state->result);
}
+ talloc_free(c);
+ return status;
+}
- state->r->in.domainname = talloc_strdup(state->r, lp_workgroup());
- state->r->in.ip_address = state->io->out.dcs[0].address;
- state->r->in.my_computername = lp_netbios_name();
- state->r->in.my_accountname = talloc_asprintf(state->r, "%s$",
- lp_netbios_name());
- state->r->in.account_control = ACB_WSTRUST;
- state->r->in.domain_sid = secrets_get_domain_sid(state->r,
- lp_workgroup());
-
- if ((state->r->in.domainname == NULL) ||
- (state->r->in.my_accountname == NULL)) {
- DEBUG(0, ("talloc failed\n"));
- c->status = NT_STATUS_NO_MEMORY;
- goto done;
- }
- if (state->r->in.domain_sid == NULL) {
- c->status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- goto done;
+
+struct lsa_lookupnames_state {
+ struct composite_context *ctx;
+ uint32_t num_names;
+ struct lsa_LookupNames r;
+ struct lsa_TransSidArray sids;
+ uint32_t count;
+ struct wb_sid_object **result;
+};
+
+static void lsa_lookupnames_recv_sids(struct rpc_request *req);
+
+struct composite_context *wb_lsa_lookupnames_send(TALLOC_CTX *mem_ctx,
+ struct dcerpc_pipe *lsa_pipe,
+ struct policy_handle *handle,
+ int num_names,
+ const char **names)
+{
+ struct composite_context *result;
+ struct rpc_request *req;
+ struct lsa_lookupnames_state *state;
+
+ struct lsa_String *lsa_names;
+ int i;
+
+ result = composite_create(mem_ctx, lsa_pipe->conn->event_ctx);
+ if (result == NULL) goto failed;
+
+ state = talloc(result, struct lsa_lookupnames_state);
+ if (state == NULL) goto failed;
+ result->private_data = state;
+ state->ctx = result;
+
+ state->sids.count = 0;
+ state->sids.sids = NULL;
+ state->num_names = num_names;
+ state->count = 0;
+
+ lsa_names = talloc_array(state, struct lsa_String, num_names);
+ if (lsa_names == NULL) goto failed;
+
+ for (i=0; i<num_names; i++) {
+ lsa_names[i].string = names[i];
}
- state->ireq = irpc_call_send(state->io->in.msg_ctx, nbt_servers[0],
- &dcerpc_table_irpc, DCERPC_NBTD_GETDCNAME,
- state->r, state);
-
- if (state->ireq == NULL) {
- c->status = NT_STATUS_NO_MEMORY;
- goto done;
+ state->r.in.handle = handle;
+ state->r.in.num_names = num_names;
+ state->r.in.names = lsa_names;
+ state->r.in.sids = &state->sids;
+ state->r.in.level = 1;
+ state->r.in.count = &state->count;
+ state->r.out.count = &state->count;
+ state->r.out.sids = &state->sids;
+
+ req = dcerpc_lsa_LookupNames_send(lsa_pipe, state, &state->r);
+ if (req == NULL) goto failed;
+
+ req->async.callback = lsa_lookupnames_recv_sids;
+ req->async.private_data = state;
+ return result;
+
+ failed:
+ talloc_free(result);
+ return NULL;
+}
+
+static void lsa_lookupnames_recv_sids(struct rpc_request *req)
+{
+ struct lsa_lookupnames_state *state =
+ talloc_get_type(req->async.private_data,
+ struct lsa_lookupnames_state);
+ int i;
+
+ state->ctx->status = dcerpc_ndr_request_recv(req);
+ if (!composite_is_ok(state->ctx)) return;
+ state->ctx->status = state->r.out.result;
+ if (!NT_STATUS_IS_OK(state->ctx->status) &&
+ !NT_STATUS_EQUAL(state->ctx->status, STATUS_SOME_UNMAPPED)) {
+ composite_error(state->ctx, state->ctx->status);
+ return;
}
- c->status = NT_STATUS_OK;
- state->ireq->async.fn = finddcs_getdc;
- state->ireq->async.private = c;
+ state->result = talloc_array(state, struct wb_sid_object *,
+ state->num_names);
+ if (composite_nomem(state->result, state->ctx)) return;
- done:
- if (!NT_STATUS_IS_OK(c->status)) {
- c->state = COMPOSITE_STATE_ERROR;
+ for (i=0; i<state->num_names; i++) {
+ struct lsa_TranslatedSid *sid = &state->r.out.sids->sids[i];
+ struct lsa_DomainInfo *dom;
+
+ state->result[i] = talloc_zero(state->result,
+ struct wb_sid_object);
+ if (composite_nomem(state->result[i], state->ctx)) return;
+
+ state->result[i]->type = sid->sid_type;
+ if (state->result[i]->type == SID_NAME_UNKNOWN) {
+ continue;
+ }
+
+ if (sid->sid_index >= state->r.out.domains->count) {
+ composite_error(state->ctx,
+ NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ dom = &state->r.out.domains->domains[sid->sid_index];
+
+ state->result[i]->sid = dom_sid_add_rid(state->result[i],
+ dom->sid, sid->rid);
}
-
- if (c->state >= COMPOSITE_STATE_DONE &&
- c->async.fn) {
- c->async.fn(c);
+
+ composite_done(state->ctx);
+}
+
+NTSTATUS wb_lsa_lookupnames_recv(struct composite_context *c,
+ TALLOC_CTX *mem_ctx,
+ struct wb_sid_object ***sids)
+{
+ NTSTATUS status = composite_wait(c);
+ if (NT_STATUS_IS_OK(status)) {
+ struct lsa_lookupnames_state *state =
+ talloc_get_type(c->private_data,
+ struct lsa_lookupnames_state);
+ *sids = talloc_steal(mem_ctx, state->result);
}
+ talloc_free(c);
+ return status;
}
-struct composite_context *wb_finddcs_send(struct wb_finddcs *io,
- struct event_context *event_ctx)
+
+#if 0
+
+struct cmd_checkmachacc_state {
+ struct composite_context *ctx;
+ struct wbsrv_call *call;
+ struct wbsrv_domain *domain;
+};
+
+static void cmd_checkmachacc_recv_init(struct composite_context *ctx);
+
+ struct composite_context *wb_cmd_checkmachacc_send(struct wbsrv_call *call)
{
- struct composite_context *c;
- struct finddcs_state *state;
- struct nbt_name name;
+ struct composite_context *result, *ctx;
+ struct cmd_checkmachacc_state *state;
+ struct wbsrv_service *service = call->wbconn->listen_socket->service;
- c = talloc_zero(NULL, struct composite_context);
- if (c == NULL) goto failed;
- c->state = COMPOSITE_STATE_IN_PROGRESS;
- c->event_ctx = event_ctx;
+ result = composite_create(mem_ctx, call->event_ctx;
+ if (result == NULL) goto failed;
- state = talloc(c, struct finddcs_state);
+ state = talloc(result, struct cmd_checkmachacc_state);
if (state == NULL) goto failed;
+ state->ctx = result;
+ result->private_data = state;
+ state->call = call;
- state->io = io;
+ state->domain = service->domains;
- make_nbt_name(&name, io->in.domain, 0x1c);
- state->creq = resolve_name_send(&name, c->event_ctx,
- lp_name_resolve_order());
+ ctx = wb_init_domain_send(service, state->domain);
+ if (ctx == NULL) goto failed;
+ ctx->async.fn = cmd_checkmachacc_recv_init;
+ ctx->async.private_data = state;
- if (state->creq == NULL) goto failed;
- state->creq->async.private_data = c;
- state->creq->async.fn = finddcs_resolve;
- c->private_data = state;
+ return result;
- return c;
-failed:
- talloc_free(c);
+ failed:
+ talloc_free(result);
return NULL;
}
-NTSTATUS wb_finddcs_recv(struct composite_context *c, TALLOC_CTX *mem_ctx)
+static void cmd_checkmachacc_recv_init(struct composite_context *ctx)
{
- NTSTATUS status;
+ struct cmd_checkmachacc_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct cmd_checkmachacc_state);
- status = composite_wait(c);
+ state->ctx->status = wb_init_domain_recv(ctx);
+ if (!composite_is_ok(state->ctx)) return;
- if (NT_STATUS_IS_OK(status)) {
- struct finddcs_state *state = talloc_get_type(c->private_data,
- struct finddcs_state);
- talloc_steal(mem_ctx, state->io->out.dcs);
- }
+ composite_done(state->ctx);
+}
+ NTSTATUS wb_cmd_checkmachacc_recv(struct composite_context *c)
+{
+ NTSTATUS status = composite_wait(c);
talloc_free(c);
return status;
}
-NTSTATUS wb_finddcs(struct wb_finddcs *io, TALLOC_CTX *mem_ctx,
- struct event_context *ev)
+ NTSTATUS wb_cmd_checkmachacc(struct wbsrv_call *call)
+{
+ struct composite_context *c = wb_cmd_checkmachacc_send(call);
+ return wb_cmd_checkmachacc_recv(c);
+}
+#endif
+
+struct samr_getuserdomgroups_state {
+ struct composite_context *ctx;
+ struct dcerpc_pipe *samr_pipe;
+
+ int num_rids;
+ uint32_t *rids;
+
+ struct policy_handle *user_handle;
+ struct samr_OpenUser o;
+ struct samr_GetGroupsForUser g;
+ struct samr_Close c;
+};
+
+static void samr_usergroups_recv_open(struct rpc_request *req);
+static void samr_usergroups_recv_groups(struct rpc_request *req);
+static void samr_usergroups_recv_close(struct rpc_request *req);
+
+struct composite_context *wb_samr_userdomgroups_send(TALLOC_CTX *mem_ctx,
+ struct dcerpc_pipe *samr_pipe,
+ struct policy_handle *domain_handle,
+ uint32_t rid)
+{
+ struct composite_context *result;
+ struct rpc_request *req;
+ struct samr_getuserdomgroups_state *state;
+
+ result = composite_create(mem_ctx, samr_pipe->conn->event_ctx);
+ if (result == NULL) goto failed;
+
+ state = talloc(result, struct samr_getuserdomgroups_state);
+ if (state == NULL) goto failed;
+ result->private_data = state;
+ state->ctx = result;
+
+ state->samr_pipe = samr_pipe;
+
+ state->user_handle = talloc(state, struct policy_handle);
+ if (state->user_handle == NULL) goto failed;
+
+ state->o.in.domain_handle = domain_handle;
+ state->o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ state->o.in.rid = rid;
+ state->o.out.user_handle = state->user_handle;
+
+ req = dcerpc_samr_OpenUser_send(state->samr_pipe, state, &state->o);
+ if (req == NULL) goto failed;
+
+ req->async.callback = samr_usergroups_recv_open;
+ req->async.private_data = state;
+ return result;
+
+ failed:
+ talloc_free(result);
+ return NULL;
+}
+
+static void samr_usergroups_recv_open(struct rpc_request *req)
+{
+ struct samr_getuserdomgroups_state *state =
+ talloc_get_type(req->async.private_data,
+ struct samr_getuserdomgroups_state);
+
+ state->ctx->status = dcerpc_ndr_request_recv(req);
+ if (!composite_is_ok(state->ctx)) return;
+ state->ctx->status = state->o.out.result;
+ if (!composite_is_ok(state->ctx)) return;
+
+ state->g.in.user_handle = state->user_handle;
+
+ req = dcerpc_samr_GetGroupsForUser_send(state->samr_pipe, state,
+ &state->g);
+ composite_continue_rpc(state->ctx, req, samr_usergroups_recv_groups,
+ state);
+}
+
+static void samr_usergroups_recv_groups(struct rpc_request *req)
{
- struct composite_context *c = wb_finddcs_send(io, ev);
- return wb_finddcs_recv(c, mem_ctx);
+ struct samr_getuserdomgroups_state *state =
+ talloc_get_type(req->async.private_data,
+ struct samr_getuserdomgroups_state);
+
+ state->ctx->status = dcerpc_ndr_request_recv(req);
+ if (!composite_is_ok(state->ctx)) return;
+ state->ctx->status = state->g.out.result;
+ if (!composite_is_ok(state->ctx)) return;
+
+ state->c.in.handle = state->user_handle;
+ state->c.out.handle = state->user_handle;
+
+ req = dcerpc_samr_Close_send(state->samr_pipe, state, &state->c);
+ composite_continue_rpc(state->ctx, req, samr_usergroups_recv_close,
+ state);
+}
+
+static void samr_usergroups_recv_close(struct rpc_request *req)
+{
+ struct samr_getuserdomgroups_state *state =
+ talloc_get_type(req->async.private_data,
+ struct samr_getuserdomgroups_state);
+
+ state->ctx->status = dcerpc_ndr_request_recv(req);
+ if (!composite_is_ok(state->ctx)) return;
+ state->ctx->status = state->c.out.result;
+ if (!composite_is_ok(state->ctx)) return;
+
+ composite_done(state->ctx);
+}
+
+NTSTATUS wb_samr_userdomgroups_recv(struct composite_context *ctx,
+ TALLOC_CTX *mem_ctx,
+ int *num_rids, uint32_t **rids)
+{
+ struct samr_getuserdomgroups_state *state =
+ talloc_get_type(ctx->private_data,
+ struct samr_getuserdomgroups_state);
+
+ int i;
+ NTSTATUS status = composite_wait(ctx);
+ if (!NT_STATUS_IS_OK(status)) goto done;
+
+ *num_rids = state->g.out.rids->count;
+ *rids = talloc_array(mem_ctx, uint32_t, *num_rids);
+ if (*rids == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (i=0; i<*num_rids; i++) {
+ (*rids)[i] = state->g.out.rids->rids[i].rid;
+ }
+
+ done:
+ talloc_free(ctx);
+ return status;
}