libwbclient: Separate out the async functions
authorKai Blin <kai@samba.org>
Sat, 13 Feb 2010 12:42:56 +0000 (13:42 +0100)
committerKai Blin <kai@samba.org>
Sat, 13 Feb 2010 13:30:36 +0000 (14:30 +0100)
nsswitch/libwbclient/config.mk
nsswitch/libwbclient/wbc_idmap.c
nsswitch/libwbclient/wbc_idmap_async.c [new file with mode: 0644]
nsswitch/libwbclient/wbc_pam.c
nsswitch/libwbclient/wbc_pam_async.c [new file with mode: 0644]
nsswitch/libwbclient/wbc_sid.c
nsswitch/libwbclient/wbc_sid_async.c [new file with mode: 0644]
nsswitch/libwbclient/wbc_util.c
nsswitch/libwbclient/wbc_util_async.c [new file with mode: 0644]
source3/Makefile.in
source4/torture/winbind/config.mk

index ffdab159f84669ad7e990b7eb05436ccc8c17259..1c7a4b349f39fb4afdff68d432982af3f04c9a7d 100644 (file)
@@ -1,15 +1,24 @@
 [SUBSYSTEM::LIBWBCLIENT]
-PUBLIC_DEPENDENCIES = LIBASYNC_REQ \
-                     LIBTEVENT \
-                     LIBTALLOC \
-                     UTIL_TEVENT
+PUBLIC_DEPENDENCIES = LIBTALLOC
 
