*/
#include "includes.h"
+#include <tevent.h>
+#include "nsswitch/winbind_client.h"
#include "libcli/wbclient/wbclient.h"
+#include "libcli/security/dom_sid.h"
+#include "nsswitch/libwbclient/wbclient.h"
-/**
- * Get the server_id of the winbind task.
- *
- * \param[in] msg_ctx message context to use
- * \param[in] mem_ctx talloc context to use
- * \param[out] ids array of server_id structs containing the winbind id
- * \return NT_STATUS_OK on success, NT_STATUS_INTERNAL_ERROR on failure
- */
-static NTSTATUS get_server_id(struct messaging_context *msg_ctx,
- TALLOC_CTX *mem_ctx, struct server_id **ids)
+NTSTATUS wbc_sids_to_xids(struct id_map *ids, uint32_t count)
{
- *ids = irpc_servers_byname(msg_ctx, mem_ctx, "winbind_server");
- if (*ids == NULL || (*ids)[0].id == 0) {
- DEBUG(0, ("Geting the winbind server ID failed.\n"));
- return NT_STATUS_INTERNAL_ERROR;
+ TALLOC_CTX *mem_ctx;
+ uint32_t i;
+ struct wbcDomainSid *sids;
+ struct wbcUnixId *xids;
+ wbcErr result;
+ bool wb_off;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
- return NT_STATUS_OK;
-}
-
-/**
- * Initialize the wbclient context, talloc_free() when done.
- *
- * \param mem_ctx talloc context to allocate memory from
- * \param msg_ctx message context to use
- * \param
- */
-struct wbc_context *wbc_init(TALLOC_CTX *mem_ctx,
- struct messaging_context *msg_ctx,
- struct event_context *event_ctx)
-{
- struct wbc_context *ctx;
- NTSTATUS status;
-
- ctx = talloc(mem_ctx, struct wbc_context);
- if (ctx == NULL) return NULL;
- status = get_server_id(msg_ctx, mem_ctx, &ctx->ids);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(ctx);
- return NULL;
+ sids = talloc_array(mem_ctx, struct wbcDomainSid, count);
+ if (sids == NULL) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
}
- ctx->msg_ctx = msg_ctx;
- ctx->event_ctx = event_ctx;
-
- return ctx;
-}
-
-struct wbc_idmap_state {
- struct composite_context *ctx;
- struct winbind_get_idmap *req;
- struct irpc_request *irpc_req;
- struct id_mapping *ids;
-};
-
-static void sids_to_xids_recv_ids(struct irpc_request *req);
-
-struct composite_context *wbc_sids_to_xids_send(struct wbc_context *wbc_ctx,
- TALLOC_CTX *mem_ctx,
- uint32_t count,
- struct id_mapping *ids)
-{
- struct composite_context *ctx;
- struct wbc_idmap_state *state;
-
- DEBUG(5, ("wbc_sids_to_xids called\n"));
-
- ctx = composite_create(mem_ctx, wbc_ctx->event_ctx);
- if (ctx == NULL) return NULL;
+ xids = talloc_array(mem_ctx, struct wbcUnixId, count);
+ if (xids == NULL) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
- state = talloc(ctx, struct wbc_idmap_state);
- if (composite_nomem(state, ctx)) return ctx;
- ctx->private_data = state;
+ for (i=0; i<count; i++) {
+ memcpy(&sids[i], ids[i].sid, sizeof(struct dom_sid));
+ }
- state->req = talloc(state, struct winbind_get_idmap);
- if (composite_nomem(state->req, ctx)) return ctx;
+ wb_off = winbind_env_set();
+ if (wb_off) {
+ (void)winbind_on();
+ }
- state->req->in.count = count;
- state->req->in.level = WINBIND_IDMAP_LEVEL_SIDS_TO_XIDS;
- state->req->in.ids = ids;
- state->ctx = ctx;
+ result = wbcSidsToUnixIds(sids, count, xids);
- state->irpc_req = IRPC_CALL_SEND(wbc_ctx->msg_ctx, wbc_ctx->ids[0],
- winbind, WINBIND_GET_IDMAP, state->req,
- state);
- if (composite_nomem(state->irpc_req, ctx)) return ctx;
+ if (wb_off) {
+ (void)winbind_off();
+ }
- composite_continue_irpc(ctx, state->irpc_req, sids_to_xids_recv_ids,
- state);
- return ctx;
-}
+ if (!WBC_ERROR_IS_OK(result)) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
-static void sids_to_xids_recv_ids(struct irpc_request *req)
-{
- struct wbc_idmap_state *state = talloc_get_type_abort(
- req->async.private,
- struct wbc_idmap_state);
+ for (i=0; i<count; i++) {
+ struct wbcUnixId *xid = &xids[i];
+ struct unixid *id = &ids[i].xid;
+
+ switch (xid->type) {
+ case WBC_ID_TYPE_UID:
+ id->type = ID_TYPE_UID;
+ id->id = xid->id.uid;
+ break;
+ case WBC_ID_TYPE_GID:
+ id->type = ID_TYPE_GID;
+ id->id = xid->id.gid;
+ break;
+ case WBC_ID_TYPE_BOTH:
+ id->type = ID_TYPE_BOTH;
+ id->id = xid->id.uid;
+ break;
+ case WBC_ID_TYPE_NOT_SPECIFIED:
+ id->type = ID_TYPE_NOT_SPECIFIED;
+ id->id = UINT32_MAX;
+ break;
+ }
+ ids[i].status = ID_MAPPED;
+ }
- state->ctx->status = irpc_call_recv(state->irpc_req);
- if (!composite_is_ok(state->ctx)) return;
+ TALLOC_FREE(mem_ctx);
- state->ids = state->req->out.ids;
- composite_done(state->ctx);
+ return NT_STATUS_OK;
}
-NTSTATUS wbc_sids_to_xids_recv(struct composite_context *ctx,
- struct id_mapping **ids)
+NTSTATUS wbc_xids_to_sids(struct tevent_context *ev, struct id_map *ids,
+ uint32_t count)
{
- NTSTATUS status = composite_wait(ctx);
- DEBUG(5, ("wbc_sids_to_xids_recv called\n"));
- if (NT_STATUS_IS_OK(status)) {
- struct wbc_idmap_state *state = talloc_get_type_abort(
- ctx->private_data,
- struct wbc_idmap_state);
- *ids = state->ids;
+ TALLOC_CTX *mem_ctx;
+ uint32_t i;
+ struct wbcDomainSid *sids;
+ struct wbcUnixId *xids;
+ wbcErr result;
+ bool wb_off;
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
- return status;
-}
-
-static void xids_to_sids_recv_ids(struct irpc_request *req);
-
-struct composite_context *wbc_xids_to_sids_send(struct wbc_context *wbc_ctx,
- TALLOC_CTX *mem_ctx,
- uint32_t count,
- struct id_mapping *ids)
-{
- struct composite_context *ctx;
- struct wbc_idmap_state *state;
-
- DEBUG(5, ("wbc_xids_to_sids called\n"));
-
- ctx = composite_create(mem_ctx, wbc_ctx->event_ctx);
- if (ctx == NULL) return NULL;
-
- state = talloc(ctx, struct wbc_idmap_state);
- if (composite_nomem(state, ctx)) return ctx;
- ctx->private_data = state;
-
- state->req = talloc(state, struct winbind_get_idmap);
- if (composite_nomem(state->req, ctx)) return ctx;
-
- state->req->in.count = count;
- state->req->in.level = WINBIND_IDMAP_LEVEL_XIDS_TO_SIDS;
- state->req->in.ids = ids;
- state->ctx = ctx;
+ sids = talloc_array(mem_ctx, struct wbcDomainSid, count);
+ if (sids == NULL) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
- state->irpc_req = IRPC_CALL_SEND(wbc_ctx->msg_ctx, wbc_ctx->ids[0],
- winbind, WINBIND_GET_IDMAP, state->req,
- state);
- if (composite_nomem(state->irpc_req, ctx)) return ctx;
+ xids = talloc_array(mem_ctx, struct wbcUnixId, count);
+ if (xids == NULL) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
- composite_continue_irpc(ctx, state->irpc_req, xids_to_sids_recv_ids,
- state);
+ for (i=0; i<count; i++) {
+ struct id_map *id = &ids[i];
+ struct wbcUnixId *xid = &xids[i];
+
+ switch (id->xid.type) {
+ case ID_TYPE_UID:
+ *xid = (struct wbcUnixId) {
+ .type = WBC_ID_TYPE_UID,
+ .id.uid = id->xid.id
+ };
+ break;
+ case ID_TYPE_GID:
+ *xid = (struct wbcUnixId) {
+ .type = WBC_ID_TYPE_GID,
+ .id.uid = id->xid.id
+ };
+ break;
+ default:
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NOT_FOUND;
+ }
+ }
- return ctx;
-}
+ wb_off = winbind_env_set();
+ if (wb_off) {
+ (void)winbind_on();
+ }
-static void xids_to_sids_recv_ids(struct irpc_request *req)
-{
- struct wbc_idmap_state *state = talloc_get_type_abort(
- req->async.private,
- struct wbc_idmap_state);
+ result = wbcUnixIdsToSids(xids, count, sids);
- state->ctx->status = irpc_call_recv(state->irpc_req);
- if (!composite_is_ok(state->ctx)) return;
+ if (wb_off) {
+ (void)winbind_off();
+ }
- state->ids = state->req->out.ids;
- composite_done(state->ctx);
-}
+ if (!WBC_ERROR_IS_OK(result)) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
-NTSTATUS wbc_xids_to_sids_recv(struct composite_context *ctx,
- struct id_mapping **ids)
-{
- NTSTATUS status = composite_wait(ctx);
- DEBUG(5, ("wbc_xids_to_sids_recv called\n"));
- if (NT_STATUS_IS_OK(status)) {
- struct wbc_idmap_state *state = talloc_get_type_abort(
- ctx->private_data,
- struct wbc_idmap_state);
- *ids = state->ids;
+ for (i=0; i<count; i++) {
+ struct wbcDomainSid *sid = &sids[i];
+ struct wbcDomainSid null_sid = { 0 };
+ struct id_map *id = &ids[i];
+
+ if (memcmp(sid, &null_sid, sizeof(*sid)) != 0) {
+ struct dom_sid domsid;
+ id->status = ID_MAPPED;
+
+ memcpy(&domsid, sid, sizeof(struct dom_sid));
+ id->sid = dom_sid_dup(ids, &domsid);
+ if (id->sid == NULL) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ } else {
+ id->status = ID_UNMAPPED;
+ id->sid = NULL;
+ }
}
- return status;
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_OK;
}
-