wbclient: Add an async winbind client library.
authorKai Blin <kai@samba.org>
Sat, 29 Mar 2008 00:42:06 +0000 (01:42 +0100)
committerKai Blin <kai@samba.org>
Wed, 2 Apr 2008 21:06:27 +0000 (23:06 +0200)
source/headermap.txt
source/libcli/config.mk
source/libcli/wbclient/config.mk [new file with mode: 0644]
source/libcli/wbclient/wbclient.c [new file with mode: 0644]
source/libcli/wbclient/wbclient.h [new file with mode: 0644]
source/librpc/idl/lsa.idl
source/librpc/idl/winbind.idl
source/rpc_server/config.mk
source/winbind/idmap.h
source/winbind/wb_irpc.c

index 8d4d78b..670b14c 100644 (file)
@@ -66,4 +66,8 @@ param/share.h: share.h
 lib/util/util_tdb.h: util_tdb.h
 lib/util/util_ldb.h: util_ldb.h
 lib/util/wrap_xattr.h: wrap_xattr.h
+lib/events/events.h: events/events.h
+lib/events/events_internal.h: events/events_internal.h
 libcli/ldap/ldap_ndr.h: ldap_ndr.h
+libcli/wbclient/wbclient.h: wbclient/wbclient.h
+lib/gencache/gencache.h: gencache.h
index b85fbe7..0c00fa2 100644 (file)
@@ -1,6 +1,7 @@
 mkinclude auth/config.mk
 mkinclude ldap/config.mk
 mkinclude security/config.mk
+mkinclude wbclient/config.mk
 
 [SUBSYSTEM::LIBSAMBA-ERRORS]
 OBJ_FILES = util/doserr.o \
diff --git a/source/libcli/wbclient/config.mk b/source/libcli/wbclient/config.mk
new file mode 100644 (file)
index 0000000..32f2f5a
--- /dev/null
@@ -0,0 +1,6 @@
+[SUBSYSTEM::LIBWBCLIENT]
+OBJ_FILES = wbclient.o
+PUBLIC_DEPENDENCIES = LIBSAMBA-ERRORS LIBEVENTS
+PRIVATE_DEPENDENCIES = NDR_WINBIND MESSAGING
+
+PUBLIC_HEADERS += libcli/wbclient/wbclient.h
diff --git a/source/libcli/wbclient/wbclient.c b/source/libcli/wbclient/wbclient.c
new file mode 100644 (file)
index 0000000..1b2d314
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Winbind client library.
+
+   Copyright (C) 2008 Kai Blin  <kai@samba.org>
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/wbclient/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)
+{
+       *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;
+       }
+       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;
+       }
+
+       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;
+
+       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_SIDS_TO_XIDS;
+       state->req->in.ids = ids;
+       state->ctx = ctx;
+
+       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;
+
+       composite_continue_irpc(ctx, state->irpc_req, sids_to_xids_recv_ids,
+                               state);
+       return ctx;
+}
+
+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);
+
+       state->ctx->status = irpc_call_recv(state->irpc_req);
+       if (!composite_is_ok(state->ctx)) return;
+
+       state->ids = state->req->out.ids;
+       composite_done(state->ctx);
+}
+
+NTSTATUS wbc_sids_to_xids_recv(struct composite_context *ctx,
+                              struct id_mapping **ids)
+{
+       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;
+       }
+
+       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;
+
+       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;
+
+       composite_continue_irpc(ctx, state->irpc_req, xids_to_sids_recv_ids,
+                       state);
+
+       return ctx;
+}
+
+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);
+
+       state->ctx->status = irpc_call_recv(state->irpc_req);
+       if (!composite_is_ok(state->ctx)) return;
+
+       state->ids = state->req->out.ids;
+       composite_done(state->ctx);
+}
+
+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;
+       }
+
+       return status;
+}
+
diff --git a/source/libcli/wbclient/wbclient.h b/source/libcli/wbclient/wbclient.h
new file mode 100644 (file)
index 0000000..099abaa
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Winbind client library.
+
+   Copyright (C) 2008 Kai Blin  <kai@samba.org>
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.
+*/
+#include "lib/messaging/irpc.h"
+#include "libcli/composite/composite.h"
+#include "librpc/gen_ndr/ndr_winbind.h"
+
+struct wbc_context {
+       struct messaging_context *msg_ctx;
+       struct event_context *event_ctx;
+       struct server_id *ids;
+};
+
+struct wbc_context *wbc_init(TALLOC_CTX *mem_ctx,
+                            struct messaging_context *msg_ctx,
+                            struct event_context *event_ctx);
+
+struct composite_context *wbc_sids_to_xids_send(struct wbc_context *wbc_ctx,
+                                               TALLOC_CTX *mem_ctx,
+                                               uint32_t count,
+                                               struct id_mapping *ids);
+
+NTSTATUS wbc_sids_to_xids_recv(struct composite_context *ctx,
+                              struct id_mapping **ids);
+
+struct composite_context *wbc_xids_to_sids_send(struct wbc_context *wbc_ctx,
+                                               TALLOC_CTX *mem_ctx,
+                                               uint32_t count,
+                                               struct id_mapping *ids);
+
+NTSTATUS wbc_xids_to_sids_recv(struct composite_context *ctx,
+                              struct id_mapping **ids);
+
index 6d15822..e36e79f 100644 (file)
@@ -338,7 +338,7 @@ import "misc.idl", "security.idl";
 
        /******************/
        /* Function: 0x0e */