-LIBWBCLIENT_OBJ_FILES = $(addprefix $(libwbclientsrcdir)/, wbc_async.o \
-                                                               wbc_guid.o \
+LIBWBCLIENT_OBJ_FILES = $(addprefix $(libwbclientsrcdir)/, wbc_guid.o \
                                                                wbc_idmap.o \
                                                                wbclient.o \
                                                                wbc_pam.o \
                                                                wbc_pwd.o \
                                                                wbc_sid.o \
-                                                               wbc_util.o \
+                                                               wbc_util.o )
+
+[SUBSYSTEM::LIBWBCLIENT_ASYNC]
+PUBLIC_DEPENDENCIES = LIBASYNC_REQ \
+                     LIBTEVENT \
+                     LIBTALLOC \
+                     UTIL_TEVENT \
+                     LIBWBCLIENT
+
+LIBWBCLIENT_ASYNC_OBJ_FILES = $(addprefix $(libwbclientsrcdir)/, wbc_async.o \
+                                                               wbc_idmap_async.o \
+                                                               wbc_pam_async.o \
+                                                               wbc_sid_async.o \
+                                                               wbc_util_async.o \
                                                                wb_reqtrans.o )
index e1bb6f2d594aa45f44eb7fd2291ebce5dd68f7a3..caa6a46417aff4c1e4e4e1fa04d4e5359fa60edb 100644 (file)
@@ -4,8 +4,6 @@
    Winbind client API
 
    Copyright (C) Gerald (Jerry) Carter 2007
-   Copyright (C) Kai Blin 2009
-
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
 #include "replace.h"
 #include "libwbclient.h"
 
-struct wbc_sid_to_uid_state {
-       struct winbindd_request req;
-       uid_t uid;
-};
-
-static void wbcSidToUid_done(struct tevent_req *subreq);
-
-/**
- * @brief Convert a Windows SID to a Unix uid, allocating an uid if needed
- *
- * @param mem_ctx      talloc context to allocate the request from
- * @param ev           tevent context to use for async operation
- * @param wb_ctx       winbind context to use
- * @param *sid         pointer to the domain SID to be resolved
- *
- * @return tevent_req on success, NULL on error
- */
-
-struct tevent_req *wbcSidToUid_send(TALLOC_CTX *mem_ctx,
-                                   struct tevent_context *ev,
-                                   struct wb_context *wb_ctx,
-                                   const struct wbcDomainSid *sid)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_sid_to_uid_state *state;
-       char *sid_string;
-       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_sid_to_uid_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-
-       state->req.cmd = WINBINDD_SID_TO_UID;
-       wbc_status = wbcSidToString(sid, &sid_string);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               return tevent_req_post(req, ev);
-       }
-       strncpy(state->req.data.sid, sid_string, sizeof(state->req.data.sid)-1);
-       wbcFreeMemory(sid_string);
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcSidToUid_done, req);
-       return req;
-}
-
-static void wbcSidToUid_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_sid_to_uid_state *state = tevent_req_data(
-                       req, struct wbc_sid_to_uid_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-       state->uid = resp->data.uid;
-       TALLOC_FREE(resp);
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive a Unix uid mapped to a Windows SID
- *
- * @param req          tevent_req containing the request
- * @param *puid                pointer to hold the resolved uid_t value
- *
- * @return #wbcErr
- */
-
-wbcErr wbcSidToUid_recv(struct tevent_req *req, uid_t *puid)
-{
-       struct wbc_sid_to_uid_state *state = tevent_req_data(
-                       req, struct wbc_sid_to_uid_state);
-       wbcErr wbc_status;
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       *puid = state->uid;
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
-
 /* Convert a Windows SID to a Unix uid, allocating an uid if needed */
 wbcErr wbcSidToUid(const struct wbcDomainSid *sid, uid_t *puid)
 {
@@ -171,116 +70,6 @@ wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid,
        return WBC_ERR_NOT_IMPLEMENTED;
 }
 
-struct wbc_uid_to_sid_state {
-       struct winbindd_request req;
-       struct wbcDomainSid *sid;
-};
-
-static void wbcUidToSid_done(struct tevent_req *subreq);
-
-/**
- * @brief Request a Windows SID for an Unix uid, allocating an SID if needed
- *
- * @param mem_ctx      talloc context to allocate the request from
- * @param ev           tevent context to use for async operation
- * @param wb_ctx       winbind context to use
- * @param uid          uid to be resolved to a SID
- *
- * @return tevent_req on success, NULL on error
- */
-
-struct tevent_req *wbcUidToSid_send(TALLOC_CTX *mem_ctx,
-                                   struct tevent_context *ev,
-                                   struct wb_context *wb_ctx,
-                                   uid_t uid)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_uid_to_sid_state *state;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_uid_to_sid_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-
-       state->req.cmd = WINBINDD_UID_TO_SID;
-       state->req.data.uid = uid;
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcUidToSid_done, req);
-       return req;
-}
-
-static void wbcUidToSid_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_uid_to_sid_state *state = tevent_req_data(
-                       req, struct wbc_uid_to_sid_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       state->sid = talloc(state, struct wbcDomainSid);
-       if (state->sid == NULL) {
-               TALLOC_FREE(resp);
-               tevent_req_error(req, WBC_ERR_NO_MEMORY);
-               return;
-       }
-
-       wbc_status = wbcStringToSid(resp->data.sid.sid, state->sid);
-       TALLOC_FREE(resp);
-
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive a Unix uid mapped to a Windows SID
- *
- * @param req          tevent_req containing the request
- * @param *psid                pointer to hold the resolved SID
- *
- * @return #wbcErr
- */
-
-wbcErr wbcUidToSid_recv(struct tevent_req *req, struct wbcDomainSid *psid)
-{
-       struct wbc_uid_to_sid_state *state = tevent_req_data(
-                       req, struct wbc_uid_to_sid_state);
-       wbcErr wbc_status;
-
-       if (psid == NULL) {
-               tevent_req_received(req);
-               return WBC_ERR_INVALID_PARAM;
-       }
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       memcpy(psid, state->sid, sizeof(struct wbcDomainSid));
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
-
 /* Convert a Unix uid to a Windows SID, allocating a SID if needed */
 wbcErr wbcUidToSid(uid_t uid, struct wbcDomainSid *sid)
 {
@@ -321,106 +110,6 @@ wbcErr wbcQueryUidToSid(uid_t uid,
        return WBC_ERR_NOT_IMPLEMENTED;
 }
 
-struct wbc_sid_to_gid_state {
-       struct winbindd_request req;
-       gid_t gid;
-};
-
-static void wbcSidToGid_done(struct tevent_req *subreq);
-
-/**
- * @brief Request to convert a Windows SID to a Unix gid,
- * allocating a gid if needed
- *
- * @param mem_ctx      talloc context to allocate the request from
- * @param ev           tevent context to use for async operation
- * @param wb_ctx       winbind context to use
- * @param *sid         pointer to the domain SID to be resolved
- *
- * @return tevent_req on success, NULL on error
- */
-
-struct tevent_req *wbcSidToGid_send(TALLOC_CTX *mem_ctx,
-                                   struct tevent_context *ev,
-                                   struct wb_context *wb_ctx,
-                                   const struct wbcDomainSid *sid)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_sid_to_gid_state *state;
-       char *sid_string;
-       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_sid_to_gid_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-
-       state->req.cmd = WINBINDD_SID_TO_GID;
-       wbc_status = wbcSidToString(sid, &sid_string);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               return tevent_req_post(req, ev);
-       }
-       strncpy(state->req.data.sid, sid_string, sizeof(state->req.data.sid)-1);
-       wbcFreeMemory(sid_string);
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcSidToGid_done, req);
-       return req;
-}
-
-static void wbcSidToGid_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_sid_to_gid_state *state = tevent_req_data(
-                       req, struct wbc_sid_to_gid_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-       state->gid = resp->data.gid;
-       TALLOC_FREE(resp);
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive a Unix gid mapped to a Windows SID
- *
- * @param req          tevent_req containing the request
- * @param *pgid                pointer to hold the resolved gid_t value
- *
- * @return #wbcErr
- */
-
-wbcErr wbcSidToGid_recv(struct tevent_req *req, gid_t *pgid)
-{
-       struct wbc_sid_to_gid_state *state = tevent_req_data(
-                       req, struct wbc_sid_to_gid_state);
-       wbcErr wbc_status;
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       *pgid = state->gid;
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
-
 /** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed
  *
  * @param *sid        Pointer to the domain SID to be resolved
@@ -477,116 +166,6 @@ wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid,
        return WBC_ERR_NOT_IMPLEMENTED;
 }
 
-struct wbc_gid_to_sid_state {
-       struct winbindd_request req;
-       struct wbcDomainSid *sid;
-};
-
-static void wbcGidToSid_done(struct tevent_req *subreq);
-
-/**
- * @brief Request a Windows SID for an Unix Gid, allocating an SID if needed
- *
- * @param mem_ctx      talloc context to allocate the request from
- * @param ev           tevent context to use for async operation
- * @param wb_ctx       winbind context to use
- * @param gid          gid to be resolved to a SID
- *
- * @return tevent_req on success, NULL on error
- */
-
-struct tevent_req *wbcGidToSid_send(TALLOC_CTX *mem_ctx,
-                                   struct tevent_context *ev,
-                                   struct wb_context *wb_ctx,
-                                   gid_t gid)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_gid_to_sid_state *state;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_gid_to_sid_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-
-       state->req.cmd = WINBINDD_GID_TO_SID;
-       state->req.data.gid = gid;
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcGidToSid_done, req);
-       return req;
-}
-
-static void wbcGidToSid_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_gid_to_sid_state *state = tevent_req_data(
-                       req, struct wbc_gid_to_sid_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       state->sid = talloc(state, struct wbcDomainSid);
-       if (state->sid == NULL) {
-               TALLOC_FREE(resp);
-               tevent_req_error(req, WBC_ERR_NO_MEMORY);
-               return;
-       }
-
-       wbc_status = wbcStringToSid(resp->data.sid.sid, state->sid);
-       TALLOC_FREE(resp);
-
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive a Unix gid mapped to a Windows SID
- *
- * @param req          tevent_req containing the request
- * @param *psid                pointer to hold the resolved SID
- *
- * @return #wbcErr
- */
-
-wbcErr wbcGidToSid_recv(struct tevent_req *req, struct wbcDomainSid *psid)
-{
-       struct wbc_gid_to_sid_state *state = tevent_req_data(
-                       req, struct wbc_gid_to_sid_state);
-       wbcErr wbc_status;
-
-       if (psid == NULL) {
-               tevent_req_received(req);
-               return WBC_ERR_INVALID_PARAM;
-       }
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       memcpy(psid, state->sid, sizeof(struct wbcDomainSid));
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
-
 
 /* Convert a Unix gid to a Windows SID, allocating a SID if needed */
 wbcErr wbcGidToSid(gid_t gid, struct wbcDomainSid *sid)
diff --git a/nsswitch/libwbclient/wbc_idmap_async.c b/nsswitch/libwbclient/wbc_idmap_async.c
new file mode 100644 (file)
index 0000000..4b84bb9
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Winbind client API
+
+   Copyright (C) 2009,2010 Kai Blin  <kai@samba.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* Required Headers */
+
+#include "replace.h"
+#include "libwbclient.h"
+
+struct wbc_sid_to_uid_state {
+       struct winbindd_request req;
+       uid_t uid;
+};
+
+static void wbcSidToUid_done(struct tevent_req *subreq);
+
+/**
+ * @brief Convert a Windows SID to a Unix uid, allocating an uid if needed
+ *
+ * @param mem_ctx      talloc context to allocate the request from
+ * @param ev           tevent context to use for async operation
+ * @param wb_ctx       winbind context to use
+ * @param *sid         pointer to the domain SID to be resolved
+ *
+ * @return tevent_req on success, NULL on error
+ */
+
+struct tevent_req *wbcSidToUid_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   struct wb_context *wb_ctx,
+                                   const struct wbcDomainSid *sid)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_sid_to_uid_state *state;
+       char *sid_string;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_sid_to_uid_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+
+       state->req.cmd = WINBINDD_SID_TO_UID;
+       wbc_status = wbcSidToString(sid, &sid_string);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return tevent_req_post(req, ev);
+       }
+       strncpy(state->req.data.sid, sid_string, sizeof(state->req.data.sid)-1);
+       wbcFreeMemory(sid_string);
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcSidToUid_done, req);
+       return req;
+}
+
+static void wbcSidToUid_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_sid_to_uid_state *state = tevent_req_data(
+                       req, struct wbc_sid_to_uid_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+       state->uid = resp->data.uid;
+       TALLOC_FREE(resp);
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive a Unix uid mapped to a Windows SID
+ *
+ * @param req          tevent_req containing the request
+ * @param *puid                pointer to hold the resolved uid_t value
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcSidToUid_recv(struct tevent_req *req, uid_t *puid)
+{
+       struct wbc_sid_to_uid_state *state = tevent_req_data(
+                       req, struct wbc_sid_to_uid_state);
+       wbcErr wbc_status;
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       *puid = state->uid;
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
+
+
+struct wbc_uid_to_sid_state {
+       struct winbindd_request req;
+       struct wbcDomainSid *sid;
+};
+
+static void wbcUidToSid_done(struct tevent_req *subreq);
+
+/**
+ * @brief Request a Windows SID for an Unix uid, allocating an SID if needed
+ *
+ * @param mem_ctx      talloc context to allocate the request from
+ * @param ev           tevent context to use for async operation
+ * @param wb_ctx       winbind context to use
+ * @param uid          uid to be resolved to a SID
+ *
+ * @return tevent_req on success, NULL on error
+ */
+
+struct tevent_req *wbcUidToSid_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   struct wb_context *wb_ctx,
+                                   uid_t uid)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_uid_to_sid_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_uid_to_sid_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+
+       state->req.cmd = WINBINDD_UID_TO_SID;
+       state->req.data.uid = uid;
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcUidToSid_done, req);
+       return req;
+}
+
+static void wbcUidToSid_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_uid_to_sid_state *state = tevent_req_data(
+                       req, struct wbc_uid_to_sid_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       state->sid = talloc(state, struct wbcDomainSid);
+       if (state->sid == NULL) {
+               TALLOC_FREE(resp);
+               tevent_req_error(req, WBC_ERR_NO_MEMORY);
+               return;
+       }
+
+       wbc_status = wbcStringToSid(resp->data.sid.sid, state->sid);
+       TALLOC_FREE(resp);
+
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive a Unix uid mapped to a Windows SID
+ *
+ * @param req          tevent_req containing the request
+ * @param *psid                pointer to hold the resolved SID
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcUidToSid_recv(struct tevent_req *req, struct wbcDomainSid *psid)
+{
+       struct wbc_uid_to_sid_state *state = tevent_req_data(
+                       req, struct wbc_uid_to_sid_state);
+       wbcErr wbc_status;
+
+       if (psid == NULL) {
+               tevent_req_received(req);
+               return WBC_ERR_INVALID_PARAM;
+       }
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       memcpy(psid, state->sid, sizeof(struct wbcDomainSid));
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
+
+
+struct wbc_sid_to_gid_state {
+       struct winbindd_request req;
+       gid_t gid;
+};
+
+static void wbcSidToGid_done(struct tevent_req *subreq);
+
+/**
+ * @brief Request to convert a Windows SID to a Unix gid,
+ * allocating a gid if needed
+ *
+ * @param mem_ctx      talloc context to allocate the request from
+ * @param ev           tevent context to use for async operation
+ * @param wb_ctx       winbind context to use
+ * @param *sid         pointer to the domain SID to be resolved
+ *
+ * @return tevent_req on success, NULL on error
+ */
+
+struct tevent_req *wbcSidToGid_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   struct wb_context *wb_ctx,
+                                   const struct wbcDomainSid *sid)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_sid_to_gid_state *state;
+       char *sid_string;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_sid_to_gid_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+
+       state->req.cmd = WINBINDD_SID_TO_GID;
+       wbc_status = wbcSidToString(sid, &sid_string);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               return tevent_req_post(req, ev);
+       }
+       strncpy(state->req.data.sid, sid_string, sizeof(state->req.data.sid)-1);
+       wbcFreeMemory(sid_string);
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcSidToGid_done, req);
+       return req;
+}
+
+static void wbcSidToGid_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_sid_to_gid_state *state = tevent_req_data(
+                       req, struct wbc_sid_to_gid_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+       state->gid = resp->data.gid;
+       TALLOC_FREE(resp);
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive a Unix gid mapped to a Windows SID
+ *
+ * @param req          tevent_req containing the request
+ * @param *pgid                pointer to hold the resolved gid_t value
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcSidToGid_recv(struct tevent_req *req, gid_t *pgid)
+{
+       struct wbc_sid_to_gid_state *state = tevent_req_data(
+                       req, struct wbc_sid_to_gid_state);
+       wbcErr wbc_status;
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       *pgid = state->gid;
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
+
+
+struct wbc_gid_to_sid_state {
+       struct winbindd_request req;
+       struct wbcDomainSid *sid;
+};
+
+static void wbcGidToSid_done(struct tevent_req *subreq);
+
+/**
+ * @brief Request a Windows SID for an Unix Gid, allocating an SID if needed
+ *
+ * @param mem_ctx      talloc context to allocate the request from
+ * @param ev           tevent context to use for async operation
+ * @param wb_ctx       winbind context to use
+ * @param gid          gid to be resolved to a SID
+ *
+ * @return tevent_req on success, NULL on error
+ */
+
+struct tevent_req *wbcGidToSid_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   struct wb_context *wb_ctx,
+                                   gid_t gid)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_gid_to_sid_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_gid_to_sid_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+
+       state->req.cmd = WINBINDD_GID_TO_SID;
+       state->req.data.gid = gid;
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcGidToSid_done, req);
+       return req;
+}
+
+static void wbcGidToSid_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_gid_to_sid_state *state = tevent_req_data(
+                       req, struct wbc_gid_to_sid_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       state->sid = talloc(state, struct wbcDomainSid);
+       if (state->sid == NULL) {
+               TALLOC_FREE(resp);
+               tevent_req_error(req, WBC_ERR_NO_MEMORY);
+               return;
+       }
+
+       wbc_status = wbcStringToSid(resp->data.sid.sid, state->sid);
+       TALLOC_FREE(resp);
+
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive a Unix gid mapped to a Windows SID
+ *
+ * @param req          tevent_req containing the request
+ * @param *psid                pointer to hold the resolved SID
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcGidToSid_recv(struct tevent_req *req, struct wbcDomainSid *psid)
+{
+       struct wbc_gid_to_sid_state *state = tevent_req_data(
+                       req, struct wbc_gid_to_sid_state);
+       wbcErr wbc_status;
+
+       if (psid == NULL) {
+               tevent_req_received(req);
+               return WBC_ERR_INVALID_PARAM;
+       }
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       memcpy(psid, state->sid, sizeof(struct wbcDomainSid));
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
index ef85f2b7fd7a38a19a8fcb6ee8e2711b2c0b960c..03039a26ac2069693cc31880674b954f8e47b207 100644 (file)
@@ -300,275 +300,6 @@ done:
        return wbc_status;
 }
 
-struct wbc_authenticate_user_ex_state {
-       struct winbindd_request req;
-       struct tevent_context *ev;
-       struct wb_context *wb_ctx;
-       const struct wbcAuthUserParams *params;
-       struct wbcAuthUserInfo *info;
-       struct wbcAuthErrorInfo *error;
-};
-
-static void wbcAuthenticateUserEx_got_info(struct tevent_req *subreq);
-static void wbcAuthenticateUserEx_done(struct tevent_req *subreq);
-
-struct tevent_req *wbcAuthenticateUserEx_send(TALLOC_CTX *mem_ctx,
-                                       struct tevent_context *ev,
-                                       struct wb_context *wb_ctx,
-                                       const struct wbcAuthUserParams *params)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_authenticate_user_ex_state *state;
-
-       req = tevent_req_create(mem_ctx, &state,
-                               struct wbc_authenticate_user_ex_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       state->ev = ev;
-       state->wb_ctx = wb_ctx;
-       state->params = params;
-
-       if (!params) {
-               tevent_req_error(req, WBC_ERR_INVALID_PARAM);
-               return tevent_req_post(req, ev);
-       }
-
-       if (!params->account_name) {
-               tevent_req_error(req, WBC_ERR_INVALID_PARAM);
-               return tevent_req_post(req, ev);
-       }
-
-       ZERO_STRUCT(state->req);
-
-       if (params->flags) {
-               state->req.flags = params->flags;
-       }
-
-       switch (params->level) {
-       case WBC_AUTH_USER_LEVEL_PLAIN:
-               state->req.cmd = WINBINDD_PAM_AUTH;
-               state->req.flags |= WBFLAG_PAM_INFO3_TEXT |
-                                   WBFLAG_PAM_USER_SESSION_KEY |
-                                   WBFLAG_PAM_LMKEY;
-
-               if (!params->password.plaintext) {
-                       tevent_req_error(req, WBC_ERR_INVALID_PARAM);
-                       return tevent_req_post(req, ev);
-               }
-
-               strncpy(state->req.data.auth.pass,
-                       params->password.plaintext,
-                       sizeof(state->req.data.auth.pass)-1);
-
-               if (params->domain_name && params->domain_name[0]) {
-                       /* We need to get the winbind separator :-( */
-                       subreq = wbcInfo_send(state, ev, wb_ctx);
-                       if (tevent_req_nomem(subreq, req)) {
-                               return tevent_req_post(req, ev);
-                       }
-
-                       tevent_req_set_callback(subreq,
-                                               wbcAuthenticateUserEx_got_info,
-                                               req);
-                       return req;
-               } else {
-                       strncpy(state->req.data.auth.user,
-                               params->account_name,
-                               sizeof(state->req.data.auth.user)-1);
-               }
-
-               break;
-
-       case WBC_AUTH_USER_LEVEL_HASH:
-               tevent_req_error(req, WBC_ERR_NOT_IMPLEMENTED);
-               return tevent_req_post(req, ev);
-               /* Make some static code checkers happy */
-               break;
-
-       case WBC_AUTH_USER_LEVEL_RESPONSE:
-               state->req.cmd = WINBINDD_PAM_AUTH_CRAP;
-               state->req.flags |= WBFLAG_PAM_INFO3_TEXT |
-                                   WBFLAG_PAM_USER_SESSION_KEY |
-                                   WBFLAG_PAM_LMKEY;
-
-               if (params->password.response.lm_length &&
-                   !params->password.response.lm_data) {
-                       tevent_req_error(req, WBC_ERR_INVALID_PARAM);
-                       return tevent_req_post(req, ev);
-               }
-               if (params->password.response.lm_length == 0 &&
-                   params->password.response.lm_data) {
-                       tevent_req_error(req, WBC_ERR_INVALID_PARAM);
-                       return tevent_req_post(req, ev);
-               }
-
-               if (params->password.response.nt_length &&
-                   !params->password.response.nt_data) {
-                       tevent_req_error(req, WBC_ERR_INVALID_PARAM);
-                       return tevent_req_post(req, ev);
-               }
-               if (params->password.response.nt_length == 0&&
-                   params->password.response.nt_data) {
-                       tevent_req_error(req, WBC_ERR_INVALID_PARAM);
-                       return tevent_req_post(req, ev);
-               }
-
-               strncpy(state->req.data.auth_crap.user,
-                       params->account_name,
-                       sizeof(state->req.data.auth_crap.user)-1);
-               if (params->domain_name) {
-                       strncpy(state->req.data.auth_crap.domain,
-                               params->domain_name,
-                               sizeof(state->req.data.auth_crap.domain)-1);
-               }
-               if (params->workstation_name) {
-                       strncpy(state->req.data.auth_crap.workstation,
-                               params->workstation_name,
-                               sizeof(state->req.data.auth_crap.workstation)-1);
-               }
-
-               state->req.data.auth_crap.logon_parameters =
-                               params->parameter_control;
-
-               memcpy(state->req.data.auth_crap.chal,
-                      params->password.response.challenge,
-                      sizeof(state->req.data.auth_crap.chal));
-
-               state->req.data.auth_crap.lm_resp_len =
-                               MIN(params->password.response.lm_length,
-                                   sizeof(state->req.data.auth_crap.lm_resp));
-               state->req.data.auth_crap.nt_resp_len =
-                               MIN(params->password.response.nt_length,
-                                   sizeof(state->req.data.auth_crap.nt_resp));
-               if (params->password.response.lm_data) {
-                       memcpy(state->req.data.auth_crap.lm_resp,
-                              params->password.response.lm_data,
-                              state->req.data.auth_crap.lm_resp_len);
-               }
-               if (params->password.response.nt_data) {
-                       memcpy(state->req.data.auth_crap.nt_resp,
-                              params->password.response.nt_data,
-                              state->req.data.auth_crap.nt_resp_len);
-               }
-               break;
-       default:
-               tevent_req_error(req, WBC_ERR_INVALID_PARAM);
-               return tevent_req_post(req, ev);
-               break;
-       }
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcAuthenticateUserEx_done, req);
-       return req;
-}
-
-static void wbcAuthenticateUserEx_got_info(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_authenticate_user_ex_state *state = tevent_req_data(
-                       req, struct wbc_authenticate_user_ex_state);
-       char *version_string;
-       char separator;
-       wbcErr wbc_status;
-
-       wbc_status = wbcInfo_recv(subreq, state, &separator, &version_string);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       snprintf(state->req.data.auth.user,
-                sizeof(state->req.data.auth.user)-1,
-                "%s%c%s",
-                state->params->domain_name,
-                separator,
-                state->params->account_name);
-
-       subreq = wb_trans_send(state, state->ev, state->wb_ctx, false,
-                              &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return;
-       }
-
-       tevent_req_set_callback(subreq, wbcAuthenticateUserEx_done, req);
-       return;
-}
-
-static void wbcAuthenticateUserEx_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_authenticate_user_ex_state *state = tevent_req_data(
-                       req, struct wbc_authenticate_user_ex_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       ZERO_STRUCT(resp);
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               goto done;
-       }
-
-       if (resp->data.auth.nt_status != 0) {
-               wbc_status = wbc_create_error_info(resp, &state->error);
-               if (!WBC_ERROR_IS_OK(wbc_status)) {
-                       tevent_req_error(req, wbc_status);
-                       goto done;
-               }
-
-               tevent_req_error(req, WBC_ERR_AUTH_ERROR);
-               goto done;
-       }
-
-       wbc_status = wbc_create_auth_info(state, resp, &state->info);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               goto done;
-       }
-
-done:
-       TALLOC_FREE(resp);
-}
-
-wbcErr wbcAuthenticateUserEx_recv(struct tevent_req *req,
-                                 TALLOC_CTX *mem_ctx,
-                                 struct wbcAuthUserInfo **info,
-                                 struct wbcAuthErrorInfo **error)
-{
-       struct wbc_authenticate_user_ex_state *state = tevent_req_data(
-                       req, struct wbc_authenticate_user_ex_state);
-       wbcErr wbc_status;
-
-       if (error) {
-               *error = NULL;
-       }
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               if (error) {
-                       *error = talloc_steal(mem_ctx, state->error);
-               }
-               return wbc_status;
-       }
-
-       if (info) {
-               *info = talloc_steal(mem_ctx, state->info);
-       }
-
-       tevent_req_received(req);
-       return wbc_status;
-}
 
 /* Authenticate with more detailed information */
 wbcErr wbcAuthenticateUserEx(const struct wbcAuthUserParams *params,
diff --git a/nsswitch/libwbclient/wbc_pam_async.c b/nsswitch/libwbclient/wbc_pam_async.c
new file mode 100644 (file)
index 0000000..f551f74
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Winbind client API
+
+   Copyright (C) 2009 Kai Blin  <kai@samba.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* Required Headers */
+
+#include "replace.h"
+#include "libwbclient.h"
+#include "../winbind_client.h"
+
+/* FIXME: Currently this is still a copy of the same function from wbc_pam.c */
+static wbcErr wbc_create_auth_info(TALLOC_CTX *mem_ctx,
+                                  const struct winbindd_response *resp,
+                                  struct wbcAuthUserInfo **_i)
+{
+       wbcErr wbc_status = WBC_ERR_SUCCESS;
+       struct wbcAuthUserInfo *i;
+       struct wbcDomainSid domain_sid;
+       char *p;
+       uint32_t sn = 0;
+       uint32_t j;
+
+       i = talloc(mem_ctx, struct wbcAuthUserInfo);
+       BAIL_ON_PTR_ERROR(i, wbc_status);
+
+       i->user_flags   = resp->data.auth.info3.user_flgs;
+
+       i->account_name = talloc_strdup(i, resp->data.auth.info3.user_name);
+       BAIL_ON_PTR_ERROR(i->account_name, wbc_status);
+       i->user_principal= NULL;
+       i->full_name    = talloc_strdup(i, resp->data.auth.info3.full_name);
+       BAIL_ON_PTR_ERROR(i->full_name, wbc_status);
+       i->domain_name  = talloc_strdup(i, resp->data.auth.info3.logon_dom);
+       BAIL_ON_PTR_ERROR(i->domain_name, wbc_status);
+       i->dns_domain_name= NULL;
+
+       i->acct_flags   = resp->data.auth.info3.acct_flags;
+       memcpy(i->user_session_key,
+              resp->data.auth.user_session_key,
+              sizeof(i->user_session_key));
+       memcpy(i->lm_session_key,
+              resp->data.auth.first_8_lm_hash,
+              sizeof(i->lm_session_key));
+
+       i->logon_count          = resp->data.auth.info3.logon_count;
+       i->bad_password_count   = resp->data.auth.info3.bad_pw_count;
+
+       i->logon_time           = resp->data.auth.info3.logon_time;
+       i->logoff_time          = resp->data.auth.info3.logoff_time;
+       i->kickoff_time         = resp->data.auth.info3.kickoff_time;
+       i->pass_last_set_time   = resp->data.auth.info3.pass_last_set_time;
+       i->pass_can_change_time = resp->data.auth.info3.pass_can_change_time;
+       i->pass_must_change_time= resp->data.auth.info3.pass_must_change_time;
+
+       i->logon_server = talloc_strdup(i, resp->data.auth.info3.logon_srv);
+       BAIL_ON_PTR_ERROR(i->logon_server, wbc_status);
+       i->logon_script = talloc_strdup(i, resp->data.auth.info3.logon_script);
+       BAIL_ON_PTR_ERROR(i->logon_script, wbc_status);
+       i->profile_path = talloc_strdup(i, resp->data.auth.info3.profile_path);
+       BAIL_ON_PTR_ERROR(i->profile_path, wbc_status);
+       i->home_directory= talloc_strdup(i, resp->data.auth.info3.home_dir);
+       BAIL_ON_PTR_ERROR(i->home_directory, wbc_status);
+       i->home_drive   = talloc_strdup(i, resp->data.auth.info3.dir_drive);
+       BAIL_ON_PTR_ERROR(i->home_drive, wbc_status);
+
+       i->num_sids     = 2;
+       i->num_sids     += resp->data.auth.info3.num_groups;
+       i->num_sids     += resp->data.auth.info3.num_other_sids;
+
+       i->sids = talloc_array(i, struct wbcSidWithAttr, i->num_sids);
+       BAIL_ON_PTR_ERROR(i->sids, wbc_status);
+
+       wbc_status = wbcStringToSid(resp->data.auth.info3.dom_sid,
+                                   &domain_sid);
+       BAIL_ON_WBC_ERROR(wbc_status);
+
+#define _SID_COMPOSE(s, d, r, a) { \
+       (s).sid = d; \
+       if ((s).sid.num_auths < WBC_MAXSUBAUTHS) { \
+               (s).sid.sub_auths[(s).sid.num_auths++] = r; \
+       } else { \
+               wbc_status = WBC_ERR_INVALID_SID; \
+               BAIL_ON_WBC_ERROR(wbc_status); \
+       } \
+       (s).attributes = a; \
+} while (0)
+
+       sn = 0;
+       _SID_COMPOSE(i->sids[sn], domain_sid,
+                    resp->data.auth.info3.user_rid,
+                    0);
+       sn++;
+       _SID_COMPOSE(i->sids[sn], domain_sid,
+                    resp->data.auth.info3.group_rid,
+                    0);
+       sn++;
+
+       p = (char *)resp->extra_data.data;
+       if (!p) {
+               wbc_status = WBC_ERR_INVALID_RESPONSE;
+               BAIL_ON_WBC_ERROR(wbc_status);
+       }
+
+       for (j=0; j < resp->data.auth.info3.num_groups; j++) {
+               uint32_t rid;
+               uint32_t attrs;
+               int ret;
+               char *s = p;
+               char *e = strchr(p, '\n');
+               if (!e) {
+                       wbc_status = WBC_ERR_INVALID_RESPONSE;
+                       BAIL_ON_WBC_ERROR(wbc_status);
+               }
+               e[0] = '\0';
+               p = &e[1];
+
+               ret = sscanf(s, "0x%08X:0x%08X", &rid, &attrs);
+               if (ret != 2) {
+                       wbc_status = WBC_ERR_INVALID_RESPONSE;
+                       BAIL_ON_WBC_ERROR(wbc_status);
+               }
+
+               _SID_COMPOSE(i->sids[sn], domain_sid,
+                            rid, attrs);
+               sn++;
+       }
+
+       for (j=0; j < resp->data.auth.info3.num_other_sids; j++) {
+               uint32_t attrs;
+               int ret;
+               char *s = p;
+               char *a;
+               char *e = strchr(p, '\n');
+               if (!e) {
+                       wbc_status = WBC_ERR_INVALID_RESPONSE;
+                       BAIL_ON_WBC_ERROR(wbc_status);
+               }
+               e[0] = '\0';
+               p = &e[1];
+
+               e = strchr(s, ':');
+               if (!e) {
+                       wbc_status = WBC_ERR_INVALID_RESPONSE;
+                       BAIL_ON_WBC_ERROR(wbc_status);
+               }
+               e[0] = '\0';
+               a = &e[1];
+
+               ret = sscanf(a, "0x%08X",
+                            &attrs);
+               if (ret != 1) {
+                       wbc_status = WBC_ERR_INVALID_RESPONSE;
+                       BAIL_ON_WBC_ERROR(wbc_status);
+               }
+
+               wbc_status = wbcStringToSid(s, &i->sids[sn].sid);
+               BAIL_ON_WBC_ERROR(wbc_status);
+
+               i->sids[sn].attributes = attrs;
+               sn++;
+       }
+
+       i->num_sids = sn;
+
+       *_i = i;
+       i = NULL;
+done:
+       talloc_free(i);
+       return wbc_status;
+}
+
+/* FIXME: Currently this is still a copy of the same function from wbc_pam.c */
+static wbcErr wbc_create_error_info(const struct winbindd_response *resp,
+                                   struct wbcAuthErrorInfo **_e)
+{
+       wbcErr wbc_status = WBC_ERR_SUCCESS;
+       struct wbcAuthErrorInfo *e;
+
+       e = talloc(NULL, struct wbcAuthErrorInfo);
+       BAIL_ON_PTR_ERROR(e, wbc_status);
+
+       e->nt_status = resp->data.auth.nt_status;
+       e->pam_error = resp->data.auth.pam_error;
+       e->nt_string = talloc_strdup(e, resp->data.auth.nt_status_string);
+       BAIL_ON_PTR_ERROR(e->nt_string, wbc_status);
+
+       e->display_string = talloc_strdup(e, resp->data.auth.error_string);
+       BAIL_ON_PTR_ERROR(e->display_string, wbc_status);
+
+       *_e = e;
+       e = NULL;
+
+done:
+       talloc_free(e);
+       return wbc_status;
+}
+
+struct wbc_authenticate_user_ex_state {
+       struct winbindd_request req;
+       struct tevent_context *ev;
+       struct wb_context *wb_ctx;
+       const struct wbcAuthUserParams *params;
+       struct wbcAuthUserInfo *info;
+       struct wbcAuthErrorInfo *error;
+};
+
+static void wbcAuthenticateUserEx_got_info(struct tevent_req *subreq);
+static void wbcAuthenticateUserEx_done(struct tevent_req *subreq);
+
+struct tevent_req *wbcAuthenticateUserEx_send(TALLOC_CTX *mem_ctx,
+                                       struct tevent_context *ev,
+                                       struct wb_context *wb_ctx,
+                                       const struct wbcAuthUserParams *params)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_authenticate_user_ex_state *state;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct wbc_authenticate_user_ex_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       state->ev = ev;
+       state->wb_ctx = wb_ctx;
+       state->params = params;
+
+       if (!params) {
+               tevent_req_error(req, WBC_ERR_INVALID_PARAM);
+               return tevent_req_post(req, ev);
+       }
+
+       if (!params->account_name) {
+               tevent_req_error(req, WBC_ERR_INVALID_PARAM);
+               return tevent_req_post(req, ev);
+       }
+
+       ZERO_STRUCT(state->req);
+
+       if (params->flags) {
+               state->req.flags = params->flags;
+       }
+
+       switch (params->level) {
+       case WBC_AUTH_USER_LEVEL_PLAIN:
+               state->req.cmd = WINBINDD_PAM_AUTH;
+               state->req.flags |= WBFLAG_PAM_INFO3_TEXT |
+                                   WBFLAG_PAM_USER_SESSION_KEY |
+                                   WBFLAG_PAM_LMKEY;
+
+               if (!params->password.plaintext) {
+                       tevent_req_error(req, WBC_ERR_INVALID_PARAM);
+                       return tevent_req_post(req, ev);
+               }
+
+               strncpy(state->req.data.auth.pass,
+                       params->password.plaintext,
+                       sizeof(state->req.data.auth.pass)-1);
+
+               if (params->domain_name && params->domain_name[0]) {
+                       /* We need to get the winbind separator :-( */
+                       subreq = wbcInfo_send(state, ev, wb_ctx);
+                       if (tevent_req_nomem(subreq, req)) {
+                               return tevent_req_post(req, ev);
+                       }
+
+                       tevent_req_set_callback(subreq,
+                                               wbcAuthenticateUserEx_got_info,
+                                               req);
+                       return req;
+               } else {
+                       strncpy(state->req.data.auth.user,
+                               params->account_name,
+                               sizeof(state->req.data.auth.user)-1);
+               }
+
+               break;
+
+       case WBC_AUTH_USER_LEVEL_HASH:
+               tevent_req_error(req, WBC_ERR_NOT_IMPLEMENTED);
+               return tevent_req_post(req, ev);
+               /* Make some static code checkers happy */
+               break;
+
+       case WBC_AUTH_USER_LEVEL_RESPONSE:
+               state->req.cmd = WINBINDD_PAM_AUTH_CRAP;
+               state->req.flags |= WBFLAG_PAM_INFO3_TEXT |
+                                   WBFLAG_PAM_USER_SESSION_KEY |
+                                   WBFLAG_PAM_LMKEY;
+
+               if (params->password.response.lm_length &&
+                   !params->password.response.lm_data) {
+                       tevent_req_error(req, WBC_ERR_INVALID_PARAM);
+                       return tevent_req_post(req, ev);
+               }
+               if (params->password.response.lm_length == 0 &&
+                   params->password.response.lm_data) {
+                       tevent_req_error(req, WBC_ERR_INVALID_PARAM);
+                       return tevent_req_post(req, ev);
+               }
+
+               if (params->password.response.nt_length &&
+                   !params->password.response.nt_data) {
+                       tevent_req_error(req, WBC_ERR_INVALID_PARAM);
+                       return tevent_req_post(req, ev);
+               }
+               if (params->password.response.nt_length == 0&&
+                   params->password.response.nt_data) {
+                       tevent_req_error(req, WBC_ERR_INVALID_PARAM);
+                       return tevent_req_post(req, ev);
+               }
+
+               strncpy(state->req.data.auth_crap.user,
+                       params->account_name,
+                       sizeof(state->req.data.auth_crap.user)-1);
+               if (params->domain_name) {
+                       strncpy(state->req.data.auth_crap.domain,
+                               params->domain_name,
+                               sizeof(state->req.data.auth_crap.domain)-1);
+               }
+               if (params->workstation_name) {
+                       strncpy(state->req.data.auth_crap.workstation,
+                               params->workstation_name,
+                               sizeof(state->req.data.auth_crap.workstation)-1);
+               }
+
+               state->req.data.auth_crap.logon_parameters =
+                               params->parameter_control;
+
+               memcpy(state->req.data.auth_crap.chal,
+                      params->password.response.challenge,
+                      sizeof(state->req.data.auth_crap.chal));
+
+               state->req.data.auth_crap.lm_resp_len =
+                               MIN(params->password.response.lm_length,
+                                   sizeof(state->req.data.auth_crap.lm_resp));
+               state->req.data.auth_crap.nt_resp_len =
+                               MIN(params->password.response.nt_length,
+                                   sizeof(state->req.data.auth_crap.nt_resp));
+               if (params->password.response.lm_data) {
+                       memcpy(state->req.data.auth_crap.lm_resp,
+                              params->password.response.lm_data,
+                              state->req.data.auth_crap.lm_resp_len);
+               }
+               if (params->password.response.nt_data) {
+                       memcpy(state->req.data.auth_crap.nt_resp,
+                              params->password.response.nt_data,
+                              state->req.data.auth_crap.nt_resp_len);
+               }
+               break;
+       default:
+               tevent_req_error(req, WBC_ERR_INVALID_PARAM);
+               return tevent_req_post(req, ev);
+               break;
+       }
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcAuthenticateUserEx_done, req);
+       return req;
+}
+
+static void wbcAuthenticateUserEx_got_info(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_authenticate_user_ex_state *state = tevent_req_data(
+                       req, struct wbc_authenticate_user_ex_state);
+       char *version_string;
+       char separator;
+       wbcErr wbc_status;
+
+       wbc_status = wbcInfo_recv(subreq, state, &separator, &version_string);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       snprintf(state->req.data.auth.user,
+                sizeof(state->req.data.auth.user)-1,
+                "%s%c%s",
+                state->params->domain_name,
+                separator,
+                state->params->account_name);
+
+       subreq = wb_trans_send(state, state->ev, state->wb_ctx, false,
+                              &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+
+       tevent_req_set_callback(subreq, wbcAuthenticateUserEx_done, req);
+       return;
+}
+
+static void wbcAuthenticateUserEx_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_authenticate_user_ex_state *state = tevent_req_data(
+                       req, struct wbc_authenticate_user_ex_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       ZERO_STRUCT(resp);
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               goto done;
+       }
+
+       if (resp->data.auth.nt_status != 0) {
+               wbc_status = wbc_create_error_info(resp, &state->error);
+               if (!WBC_ERROR_IS_OK(wbc_status)) {
+                       tevent_req_error(req, wbc_status);
+                       goto done;
+               }
+
+               tevent_req_error(req, WBC_ERR_AUTH_ERROR);
+               goto done;
+       }
+
+       wbc_status = wbc_create_auth_info(state, resp, &state->info);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               goto done;
+       }
+
+done:
+       TALLOC_FREE(resp);
+}
+
+wbcErr wbcAuthenticateUserEx_recv(struct tevent_req *req,
+                                 TALLOC_CTX *mem_ctx,
+                                 struct wbcAuthUserInfo **info,
+                                 struct wbcAuthErrorInfo **error)
+{
+       struct wbc_authenticate_user_ex_state *state = tevent_req_data(
+                       req, struct wbc_authenticate_user_ex_state);
+       wbcErr wbc_status;
+
+       if (error) {
+               *error = NULL;
+       }
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               if (error) {
+                       *error = talloc_steal(mem_ctx, state->error);
+               }
+               return wbc_status;
+       }
+
+       if (info) {
+               *info = talloc_steal(mem_ctx, state->info);
+       }
+
+       tevent_req_received(req);
+       return wbc_status;
+}
index a038e83b7a52940ca1c279222d3ee395f781a877..a0b8d0f6a90da0d8c001307a596eeed0ce907ce8 100644 (file)
@@ -150,134 +150,6 @@ done:
 
 }
 
-struct wbc_lookup_name_state {
-       struct winbindd_request req;
-       struct wb_context *wb_ctx;
-       struct wbcDomainSid *sid;
-       enum wbcSidType name_type;
-};
-
-static void wbcLookupName_done(struct tevent_req *subreq);
-
-/**
- * @brief Request a conversion of a domaind and name to a domain sid
- *
- * @param mem_ctx      talloc context to allocate the request from
- * @param ev           tevent context to use for async operation
- * @param wb_ctx       winbind context to use
- * @param *domain      Pointer to the domain to be resolved
- * @param *name                Pointer to the name to be resolved
- *
- * @return tevent_req on success, NULL on error
- **/
-
-struct tevent_req *wbcLookupName_send(TALLOC_CTX *mem_ctx,
-                                     struct tevent_context *ev,
-                                     struct wb_context *wb_ctx,
-                                     const char *domain,
-                                     const char *name)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_lookup_name_state *state;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_lookup_name_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-
-       state->req.cmd = WINBINDD_LOOKUPNAME;
-       strncpy(state->req.data.name.dom_name, domain,
-               sizeof(state->req.data.name.dom_name)-1);
-       strncpy(state->req.data.name.name, name,
-               sizeof(state->req.data.name.name)-1);
-       state->wb_ctx = wb_ctx;
-
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcLookupName_done, req);
-       return req;
-}
-
-static void wbcLookupName_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_lookup_name_state *state = tevent_req_data(
-                       req, struct wbc_lookup_name_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       state->sid = talloc(state, struct wbcDomainSid);
-       if (tevent_req_nomem(state->sid, req)) {
-               return;
-       }
-
-       wbc_status = wbcStringToSid(resp->data.sid.sid, state->sid);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               wbcDebug(state->wb_ctx, WBC_DEBUG_ERROR,
-                        "wbcStringToSid returned %s!\n",
-                        wbcErrorString(wbc_status));
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       state->name_type = (enum wbcSidType)resp->data.sid.type;
-
-       TALLOC_FREE(resp);
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive a conversion a SID to a domain and name
- *
- * @param *
- * @param *pname       Resolved User or group name
- * @param *pname_type  Pointer to the resolved SID type
- *
- * @return #wbcErr
- */
-
-wbcErr wbcLookupName_recv(struct tevent_req *req,
-                         struct wbcDomainSid *sid,
-                         enum wbcSidType *name_type)
-{
-       struct wbc_lookup_name_state *state = tevent_req_data(
-                       req, struct wbc_lookup_name_state);
-       wbcErr wbc_status = WBC_ERR_SUCCESS;
-
-       if (!sid || !name_type) {
-               wbcDebug(state->wb_ctx, WBC_DEBUG_TRACE,
-               "Sid is %p, name_type is %p\n", sid, name_type);
-               wbc_status = WBC_ERR_INVALID_PARAM;
-               goto failed;
-       }
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               goto failed;
-       }
-
-       memcpy(sid, state->sid, sizeof(struct wbcDomainSid));
-       *name_type = state->name_type;
-
-failed:
-       tevent_req_received(req);
-       return wbc_status;
-}
-
 
 /* Convert a domain and name to SID */
 wbcErr wbcLookupName(const char *domain,
@@ -322,134 +194,6 @@ wbcErr wbcLookupName(const char *domain,
        return wbc_status;
 }
 
-struct wbc_lookup_sid_state {
-       struct winbindd_request req;
-       char *domain;
-       char *name;
-       enum wbcSidType name_type;
-};
-
-static void wbcLookupSid_done(struct tevent_req *subreq);
-
-/**
- * @brief Request a conversion of a SID to a domain and name
- *
- * @param mem_ctx      talloc context to allocate the request from
- * @param ev           tevent context to use for async operation
- * @param wb_ctx       winbind context to use
- * @param *sid         Pointer to the domain SID to be resolved
- *
- * @return tevent_req on success, NULL on error
- **/
-
-struct tevent_req *wbcLookupSid_send(TALLOC_CTX *mem_ctx,
-                                    struct tevent_context *ev,
-                                    struct wb_context *wb_ctx,
-                                    const struct wbcDomainSid *sid)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_lookup_sid_state *state;
-       char *sid_string;
-       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_lookup_sid_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-
-       state->req.cmd = WINBINDD_LOOKUPSID;
-       wbc_status = wbcSidToString(sid, &sid_string);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return tevent_req_post(req, ev);
-       }
-       strncpy(state->req.data.sid, sid_string, sizeof(state->req.data.sid)-1);
-       wbcFreeMemory(sid_string);
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcLookupSid_done, req);
-       return req;
-}
-
-static void wbcLookupSid_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_lookup_sid_state *state = tevent_req_data(
-                       req, struct wbc_lookup_sid_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-       state->domain = talloc_strdup(state, resp->data.name.dom_name);
-       if (tevent_req_nomem(state->domain, req)) {
-               return;
-       }
-
-       state->name   = talloc_strdup(state, resp->data.name.name);
-       if (tevent_req_nomem(state->name, req)) {
-               return;
-       }
-
-       state->name_type = (enum wbcSidType)resp->data.name.type;
-
-       TALLOC_FREE(resp);
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive a conversion a SID to a domain and name
- *
- * @param *mem_ctx,    talloc context to move results to
- * @param *pdomain     Resolved Domain name (possibly "")
- * @param *pname       Resolved User or group name
- * @param *pname_type  Pointer to the resolved SID type
- *
- * @return #wbcErr
- */
-
-wbcErr wbcLookupSid_recv(struct tevent_req *req,
-                        TALLOC_CTX *mem_ctx,
-                        char **pdomain,
-                        char **pname,
-                        enum wbcSidType *pname_type)
-{
-       struct wbc_lookup_sid_state *state = tevent_req_data(
-                       req, struct wbc_lookup_sid_state);
-       wbcErr wbc_status;
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       if (pdomain != NULL) {
-               *pdomain = talloc_steal(mem_ctx, state->domain);
-       }
-
-       if (pname != NULL) {
-               *pname   = talloc_steal(mem_ctx, state->name);
-       }
-
-       if (pname_type != NULL) {
-               *pname_type = state->name_type;
-       }
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
 
 /* Convert a SID to a domain and name */
 wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
diff --git a/nsswitch/libwbclient/wbc_sid_async.c b/nsswitch/libwbclient/wbc_sid_async.c
new file mode 100644 (file)
index 0000000..7e3bd75
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Winbind client API
+
+   Copyright (C) 2009,2010 Kai Blin  <kai@samba.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* Required Headers */
+
+#include "replace.h"
+#include "libwbclient.h"
+#include "../winbind_client.h"
+
+struct wbc_lookup_name_state {
+       struct winbindd_request req;
+       struct wb_context *wb_ctx;
+       struct wbcDomainSid *sid;
+       enum wbcSidType name_type;
+};
+
+static void wbcLookupName_done(struct tevent_req *subreq);
+
+/**
+ * @brief Request a conversion of a domaind and name to a domain sid
+ *
+ * @param mem_ctx      talloc context to allocate the request from
+ * @param ev           tevent context to use for async operation
+ * @param wb_ctx       winbind context to use
+ * @param *domain      Pointer to the domain to be resolved
+ * @param *name                Pointer to the name to be resolved
+ *
+ * @return tevent_req on success, NULL on error
+ **/
+
+struct tevent_req *wbcLookupName_send(TALLOC_CTX *mem_ctx,
+                                     struct tevent_context *ev,
+                                     struct wb_context *wb_ctx,
+                                     const char *domain,
+                                     const char *name)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_lookup_name_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_lookup_name_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+
+       state->req.cmd = WINBINDD_LOOKUPNAME;
+       strncpy(state->req.data.name.dom_name, domain,
+               sizeof(state->req.data.name.dom_name)-1);
+       strncpy(state->req.data.name.name, name,
+               sizeof(state->req.data.name.name)-1);
+       state->wb_ctx = wb_ctx;
+
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcLookupName_done, req);
+       return req;
+}
+
+static void wbcLookupName_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_lookup_name_state *state = tevent_req_data(
+                       req, struct wbc_lookup_name_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       state->sid = talloc(state, struct wbcDomainSid);
+       if (tevent_req_nomem(state->sid, req)) {
+               return;
+       }
+
+       wbc_status = wbcStringToSid(resp->data.sid.sid, state->sid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               wbcDebug(state->wb_ctx, WBC_DEBUG_ERROR,
+                        "wbcStringToSid returned %s!\n",
+                        wbcErrorString(wbc_status));
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       state->name_type = (enum wbcSidType)resp->data.sid.type;
+
+       TALLOC_FREE(resp);
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive a conversion a SID to a domain and name
+ *
+ * @param *
+ * @param *pname       Resolved User or group name
+ * @param *pname_type  Pointer to the resolved SID type
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcLookupName_recv(struct tevent_req *req,
+                         struct wbcDomainSid *sid,
+                         enum wbcSidType *name_type)
+{
+       struct wbc_lookup_name_state *state = tevent_req_data(
+                       req, struct wbc_lookup_name_state);
+       wbcErr wbc_status = WBC_ERR_SUCCESS;
+
+       if (!sid || !name_type) {
+               wbcDebug(state->wb_ctx, WBC_DEBUG_TRACE,
+               "Sid is %p, name_type is %p\n", sid, name_type);
+               wbc_status = WBC_ERR_INVALID_PARAM;
+               goto failed;
+       }
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               goto failed;
+       }
+
+       memcpy(sid, state->sid, sizeof(struct wbcDomainSid));
+       *name_type = state->name_type;
+
+failed:
+       tevent_req_received(req);
+       return wbc_status;
+}
+
+
+struct wbc_lookup_sid_state {
+       struct winbindd_request req;
+       char *domain;
+       char *name;
+       enum wbcSidType name_type;
+};
+
+static void wbcLookupSid_done(struct tevent_req *subreq);
+
+/**
+ * @brief Request a conversion of a SID to a domain and name
+ *
+ * @param mem_ctx      talloc context to allocate the request from
+ * @param ev           tevent context to use for async operation
+ * @param wb_ctx       winbind context to use
+ * @param *sid         Pointer to the domain SID to be resolved
+ *
+ * @return tevent_req on success, NULL on error
+ **/
+
+struct tevent_req *wbcLookupSid_send(TALLOC_CTX *mem_ctx,
+                                    struct tevent_context *ev,
+                                    struct wb_context *wb_ctx,
+                                    const struct wbcDomainSid *sid)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_lookup_sid_state *state;
+       char *sid_string;
+       wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_lookup_sid_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+
+       state->req.cmd = WINBINDD_LOOKUPSID;
+       wbc_status = wbcSidToString(sid, &sid_string);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return tevent_req_post(req, ev);
+       }
+       strncpy(state->req.data.sid, sid_string, sizeof(state->req.data.sid)-1);
+       wbcFreeMemory(sid_string);
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcLookupSid_done, req);
+       return req;
+}
+
+static void wbcLookupSid_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_lookup_sid_state *state = tevent_req_data(
+                       req, struct wbc_lookup_sid_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+       state->domain = talloc_strdup(state, resp->data.name.dom_name);
+       if (tevent_req_nomem(state->domain, req)) {
+               return;
+       }
+
+       state->name   = talloc_strdup(state, resp->data.name.name);
+       if (tevent_req_nomem(state->name, req)) {
+               return;
+       }
+
+       state->name_type = (enum wbcSidType)resp->data.name.type;
+
+       TALLOC_FREE(resp);
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive a conversion a SID to a domain and name
+ *
+ * @param *mem_ctx,    talloc context to move results to
+ * @param *pdomain     Resolved Domain name (possibly "")
+ * @param *pname       Resolved User or group name
+ * @param *pname_type  Pointer to the resolved SID type
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcLookupSid_recv(struct tevent_req *req,
+                        TALLOC_CTX *mem_ctx,
+                        char **pdomain,
+                        char **pname,
+                        enum wbcSidType *pname_type)
+{
+       struct wbc_lookup_sid_state *state = tevent_req_data(
+                       req, struct wbc_lookup_sid_state);
+       wbcErr wbc_status;
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       if (pdomain != NULL) {
+               *pdomain = talloc_steal(mem_ctx, state->domain);
+       }
+
+       if (pname != NULL) {
+               *pname   = talloc_steal(mem_ctx, state->name);
+       }
+
+       if (pname_type != NULL) {
+               *pname_type = state->name_type;
+       }
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
index 57506f214b5825e343930af656af86d5947d9afd..2a1285e9169653429bf2ba95d4a8b024ef7543e2 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Unix SMB/CIFS implementation.
 
-   Winbind client API
+   Winbind client asynchronous API, utility functions
 
    Copyright (C) Gerald (Jerry) Carter 2007-2008
 
 #include "replace.h"
 #include "libwbclient.h"
 
-
-
-struct wbc_ping_state {
-       struct winbindd_request req;
-};
-
-static void wbcPing_done(struct tevent_req *subreq);
-
-/** @brief Ping winbind to see if the service is up and running
- *
- * @param mem_ctx      talloc context to allocate the request from
- * @param ev           event context to use for async operation
- * @param wb_ctx       winbind context to use
- *
- * @return Async request on successful dispatch of the request, NULL on error
- */
-
-struct tevent_req *wbcPing_send(TALLOC_CTX *mem_ctx,
-                               struct tevent_context *ev,
-                               struct wb_context *wb_ctx)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_ping_state *state;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_ping_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-
-       state->req.cmd = WINBINDD_PING;
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcPing_done, req);
-       return req;
-}
-
-static void wbcPing_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_ping_state *state = tevent_req_data(
-                       req, struct wbc_ping_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-       TALLOC_FREE(resp);
-
-       tevent_req_done(req);
-}
-
-/** @brief Receive ping response from winbind
- *
- * @param req          async request sent in #wbcPing_send
- *
- * @return NT_STATUS_OK on success, an error status on error.
- */
-
-wbcErr wbcPing_recv(struct tevent_req *req)
-{
-       wbcErr wbc_status;
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
-
 /** @brief Ping winbindd to see if the daemon is running
  *
  * @return #wbcErr
@@ -123,595 +42,6 @@ wbcErr wbcPing(void)
        return wbcRequestResponse(WINBINDD_PING, &request, &response);
 }
 
-struct wbc_interface_version_state {
-       struct winbindd_request req;
-       uint32_t version;
-};
-
-static void wbcInterfaceVersion_done(struct tevent_req *subreq);
-
-/**
- * @brief Request the interface version from winbind
- *
- * @param mem_ctx      talloc context to allocate memory from
- * @param ev           tevent context to use for async requests
- * @param wb_ctx       winbind context
- *
- * @return tevevt_req on success, NULL on failure
- */
-
-struct tevent_req *wbcInterfaceVersion_send(TALLOC_CTX *mem_ctx,
-                                           struct tevent_context *ev,
-                                           struct wb_context *wb_ctx)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_interface_version_state *state;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_interface_version_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-       state->req.cmd = WINBINDD_INTERFACE_VERSION;
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcInterfaceVersion_done, req);
-
-       return req;
-}
-
-static void wbcInterfaceVersion_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_interface_version_state *state = tevent_req_data(
-                       req, struct wbc_interface_version_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-       state->version = resp->data.interface_version;
-       TALLOC_FREE(resp);
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive the winbind interface version
- *
- * @param req                  tevent_req containing the request
- * @param interface_version    pointer to uint32_t to hold the interface
- *                             version
- *
- * @return #wbcErr
- */
-
-wbcErr wbcInterfaceVersion_recv(struct tevent_req *req,
-                               uint32_t *interface_version)
-{
-       struct wbc_interface_version_state *state = tevent_req_data(
-                       req, struct wbc_interface_version_state);
-       wbcErr wbc_status;
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       *interface_version = state->version;
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
-
-struct wbc_info_state {
-       struct winbindd_request req;
-       char separator;
-       char *version_string;
-};
-
-static void wbcInfo_done(struct tevent_req *subreq);
-
-/**
- * @brief Request information about the winbind service
- *
- * @param mem_ctx      talloc context to allocate memory from
- * @param ev           tevent context to use for async requests
- * @param wb_ctx       winbind context
- *
- * @return tevent_req on success, NULL on failure
- */
-
-struct tevent_req *wbcInfo_send(TALLOC_CTX *mem_ctx,
-                               struct tevent_context *ev,
-                               struct wb_context *wb_ctx)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_info_state *state;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_info_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-       state->req.cmd = WINBINDD_INFO;
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcInfo_done, req);
-       return req;
-}
-
-static void wbcInfo_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_info_state *state = tevent_req_data(
-                       req, struct wbc_info_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-       state->version_string = talloc_strdup(state,
-                                       resp->data.info.samba_version);
-       if (tevent_req_nomem(state->version_string, subreq)) {
-               return;
-       }
-       state->separator = resp->data.info.winbind_separator;
-       TALLOC_FREE(resp);
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive information about the running winbind service
- *
- * @param req                  tevent_req containing the request
- * @param mem_ctx              talloc context to allocate memory from
- * @param winbind_separator    pointer to a char to hold the separator
- * @param version_string       pointer to a string to hold the version string
- *
- * @return #wbcErr
- */
-
-wbcErr wbcInfo_recv(struct tevent_req *req,
-                   TALLOC_CTX *mem_ctx,
-                   char *winbind_separator,
-                   char **version_string)
-{
-       struct wbc_info_state *state = tevent_req_data(
-                       req, struct wbc_info_state);
-       wbcErr wbc_status;
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       *winbind_separator = state->separator;
-       *version_string = talloc_steal(mem_ctx, state->version_string);
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
-
-struct wbc_netbios_name_state {
-       struct winbindd_request req;
-       char *netbios_name;
-};
-
-static void wbcNetbiosName_done(struct tevent_req *subreq);
-
-/**
- * @brief Request the machine's netbios name
- *
- * @param mem_ctx      talloc context to allocate memory from
- * @param ev           tevent context to use for async requests
- * @param wb_ctx       winbind context
- *
- * @return tevent_req on success, NULL on failure
- */
-
-struct tevent_req *wbcNetbiosName_send(TALLOC_CTX *mem_ctx,
-                                      struct tevent_context *ev,
-                                      struct wb_context *wb_ctx)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_netbios_name_state *state;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_netbios_name_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-       state->req.cmd = WINBINDD_NETBIOS_NAME;
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcNetbiosName_done, req);
-       return req;
-}
-
-static void wbcNetbiosName_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_netbios_name_state *state = tevent_req_data(
-                       req, struct wbc_netbios_name_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-       state->netbios_name = talloc_strdup(state,
-                                       resp->data.info.samba_version);
-       if (tevent_req_nomem(state->netbios_name, subreq)) {
-               return;
-       }
-       TALLOC_FREE(resp);
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive the machine's netbios name
- *
- * @param req          tevent_req containing the request
- * @param mem_ctx      talloc context to allocate memory from
- * @param netbios_name pointer to a string to hold the netbios name
- *
- * @return #wbcErr
- */
-
-wbcErr wbcNetbiosName_recv(struct tevent_req *req,
-                          TALLOC_CTX *mem_ctx,
-                          char **netbios_name)
-{
-       struct wbc_netbios_name_state *state = tevent_req_data(
-                       req, struct wbc_netbios_name_state);
-       wbcErr wbc_status;
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       *netbios_name = talloc_steal(mem_ctx, state->netbios_name);
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
-
-struct wbc_domain_name_state {
-       struct winbindd_request req;
-       char *domain_name;
-};
-
-static void wbcDomainName_done(struct tevent_req *subreq);
-
-/**
- * @brief Request the machine's domain name
- *
- * @param mem_ctx      talloc context to allocate memory from
- * @param ev           tevent context to use for async requests
- * @param wb_ctx       winbind context
- *
- * @return tevent_req on success, NULL on failure
- */
-
-struct tevent_req *wbcDomainName_send(TALLOC_CTX *mem_ctx,
-                                     struct tevent_context *ev,
-                                     struct wb_context *wb_ctx)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_domain_name_state *state;
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_domain_name_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       ZERO_STRUCT(state->req);
-       state->req.cmd = WINBINDD_DOMAIN_NAME;
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcDomainName_done, req);
-       return req;
-}
-
-static void wbcDomainName_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_domain_name_state *state = tevent_req_data(
-                       req, struct wbc_domain_name_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-       state->domain_name = talloc_strdup(state, resp->data.domain_name);
-       if (tevent_req_nomem(state->domain_name, subreq)) {
-               return;
-       }
-       TALLOC_FREE(resp);
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive the machine's domain name
- *
- * @param req          tevent_req containing the request
- * @param mem_ctx      talloc context to allocate memory from
- * @param domain_name  pointer to a string to hold the domain name
- *
- * @return #wbcErr
- */
-
-wbcErr wbcDomainName_recv(struct tevent_req *req,
-                         TALLOC_CTX *mem_ctx,
-                         char **domain_name)
-{
-       struct wbc_domain_name_state *state = tevent_req_data(
-                       req, struct wbc_domain_name_state);
-       wbcErr wbc_status;
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       *domain_name = talloc_steal(mem_ctx, state->domain_name);
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
-
-struct wbc_interface_details_state {
-       struct tevent_context *ev;
-       struct wb_context *wb_ctx;
-       struct wbcDomainInfo *dinfo;
-       struct wbcInterfaceDetails *details;
-};
-
-static void wbcInterfaceDetails_version(struct tevent_req *subreq);
-static void wbcInterfaceDetails_info(struct tevent_req *subreq);
-static void wbcInterfaceDetails_netbios_name(struct tevent_req *subreq);
-static void wbcInterfaceDetails_domain_name(struct tevent_req *subreq);
-static void wbcInterfaceDetails_domain_info(struct tevent_req *subreq);
-
-/**
- * @brief Request some useful details about the winbind service
- *
- * @param mem_ctx      talloc context to allocate memory from
- * @param ev           tevent context to use for async requests
- * @param wb_ctx       winbind context
- *
- * @return tevent_req on success, NULL on failure
- */
-
-struct tevent_req *wbcInterfaceDetails_send(TALLOC_CTX *mem_ctx,
-                                           struct tevent_context *ev,
-                                           struct wb_context *wb_ctx)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_interface_details_state *state;
-
-       req = tevent_req_create(mem_ctx, &state,
-                               struct wbc_interface_details_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       state->ev = ev;
-       state->wb_ctx = wb_ctx;
-       state->details = talloc(state, struct wbcInterfaceDetails);
-       if (tevent_req_nomem(state->details, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       subreq = wbcInterfaceVersion_send(state, ev, wb_ctx);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcInterfaceDetails_version, req);
-       return req;
-}
-
-static void wbcInterfaceDetails_version(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_interface_details_state *state = tevent_req_data(
-                       req, struct wbc_interface_details_state);
-       wbcErr wbc_status;
-
-
-       wbc_status  = wbcInterfaceVersion_recv(subreq,
-                                       &state->details->interface_version);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       subreq = wbcInfo_send(state, state->ev, state->wb_ctx);
-       if (tevent_req_nomem(subreq, req)) {
-               return;
-       }
-
-       tevent_req_set_callback(subreq, wbcInterfaceDetails_info, req);
-}
-
-static void wbcInterfaceDetails_info(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_interface_details_state *state = tevent_req_data(
-                       req, struct wbc_interface_details_state);
-       wbcErr wbc_status;
-
-       wbc_status  = wbcInfo_recv(subreq, state->details,
-                                  &state->details->winbind_separator,
-                                  &state->details->winbind_version);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       subreq = wbcNetbiosName_send(state, state->ev, state->wb_ctx);
-       if (tevent_req_nomem(subreq, req)) {
-               return;
-       }
-
-       tevent_req_set_callback(subreq, wbcInterfaceDetails_netbios_name, req);
-}
-
-static void wbcInterfaceDetails_netbios_name(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_interface_details_state *state = tevent_req_data(
-                       req, struct wbc_interface_details_state);
-       wbcErr wbc_status;
-
-       wbc_status  = wbcNetbiosName_recv(subreq, state->details,
-                                         &state->details->netbios_name);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       subreq = wbcDomainName_send(state, state->ev, state->wb_ctx);
-       if (tevent_req_nomem(subreq, req)) {
-               return;
-       }
-
-       tevent_req_set_callback(subreq, wbcInterfaceDetails_domain_name, req);
-}
-
-static void wbcInterfaceDetails_domain_name(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_interface_details_state *state = tevent_req_data(
-                       req, struct wbc_interface_details_state);
-       wbcErr wbc_status;
-
-       wbc_status  = wbcDomainName_recv(subreq, state->details,
-                                        &state->details->netbios_domain);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       subreq = wbcDomainInfo_send(state, state->ev, state->wb_ctx,
-                                   state->details->netbios_domain);
-       if (tevent_req_nomem(subreq, req)) {
-               return;
-       }
-
-       tevent_req_set_callback(subreq, wbcInterfaceDetails_domain_info, req);
-}
-
-static void wbcInterfaceDetails_domain_info(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_interface_details_state *state = tevent_req_data(
-                       req, struct wbc_interface_details_state);
-       struct wbcDomainInfo *domain;
-       wbcErr wbc_status;
-
-       wbc_status = wbcDomainInfo_recv(subreq, state, &domain);
-       TALLOC_FREE(subreq);
-       if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
-               tevent_req_done(req);
-               return;
-       }
-
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-       state->details->dns_domain = talloc_strdup(state->details,
-                                                  domain->dns_name);
-       if (tevent_req_nomem(state->details->dns_domain, req)) {
-               return;
-       }
-
-       TALLOC_FREE(domain);
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive useful information about the winbind service
- *
- * @param req          tevent_req containing the request
- * @param mem_ctx      talloc context to allocate memory from
- * @param *details     pointer to hold the struct wbcInterfaceDetails
- *
- * @return #wbcErr
- */
-
-wbcErr wbcInterfaceDetails_recv(struct tevent_req *req,
-                               TALLOC_CTX *mem_ctx,
-                               struct wbcInterfaceDetails **details)
-{
-       struct wbc_interface_details_state *state = tevent_req_data(
-                       req, struct wbc_interface_details_state);
-       wbcErr wbc_status;
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       *details = talloc_steal(mem_ctx, state->details);
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
 
 /**
  * @brief Query useful information about the winbind service
@@ -795,145 +125,6 @@ done:
        return wbc_status;
 }
 
-struct wbc_domain_info_state {
-       struct winbindd_request req;
-       struct wbcDomainInfo *info;
-};
-
-static void wbcDomainInfo_done(struct tevent_req *subreq);
-
-/**
- * @brief Request status of a given trusted domain
- *
- * @param mem_ctx      talloc context to allocate memory from
- * @param ev           tevent context to use for async requests
- * @param wb_ctx       winbind context
- * @param domain       domain to request status from
- *
- * @return tevent_req on success, NULL on failure
- */
-
-struct tevent_req *wbcDomainInfo_send(TALLOC_CTX *mem_ctx,
-                                     struct tevent_context *ev,
-                                     struct wb_context *wb_ctx,
-                                     const char *domain)
-{
-       struct tevent_req *req, *subreq;
-       struct wbc_domain_info_state *state;
-
-       if (!domain) {
-               return NULL;
-       }
-
-       req = tevent_req_create(mem_ctx, &state, struct wbc_domain_info_state);
-       if (req == NULL) {
-               return NULL;
-       }
-
-       state->info = talloc(state, struct wbcDomainInfo);
-       if (tevent_req_nomem(state->info, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       ZERO_STRUCT(state->req);
-
-       strncpy(state->req.domain_name, domain,
-               sizeof(state->req.domain_name)-1);
-
-       state->req.cmd = WINBINDD_DOMAIN_INFO;
-
-       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
-       if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
-       }
-
-       tevent_req_set_callback(subreq, wbcDomainInfo_done, req);
-       return req;
-}
-
-static void wbcDomainInfo_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-                       subreq, struct tevent_req);
-       struct wbc_domain_info_state *state = tevent_req_data(
-                       req, struct wbc_domain_info_state);
-       struct winbindd_response *resp;
-       wbcErr wbc_status;
-
-       wbc_status = wb_trans_recv(subreq, state, &resp);
-       TALLOC_FREE(subreq);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       state->info->short_name = talloc_strdup(state->info,
-                       resp->data.domain_info.name);
-       if (tevent_req_nomem(state->info->short_name, req)) {
-               return;
-       }
-
-       state->info->dns_name = talloc_strdup(state->info,
-                       resp->data.domain_info.alt_name);
-       if (tevent_req_nomem(state->info->dns_name, req)) {
-               return;
-       }
-
-       wbc_status = wbcStringToSid(resp->data.domain_info.sid,
-                                   &state->info->sid);
-       if (!WBC_ERROR_IS_OK(wbc_status)) {
-               tevent_req_error(req, wbc_status);
-               return;
-       }
-
-       if (resp->data.domain_info.native_mode) {
-               state->info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
-       }
-       if (resp->data.domain_info.active_directory) {
-               state->info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
-       }
-       if (resp->data.domain_info.primary) {
-               state->info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
-       }
-
-       TALLOC_FREE(resp);
-
-       tevent_req_done(req);
-}
-
-/**
- * @brief Receive information about a trusted domain
- *
- * @param req          tevent_req containing the request
- * @param mem_ctx      talloc context to allocate memory from
- * @param *dinfo       pointer to returned struct wbcDomainInfo
- *
- * @return #wbcErr
- */
-
-wbcErr wbcDomainInfo_recv(struct tevent_req *req,
-                         TALLOC_CTX *mem_ctx,
-                         struct wbcDomainInfo **dinfo)
-{
-       struct wbc_domain_info_state *state = tevent_req_data(
-                       req, struct wbc_domain_info_state);
-       wbcErr wbc_status;
-
-       if (tevent_req_is_wbcerr(req, &wbc_status)) {
-               tevent_req_received(req);
-               return wbc_status;
-       }
-
-       if (dinfo == NULL) {
-               tevent_req_received(req);
-               return WBC_ERR_INVALID_PARAM;
-       }
-
-       *dinfo = talloc_steal(mem_ctx, state->info);
-
-       tevent_req_received(req);
-       return WBC_ERR_SUCCESS;
-}
 
 /** @brief Lookup the current status of a trusted domain, sync wrapper
  *
diff --git a/nsswitch/libwbclient/wbc_util_async.c b/nsswitch/libwbclient/wbc_util_async.c
new file mode 100644 (file)
index 0000000..eb7fb04
--- /dev/null
@@ -0,0 +1,835 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Winbind client API
+
+   Copyright (C) 2009,2010 Kai Blin  <kai@samba.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 3 of the License, or (at your option) any later version.
+
+   This library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* Required Headers */
+
+#include "replace.h"
+#include "libwbclient.h"
+
+struct wbc_ping_state {
+       struct winbindd_request req;
+};
+
+static void wbcPing_done(struct tevent_req *subreq);
+
+/** @brief Ping winbind to see if the service is up and running
+ *
+ * @param mem_ctx      talloc context to allocate the request from
+ * @param ev           event context to use for async operation
+ * @param wb_ctx       winbind context to use
+ *
+ * @return Async request on successful dispatch of the request, NULL on error
+ */
+
+struct tevent_req *wbcPing_send(TALLOC_CTX *mem_ctx,
+                               struct tevent_context *ev,
+                               struct wb_context *wb_ctx)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_ping_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_ping_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+
+       state->req.cmd = WINBINDD_PING;
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcPing_done, req);
+       return req;
+}
+
+static void wbcPing_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_ping_state *state = tevent_req_data(
+                       req, struct wbc_ping_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+       TALLOC_FREE(resp);
+
+       tevent_req_done(req);
+}
+
+/** @brief Receive ping response from winbind
+ *
+ * @param req          async request sent in #wbcPing_send
+ *
+ * @return NT_STATUS_OK on success, an error status on error.
+ */
+
+wbcErr wbcPing_recv(struct tevent_req *req)
+{
+       wbcErr wbc_status;
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
+
+
+struct wbc_interface_version_state {
+       struct winbindd_request req;
+       uint32_t version;
+};
+
+static void wbcInterfaceVersion_done(struct tevent_req *subreq);
+
+/**
+ * @brief Request the interface version from winbind
+ *
+ * @param mem_ctx      talloc context to allocate memory from
+ * @param ev           tevent context to use for async requests
+ * @param wb_ctx       winbind context
+ *
+ * @return tevevt_req on success, NULL on failure
+ */
+
+struct tevent_req *wbcInterfaceVersion_send(TALLOC_CTX *mem_ctx,
+                                           struct tevent_context *ev,
+                                           struct wb_context *wb_ctx)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_interface_version_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_interface_version_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+       state->req.cmd = WINBINDD_INTERFACE_VERSION;
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcInterfaceVersion_done, req);
+
+       return req;
+}
+
+static void wbcInterfaceVersion_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_interface_version_state *state = tevent_req_data(
+                       req, struct wbc_interface_version_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+       state->version = resp->data.interface_version;
+       TALLOC_FREE(resp);
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive the winbind interface version
+ *
+ * @param req                  tevent_req containing the request
+ * @param interface_version    pointer to uint32_t to hold the interface
+ *                             version
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcInterfaceVersion_recv(struct tevent_req *req,
+                               uint32_t *interface_version)
+{
+       struct wbc_interface_version_state *state = tevent_req_data(
+                       req, struct wbc_interface_version_state);
+       wbcErr wbc_status;
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       *interface_version = state->version;
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
+
+struct wbc_info_state {
+       struct winbindd_request req;
+       char separator;
+       char *version_string;
+};
+
+static void wbcInfo_done(struct tevent_req *subreq);
+
+/**
+ * @brief Request information about the winbind service
+ *
+ * @param mem_ctx      talloc context to allocate memory from
+ * @param ev           tevent context to use for async requests
+ * @param wb_ctx       winbind context
+ *
+ * @return tevent_req on success, NULL on failure
+ */
+
+struct tevent_req *wbcInfo_send(TALLOC_CTX *mem_ctx,
+                               struct tevent_context *ev,
+                               struct wb_context *wb_ctx)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_info_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_info_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+       state->req.cmd = WINBINDD_INFO;
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcInfo_done, req);
+       return req;
+}
+
+static void wbcInfo_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_info_state *state = tevent_req_data(
+                       req, struct wbc_info_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+       state->version_string = talloc_strdup(state,
+                                       resp->data.info.samba_version);
+       if (tevent_req_nomem(state->version_string, subreq)) {
+               return;
+       }
+       state->separator = resp->data.info.winbind_separator;
+       TALLOC_FREE(resp);
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive information about the running winbind service
+ *
+ * @param req                  tevent_req containing the request
+ * @param mem_ctx              talloc context to allocate memory from
+ * @param winbind_separator    pointer to a char to hold the separator
+ * @param version_string       pointer to a string to hold the version string
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcInfo_recv(struct tevent_req *req,
+                   TALLOC_CTX *mem_ctx,
+                   char *winbind_separator,
+                   char **version_string)
+{
+       struct wbc_info_state *state = tevent_req_data(
+                       req, struct wbc_info_state);
+       wbcErr wbc_status;
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       *winbind_separator = state->separator;
+       *version_string = talloc_steal(mem_ctx, state->version_string);
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
+
+struct wbc_netbios_name_state {
+       struct winbindd_request req;
+       char *netbios_name;
+};
+
+static void wbcNetbiosName_done(struct tevent_req *subreq);
+
+/**
+ * @brief Request the machine's netbios name
+ *
+ * @param mem_ctx      talloc context to allocate memory from
+ * @param ev           tevent context to use for async requests
+ * @param wb_ctx       winbind context
+ *
+ * @return tevent_req on success, NULL on failure
+ */
+
+struct tevent_req *wbcNetbiosName_send(TALLOC_CTX *mem_ctx,
+                                      struct tevent_context *ev,
+                                      struct wb_context *wb_ctx)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_netbios_name_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_netbios_name_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+       state->req.cmd = WINBINDD_NETBIOS_NAME;
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcNetbiosName_done, req);
+       return req;
+}
+
+static void wbcNetbiosName_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_netbios_name_state *state = tevent_req_data(
+                       req, struct wbc_netbios_name_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+       state->netbios_name = talloc_strdup(state,
+                                       resp->data.info.samba_version);
+       if (tevent_req_nomem(state->netbios_name, subreq)) {
+               return;
+       }
+       TALLOC_FREE(resp);
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive the machine's netbios name
+ *
+ * @param req          tevent_req containing the request
+ * @param mem_ctx      talloc context to allocate memory from
+ * @param netbios_name pointer to a string to hold the netbios name
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcNetbiosName_recv(struct tevent_req *req,
+                          TALLOC_CTX *mem_ctx,
+                          char **netbios_name)
+{
+       struct wbc_netbios_name_state *state = tevent_req_data(
+                       req, struct wbc_netbios_name_state);
+       wbcErr wbc_status;
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       *netbios_name = talloc_steal(mem_ctx, state->netbios_name);
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
+
+struct wbc_domain_name_state {
+       struct winbindd_request req;
+       char *domain_name;
+};
+
+static void wbcDomainName_done(struct tevent_req *subreq);
+
+/**
+ * @brief Request the machine's domain name
+ *
+ * @param mem_ctx      talloc context to allocate memory from
+ * @param ev           tevent context to use for async requests
+ * @param wb_ctx       winbind context
+ *
+ * @return tevent_req on success, NULL on failure
+ */
+
+struct tevent_req *wbcDomainName_send(TALLOC_CTX *mem_ctx,
+                                     struct tevent_context *ev,
+                                     struct wb_context *wb_ctx)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_domain_name_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_domain_name_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       ZERO_STRUCT(state->req);
+       state->req.cmd = WINBINDD_DOMAIN_NAME;
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcDomainName_done, req);
+       return req;
+}
+
+static void wbcDomainName_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_domain_name_state *state = tevent_req_data(
+                       req, struct wbc_domain_name_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+       state->domain_name = talloc_strdup(state, resp->data.domain_name);
+       if (tevent_req_nomem(state->domain_name, subreq)) {
+               return;
+       }
+       TALLOC_FREE(resp);
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive the machine's domain name
+ *
+ * @param req          tevent_req containing the request
+ * @param mem_ctx      talloc context to allocate memory from
+ * @param domain_name  pointer to a string to hold the domain name
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcDomainName_recv(struct tevent_req *req,
+                         TALLOC_CTX *mem_ctx,
+                         char **domain_name)
+{
+       struct wbc_domain_name_state *state = tevent_req_data(
+                       req, struct wbc_domain_name_state);
+       wbcErr wbc_status;
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       *domain_name = talloc_steal(mem_ctx, state->domain_name);
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
+
+struct wbc_interface_details_state {
+       struct tevent_context *ev;
+       struct wb_context *wb_ctx;
+       struct wbcDomainInfo *dinfo;
+       struct wbcInterfaceDetails *details;
+};
+
+static void wbcInterfaceDetails_version(struct tevent_req *subreq);
+static void wbcInterfaceDetails_info(struct tevent_req *subreq);
+static void wbcInterfaceDetails_netbios_name(struct tevent_req *subreq);
+static void wbcInterfaceDetails_domain_name(struct tevent_req *subreq);
+static void wbcInterfaceDetails_domain_info(struct tevent_req *subreq);
+
+/**
+ * @brief Request some useful details about the winbind service
+ *
+ * @param mem_ctx      talloc context to allocate memory from
+ * @param ev           tevent context to use for async requests
+ * @param wb_ctx       winbind context
+ *
+ * @return tevent_req on success, NULL on failure
+ */
+
+struct tevent_req *wbcInterfaceDetails_send(TALLOC_CTX *mem_ctx,
+                                           struct tevent_context *ev,
+                                           struct wb_context *wb_ctx)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_interface_details_state *state;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct wbc_interface_details_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       state->ev = ev;
+       state->wb_ctx = wb_ctx;
+       state->details = talloc(state, struct wbcInterfaceDetails);
+       if (tevent_req_nomem(state->details, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       subreq = wbcInterfaceVersion_send(state, ev, wb_ctx);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcInterfaceDetails_version, req);
+       return req;
+}
+
+static void wbcInterfaceDetails_version(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_interface_details_state *state = tevent_req_data(
+                       req, struct wbc_interface_details_state);
+       wbcErr wbc_status;
+
+
+       wbc_status  = wbcInterfaceVersion_recv(subreq,
+                                       &state->details->interface_version);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       subreq = wbcInfo_send(state, state->ev, state->wb_ctx);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+
+       tevent_req_set_callback(subreq, wbcInterfaceDetails_info, req);
+}
+
+static void wbcInterfaceDetails_info(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_interface_details_state *state = tevent_req_data(
+                       req, struct wbc_interface_details_state);
+       wbcErr wbc_status;
+
+       wbc_status  = wbcInfo_recv(subreq, state->details,
+                                  &state->details->winbind_separator,
+                                  &state->details->winbind_version);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       subreq = wbcNetbiosName_send(state, state->ev, state->wb_ctx);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+
+       tevent_req_set_callback(subreq, wbcInterfaceDetails_netbios_name, req);
+}
+
+static void wbcInterfaceDetails_netbios_name(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_interface_details_state *state = tevent_req_data(
+                       req, struct wbc_interface_details_state);
+       wbcErr wbc_status;
+
+       wbc_status  = wbcNetbiosName_recv(subreq, state->details,
+                                         &state->details->netbios_name);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       subreq = wbcDomainName_send(state, state->ev, state->wb_ctx);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+
+       tevent_req_set_callback(subreq, wbcInterfaceDetails_domain_name, req);
+}
+
+static void wbcInterfaceDetails_domain_name(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_interface_details_state *state = tevent_req_data(
+                       req, struct wbc_interface_details_state);
+       wbcErr wbc_status;
+
+       wbc_status  = wbcDomainName_recv(subreq, state->details,
+                                        &state->details->netbios_domain);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       subreq = wbcDomainInfo_send(state, state->ev, state->wb_ctx,
+                                   state->details->netbios_domain);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+
+       tevent_req_set_callback(subreq, wbcInterfaceDetails_domain_info, req);
+}
+
+static void wbcInterfaceDetails_domain_info(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_interface_details_state *state = tevent_req_data(
+                       req, struct wbc_interface_details_state);
+       struct wbcDomainInfo *domain;
+       wbcErr wbc_status;
+
+       wbc_status = wbcDomainInfo_recv(subreq, state, &domain);
+       TALLOC_FREE(subreq);
+       if (wbc_status == WBC_ERR_DOMAIN_NOT_FOUND) {
+               tevent_req_done(req);
+               return;
+       }
+
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+       state->details->dns_domain = talloc_strdup(state->details,
+                                                  domain->dns_name);
+       if (tevent_req_nomem(state->details->dns_domain, req)) {
+               return;
+       }
+
+       TALLOC_FREE(domain);
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive useful information about the winbind service
+ *
+ * @param req          tevent_req containing the request
+ * @param mem_ctx      talloc context to allocate memory from
+ * @param *details     pointer to hold the struct wbcInterfaceDetails
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcInterfaceDetails_recv(struct tevent_req *req,
+                               TALLOC_CTX *mem_ctx,
+                               struct wbcInterfaceDetails **details)
+{
+       struct wbc_interface_details_state *state = tevent_req_data(
+                       req, struct wbc_interface_details_state);
+       wbcErr wbc_status;
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       *details = talloc_steal(mem_ctx, state->details);
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
+
+struct wbc_domain_info_state {
+       struct winbindd_request req;
+       struct wbcDomainInfo *info;
+};
+
+static void wbcDomainInfo_done(struct tevent_req *subreq);
+
+/**
+ * @brief Request status of a given trusted domain
+ *
+ * @param mem_ctx      talloc context to allocate memory from
+ * @param ev           tevent context to use for async requests
+ * @param wb_ctx       winbind context
+ * @param domain       domain to request status from
+ *
+ * @return tevent_req on success, NULL on failure
+ */
+
+struct tevent_req *wbcDomainInfo_send(TALLOC_CTX *mem_ctx,
+                                     struct tevent_context *ev,
+                                     struct wb_context *wb_ctx,
+                                     const char *domain)
+{
+       struct tevent_req *req, *subreq;
+       struct wbc_domain_info_state *state;
+
+       if (!domain) {
+               return NULL;
+       }
+
+       req = tevent_req_create(mem_ctx, &state, struct wbc_domain_info_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       state->info = talloc(state, struct wbcDomainInfo);
+       if (tevent_req_nomem(state->info, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       ZERO_STRUCT(state->req);
+
+       strncpy(state->req.domain_name, domain,
+               sizeof(state->req.domain_name)-1);
+
+       state->req.cmd = WINBINDD_DOMAIN_INFO;
+
+       subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       tevent_req_set_callback(subreq, wbcDomainInfo_done, req);
+       return req;
+}
+
+static void wbcDomainInfo_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+                       subreq, struct tevent_req);
+       struct wbc_domain_info_state *state = tevent_req_data(
+                       req, struct wbc_domain_info_state);
+       struct winbindd_response *resp;
+       wbcErr wbc_status;
+
+       wbc_status = wb_trans_recv(subreq, state, &resp);
+       TALLOC_FREE(subreq);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       state->info->short_name = talloc_strdup(state->info,
+                       resp->data.domain_info.name);
+       if (tevent_req_nomem(state->info->short_name, req)) {
+               return;
+       }
+
+       state->info->dns_name = talloc_strdup(state->info,
+                       resp->data.domain_info.alt_name);
+       if (tevent_req_nomem(state->info->dns_name, req)) {
+               return;
+       }
+
+       wbc_status = wbcStringToSid(resp->data.domain_info.sid,
+                                   &state->info->sid);
+       if (!WBC_ERROR_IS_OK(wbc_status)) {
+               tevent_req_error(req, wbc_status);
+               return;
+       }
+
+       if (resp->data.domain_info.native_mode) {
+               state->info->domain_flags |= WBC_DOMINFO_DOMAIN_NATIVE;
+       }
+       if (resp->data.domain_info.active_directory) {
+               state->info->domain_flags |= WBC_DOMINFO_DOMAIN_AD;
+       }
+       if (resp->data.domain_info.primary) {
+               state->info->domain_flags |= WBC_DOMINFO_DOMAIN_PRIMARY;
+       }
+
+       TALLOC_FREE(resp);
+
+       tevent_req_done(req);
+}
+
+/**
+ * @brief Receive information about a trusted domain
+ *
+ * @param req          tevent_req containing the request
+ * @param mem_ctx      talloc context to allocate memory from
+ * @param *dinfo       pointer to returned struct wbcDomainInfo
+ *
+ * @return #wbcErr
+ */
+
+wbcErr wbcDomainInfo_recv(struct tevent_req *req,
+                         TALLOC_CTX *mem_ctx,
+                         struct wbcDomainInfo **dinfo)
+{
+       struct wbc_domain_info_state *state = tevent_req_data(
+                       req, struct wbc_domain_info_state);
+       wbcErr wbc_status;
+
+       if (tevent_req_is_wbcerr(req, &wbc_status)) {
+               tevent_req_received(req);
+               return wbc_status;
+       }
+
+       if (dinfo == NULL) {
+               tevent_req_received(req);
+               return WBC_ERR_INVALID_PARAM;
+       }
+
+       *dinfo = talloc_steal(mem_ctx, state->info);
+
+       tevent_req_received(req);
+       return WBC_ERR_SUCCESS;
+}
index aad1bf5d576c14ada991a45921e09bec9e213997..c4093084c46afc7478958232e4fe3a43a11af7ad 100644 (file)
@@ -2006,11 +2006,17 @@ LIBWBCLIENT_OBJ0 = ../nsswitch/libwbclient/wbclient.o \
                  ../nsswitch/libwbclient/wbc_idmap.o \
                  ../nsswitch/libwbclient/wbc_sid.o \
                  ../nsswitch/libwbclient/wbc_guid.o \
-                 ../nsswitch/libwbclient/wbc_pam.o \
-                 ../nsswitch/libwbclient/wb_reqtrans.o \
-                 ../nsswitch/libwbclient/wbc_async.o
+                 ../nsswitch/libwbclient/wbc_pam.o
+
+LIBWBCLIENT_OBJ_ASYNC = ../nsswitch/libwbclient/wb_reqtrans.o \
+                 ../nsswitch/libwbclient/wbc_async.o \
+                 ../nsswitch/libwbclient/wbc_util_async.o\
+                 ../nsswitch/libwbclient/wbc_idmap_async.o \
+                 ../nsswitch/libwbclient/wbc_sid_async.o \
+                 ../nsswitch/libwbclient/wbc_pam_async.o
 
 LIBWBCLIENT_OBJ = $(LIBWBCLIENT_OBJ0) \
+                 $(LIBWBCLIENT_OBJ_ASYNC) \
                  $(WBCOMMON_OBJ) \
                  $(LIBREPLACE_OBJ) \
                  ../lib/async_req/async_sock.o \
@@ -2038,9 +2044,9 @@ $(LIBWBCLIENT_SHARED_TARGET): $(LIBWBCLIENT_SHARED_TARGET_SONAME)
        @rm -f $@
        @ln -f -s `basename $(LIBWBCLIENT_SHARED_TARGET_SONAME)` $@
 
-$(LIBWBCLIENT_STATIC_TARGET): $(BINARY_PREREQS) $(LIBWBCLIENT_OBJ0) $(WBCOMMON_OBJ)
+$(LIBWBCLIENT_STATIC_TARGET): $(BINARY_PREREQS) $(LIBWBCLIENT_OBJ0) $(LIBWBCLIENT_OBJ_ASYNC) $(WBCOMMON_OBJ)
        @echo Linking non-shared library $@
-       @-$(AR) -rc $@ $(LIBWBCLIENT_OBJ0) $(WBCOMMON_OBJ)
+       @-$(AR) -rc $@ $(LIBWBCLIENT_OBJ0) $(LIBWBCLIENT_OBJ_ASYNC) $(WBCOMMON_OBJ)
 
 libwbclient: $(LIBWBCLIENT)
 
index 2bd613d649b5e2f8d4fbbae8b5355c0988a59658..e93070aed78b6c73683be25750d46dd30d3f7b46 100644 (file)
@@ -6,7 +6,7 @@ SUBSYSTEM = smbtorture
 OUTPUT_TYPE = MERGED_OBJ
 INIT_FUNCTION = torture_winbind_init
 PRIVATE_DEPENDENCIES = \
-               LIBWBCLIENT LIBWINBIND-CLIENT torture PAM_ERRORS
+               LIBWBCLIENT LIBWBCLIENT_ASYNC LIBWINBIND-CLIENT torture PAM_ERRORS
 # End SUBSYSTEM TORTURE_WINBIND
 #################################