-       typedef enum {
+       typedef [public] enum {
                SID_NAME_USE_NONE = 0,/* NOTUSED */
                SID_NAME_USER     = 1, /* user */
                SID_NAME_DOM_GRP  = 2, /* domain group */
index 29649c0..5cefb38 100644 (file)
@@ -3,8 +3,8 @@
 */
 
 #include "idl_types.h"
-  
-import "netlogon.idl";
+
+import "netlogon.idl", "lsa.idl", "security.idl";
 
 [
   uuid("245f3e6b-3c5d-6e21-3a2d-2a3d645b7221"),
@@ -16,6 +16,24 @@ interface winbind
        typedef [switch_type(uint16)] union netr_LogonLevel netr_LogonLevel;
        typedef [switch_type(uint16)] union netr_Validation netr_Validation;
 
+       typedef enum {
+               ID_TYPE_NOT_SPECIFIED,
+               ID_TYPE_UID,
+               ID_TYPE_GID,
+               ID_TYPE_BOTH
+       } id_type;
+
+       typedef struct {
+               uint32 id;
+               id_type type;
+       } unixid;
+
+       typedef struct {
+               unixid *unixid;
+               dom_sid *sid;
+               NTSTATUS status;
+       } id_mapping;
+
        /* a call to get runtime informations */
        void winbind_information(/* TODO */);
 
@@ -35,4 +53,16 @@ interface winbind
                [out] [switch_is(validation_level)] netr_Validation validation,
                [out] uint8 authoritative
        );
+
+       typedef [v1_enum] enum {
+               WINBIND_IDMAP_LEVEL_SIDS_TO_XIDS        = 1,
+               WINBIND_IDMAP_LEVEL_XIDS_TO_SIDS        = 2
+       } winbind_get_idmap_level;
+
+       NTSTATUS winbind_get_idmap(
+               [in]     winbind_get_idmap_level level,
+               [in]     uint32 count,
+               [in,out] [size_is(count)] id_mapping ids[]
+       );
+
 }
index 1d1c51c..d6d77dd 100644 (file)
@@ -82,7 +82,8 @@ PRIVATE_DEPENDENCIES = \
                DCERPC_COMMON \
                SAMDB \
                NDR_UNIXINFO \
-               NSS_WRAPPER
+               NSS_WRAPPER \
+               LIBWBCLIENT
 # End MODULE dcerpc_unixinfo
 ################################################
 
index 045d50c..6eae92c 100644 (file)
@@ -22,6 +22,8 @@
 #ifndef _IDMAP_H_
 #define _IDMAP_H_
 
+#include "librpc/gen_ndr/winbind.h"
+
 struct idmap_context {
        struct loadparm_context *lp_ctx;
        struct ldb_context *ldb_ctx;
@@ -29,24 +31,6 @@ struct idmap_context {
        struct dom_sid *unix_users_sid;
 };
 
-enum id_type {
-        ID_TYPE_NOT_SPECIFIED = 0,
-        ID_TYPE_UID,
-        ID_TYPE_GID,
-       ID_TYPE_BOTH
-};
-
-struct unixid {
-        uint32_t id;
-        enum id_type type;
-};
-
-struct id_mapping {
-       struct unixid *unixid;
-       struct dom_sid *sid;
-       NTSTATUS status;
-};
-
 #include "winbind/idmap_proto.h"
 
 #endif
index 5d7f7fd..0535045 100644 (file)
@@ -22,6 +22,7 @@
 #include "winbind/wb_server.h"
 #include "lib/messaging/irpc.h"
 #include "libcli/composite/composite.h"
+#include "libcli/security/proto.h"
 #include "librpc/gen_ndr/ndr_winbind.h"
 #include "smbd/service_task.h"
 
@@ -71,6 +72,71 @@ static void wb_irpc_SamLogon_callback(struct composite_context *ctx)
        irpc_send_reply(s->msg, status);
 }
 
+struct wb_irpc_get_idmap_state {
+       struct irpc_message *msg;
+       struct winbind_get_idmap *req;
+       int level;
+};
+
+static void wb_irpc_get_idmap_callback(struct composite_context *ctx);
+
+static NTSTATUS wb_irpc_get_idmap(struct irpc_message *msg,
+                                 struct winbind_get_idmap *req)
+{
+       struct wbsrv_service *service = talloc_get_type(msg->private,
+                                       struct wbsrv_service);
+       struct wb_irpc_get_idmap_state *s;
+       struct composite_context *ctx;
+
+       DEBUG(5, ("wb_irpc_get_idmap called\n"));
+
+       s = talloc(msg, struct wb_irpc_get_idmap_state);
+       NT_STATUS_HAVE_NO_MEMORY(s);
+
+       s->msg = msg;
+       s->req = req;
+       s->level = req->in.level;
+
+       switch(s->level) {
+               case WINBIND_IDMAP_LEVEL_SIDS_TO_XIDS:
+                       ctx = wb_sids2xids_send(msg, service, req->in.count,
+                                               req->in.ids);
+                       break;
+               case WINBIND_IDMAP_LEVEL_XIDS_TO_SIDS:
+                       ctx = wb_xids2sids_send(msg, service, req->in.count,
+                                               req->in.ids);
+                       break;
+       }
+       NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+       composite_continue(ctx, ctx, wb_irpc_get_idmap_callback, s);
+       msg->defer_reply = true;
+
+       return NT_STATUS_OK;
+}
+
+static void wb_irpc_get_idmap_callback(struct composite_context *ctx)
+{
+       struct wb_irpc_get_idmap_state *s;
+       NTSTATUS status;
+
+       DEBUG(5, ("wb_irpc_get_idmap_callback called\n"));
+
+       s = talloc_get_type(ctx->async.private_data,
+                           struct wb_irpc_get_idmap_state);
+
+       switch(s->level) {
+               case WINBIND_IDMAP_LEVEL_SIDS_TO_XIDS:
+                       status = wb_sids2xids_recv(ctx, &s->req->out.ids);
+                       break;
+               case WINBIND_IDMAP_LEVEL_XIDS_TO_SIDS:
+                       status = wb_xids2sids_recv(ctx, &s->req->out.ids);
+                       break;
+       }
+
+       irpc_send_reply(s->msg, status);
+}
+
 NTSTATUS wbsrv_init_irpc(struct wbsrv_service *service)
 {
        NTSTATUS status;
@@ -81,5 +147,9 @@ NTSTATUS wbsrv_init_irpc(struct wbsrv_service *service)
                               wb_irpc_SamLogon, service);
        NT_STATUS_NOT_OK_RETURN(status);
 
+       status = IRPC_REGISTER(service->task->msg_ctx, winbind, WINBIND_GET_IDMAP,
+                              wb_irpc_get_idmap, service);
+       NT_STATUS_NOT_OK_RETURN(status);
+
        return NT_STATUS_OK;
 }