summaryrefslogtreecommitdiff
path: root/source4/winbind
diff options
context:
space:
mode:
Diffstat (limited to 'source4/winbind')
-rw-r--r--source4/winbind/config.mk79
-rw-r--r--source4/winbind/idmap.c176
-rw-r--r--source4/winbind/idmap.h6
-rw-r--r--source4/winbind/wb_async_helpers.c137
-rw-r--r--source4/winbind/wb_cmd_getdcname.c28
-rw-r--r--source4/winbind/wb_cmd_getgrent.c124
-rw-r--r--source4/winbind/wb_cmd_getgrgid.c8
-rw-r--r--source4/winbind/wb_cmd_getgrnam.c4
-rw-r--r--source4/winbind/wb_cmd_getgroups.c223
-rw-r--r--source4/winbind/wb_cmd_getpwent.c3
-rw-r--r--source4/winbind/wb_cmd_getpwnam.c6
-rw-r--r--source4/winbind/wb_cmd_getpwuid.c9
-rw-r--r--source4/winbind/wb_cmd_list_groups.c36
-rw-r--r--source4/winbind/wb_cmd_list_trustdom.c39
-rw-r--r--source4/winbind/wb_cmd_list_users.c12
-rw-r--r--source4/winbind/wb_cmd_lookupname.c1
-rw-r--r--source4/winbind/wb_cmd_lookupsid.c2
-rw-r--r--source4/winbind/wb_cmd_setgrent.c171
-rw-r--r--source4/winbind/wb_cmd_setpwent.c56
-rw-r--r--source4/winbind/wb_cmd_userdomgroups.c8
-rw-r--r--source4/winbind/wb_cmd_usersids.c34
-rw-r--r--source4/winbind/wb_connect_lsa.c23
-rw-r--r--source4/winbind/wb_connect_sam.c43
-rw-r--r--source4/winbind/wb_dom_info.c69
-rw-r--r--source4/winbind/wb_dom_info_trusted.c78
-rw-r--r--source4/winbind/wb_gid2sid.c22
-rw-r--r--source4/winbind/wb_init_domain.c68
-rw-r--r--source4/winbind/wb_irpc.c53
-rw-r--r--source4/winbind/wb_name2domain.c1
-rw-r--r--source4/winbind/wb_pam_auth.c42
-rw-r--r--source4/winbind/wb_sam_logon.c20
-rw-r--r--source4/winbind/wb_samba3_cmd.c534
-rw-r--r--source4/winbind/wb_samba3_protocol.c137
-rw-r--r--source4/winbind/wb_server.c251
-rw-r--r--source4/winbind/wb_server.h43
-rw-r--r--source4/winbind/wb_setup_domains.c42
-rw-r--r--source4/winbind/wb_sid2domain.c7
-rw-r--r--source4/winbind/wb_sid2gid.c18
-rw-r--r--source4/winbind/wb_sid2uid.c18
-rw-r--r--source4/winbind/wb_sids2xids.c27
-rw-r--r--source4/winbind/wb_uid2sid.c22
-rw-r--r--source4/winbind/wb_update_rodc_dns.c167
-rw-r--r--source4/winbind/wb_utils.c4
-rw-r--r--source4/winbind/wb_xids2sids.c27
-rw-r--r--source4/winbind/wscript_build30
45 files changed, 2048 insertions, 860 deletions
diff --git a/source4/winbind/config.mk b/source4/winbind/config.mk
deleted file mode 100644
index 16c1652fe4..0000000000
--- a/source4/winbind/config.mk
+++ /dev/null
@@ -1,79 +0,0 @@
-# server subsystem
-
-#######################
-# Start SUBSYSTEM WINBIND
-[MODULE::WINBIND]
-INIT_FUNCTION = server_service_winbind_init
-SUBSYSTEM = service
-PRIVATE_DEPENDENCIES = \
- WB_HELPER \
- IDMAP \
- NDR_WINBIND \
- process_model \
- RPC_NDR_LSA \
- dcerpc_samr \
- PAM_ERRORS \
- LIBCLI_LDAP \
- LIBSAMBA-NET
-# End SUBSYSTEM WINBIND
-#######################
-
-WINBIND_OBJ_FILES = $(addprefix $(winbindsrcdir)/, \
- wb_server.o \
- wb_setup_domains.o \
- wb_irpc.o \
- wb_samba3_protocol.o \
- wb_samba3_cmd.o \
- wb_init_domain.o \
- wb_dom_info.o \
- wb_dom_info_trusted.o \
- wb_sid2domain.o \
- wb_name2domain.o \
- wb_sids2xids.o \
- wb_xids2sids.o \
- wb_gid2sid.o \
- wb_sid2uid.o \
- wb_sid2gid.o \
- wb_uid2sid.o \
- wb_connect_lsa.o \
- wb_connect_sam.o \
- wb_cmd_lookupname.o \
- wb_cmd_lookupsid.o \
- wb_cmd_getdcname.o \
- wb_cmd_getgrnam.o \
- wb_cmd_getgrgid.o \
- wb_cmd_getpwnam.o \
- wb_cmd_getpwuid.o \
- wb_cmd_userdomgroups.o \
- wb_cmd_usersids.o \
- wb_cmd_list_groups.o \
- wb_cmd_list_trustdom.o \
- wb_cmd_list_users.o \
- wb_cmd_setpwent.o \
- wb_cmd_getpwent.o \
- wb_pam_auth.o \
- wb_sam_logon.o)
-
-$(eval $(call proto_header_template,$(winbindsrcdir)/wb_proto.h,$(WINBIND_OBJ_FILES:.o=.c)))
-
-################################################
-# Start SUBYSTEM WB_HELPER
-[SUBSYSTEM::WB_HELPER]
-PUBLIC_DEPENDENCIES = RPC_NDR_LSA dcerpc_samr
-# End SUBSYSTEM WB_HELPER
-################################################
-
-WB_HELPER_OBJ_FILES = $(addprefix $(winbindsrcdir)/, wb_async_helpers.o wb_utils.o)
-
-$(eval $(call proto_header_template,$(winbindsrcdir)/wb_helper.h,$(WB_HELPER_OBJ_FILES:.o=.c)))
-
-################################################
-# Start SUBYSTEM IDMAP
-[SUBSYSTEM::IDMAP]
-PUBLIC_DEPENDENCIES = SAMDB_COMMON
-# End SUBSYSTEM IDMAP
-################################################
-
-IDMAP_OBJ_FILES = $(winbindsrcdir)/idmap.o
-
-$(eval $(call proto_header_template,$(winbindsrcdir)/idmap_proto.h,$(IDMAP_OBJ_FILES:.o=.c)))
diff --git a/source4/winbind/idmap.c b/source4/winbind/idmap.c
index d0efbb159b..ff57064d48 100644
--- a/source4/winbind/idmap.c
+++ b/source4/winbind/idmap.c
@@ -21,12 +21,9 @@
#include "includes.h"
#include "auth/auth.h"
-#include "librpc/gen_ndr/lsa.h"
-#include "librpc/gen_ndr/samr.h"
#include "librpc/gen_ndr/ndr_security.h"
-#include "lib/ldb/include/ldb.h"
-#include "lib/ldb/include/ldb_errors.h"
-#include "lib/ldb_wrap.h"
+#include <ldb.h>
+#include "ldb_wrap.h"
#include "param/param.h"
#include "winbind/idmap.h"
#include "libcli/security/security.h"
@@ -100,9 +97,7 @@ static int idmap_msg_add_dom_sid(struct idmap_context *idmap_ctx,
struct ldb_val val;
enum ndr_err_code ndr_err;
- ndr_err = ndr_push_struct_blob(&val, mem_ctx,
- lp_iconv_convenience(idmap_ctx->lp_ctx),
- sid,
+ ndr_err = ndr_push_struct_blob(&val, mem_ctx, sid,
(ndr_push_flags_fn_t)ndr_push_dom_sid);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
@@ -137,7 +132,7 @@ static struct dom_sid *idmap_msg_get_dom_sid(TALLOC_CTX *mem_ctx,
return NULL;
}
- ndr_err = ndr_pull_struct_blob(val, sid, NULL, sid,
+ ndr_err = ndr_pull_struct_blob(val, sid, sid,
(ndr_pull_flags_fn_t)ndr_pull_dom_sid);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(sid);
@@ -157,7 +152,7 @@ static struct dom_sid *idmap_msg_get_dom_sid(TALLOC_CTX *mem_ctx,
*/
struct idmap_context *idmap_init(TALLOC_CTX *mem_ctx,
struct tevent_context *ev_ctx,
- struct loadparm_context *lp_ctx)
+ struct loadparm_context *lp_ctx)
{
struct idmap_context *idmap_ctx;
@@ -169,9 +164,9 @@ struct idmap_context *idmap_init(TALLOC_CTX *mem_ctx,
idmap_ctx->lp_ctx = lp_ctx;
idmap_ctx->ldb_ctx = ldb_wrap_connect(mem_ctx, ev_ctx, lp_ctx,
- lp_idmap_url(lp_ctx),
- system_session(mem_ctx, lp_ctx),
- NULL, 0, NULL);
+ lpcfg_idmap_url(lp_ctx),
+ system_session(lp_ctx),
+ NULL, 0);
if (idmap_ctx->ldb_ctx == NULL) {
return NULL;
}
@@ -202,8 +197,10 @@ struct idmap_context *idmap_init(TALLOC_CTX *mem_ctx,
* possible or some other NTSTATUS that is more descriptive on failure.
*/
-NTSTATUS idmap_xid_to_sid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
- const struct unixid *unixid, struct dom_sid **sid)
+static NTSTATUS idmap_xid_to_sid(struct idmap_context *idmap_ctx,
+ TALLOC_CTX *mem_ctx,
+ const struct unixid *unixid,
+ struct dom_sid **sid)
{
int ret;
NTSTATUS status = NT_STATUS_NONE_MAPPED;
@@ -221,7 +218,8 @@ NTSTATUS idmap_xid_to_sid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
id_type = "ID_TYPE_GID";
break;
default:
- DEBUG(1, ("unixid->type must be type gid or uid\n"));
+ DEBUG(1, ("unixid->type must be type gid or uid (got %u) for lookup with id %lu\n",
+ (unsigned)unixid->type, (unsigned long)unixid->id));
status = NT_STATUS_NONE_MAPPED;
goto failed;
}
@@ -281,19 +279,21 @@ failed:
*
* If no mapping exists, a new mapping will be created.
*
- * \todo Check if SIDs can be resolved if lp_idmap_trusted_only() == true
+ * \todo Check if SIDs can be resolved if lpcfg_idmap_trusted_only() == true
* \todo Fix backwards compatibility for Samba3
*
* \param idmap_ctx idmap context to use
* \param mem_ctx talloc context to use
* \param sid SID to map to an unixid struct
- * \param unixid pointer to a unixid struct pointer
+ * \param unixid pointer to a unixid struct
* \return NT_STATUS_OK on success, NT_STATUS_INVALID_SID if the sid is not from
* a trusted domain and idmap trusted only = true, NT_STATUS_NONE_MAPPED if the
* mapping failed.
*/
-NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
- const struct dom_sid *sid, struct unixid **unixid)
+static NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *sid,
+ struct unixid *unixid)
{
int ret;
NTSTATUS status = NT_STATUS_NONE_MAPPED;
@@ -311,15 +311,13 @@ NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
uint32_t rid;
DEBUG(6, ("This is a local unix uid, just calculate that.\n"));
status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid);
- if (!NT_STATUS_IS_OK(status)) goto failed;
-
- *unixid = talloc(mem_ctx, struct unixid);
- if (*unixid == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto failed;
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
}
- (*unixid)->id = rid;
- (*unixid)->type = ID_TYPE_UID;
+
+ unixid->id = rid;
+ unixid->type = ID_TYPE_UID;
talloc_free(tmp_ctx);
return NT_STATUS_OK;
@@ -329,15 +327,13 @@ NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
uint32_t rid;
DEBUG(6, ("This is a local unix gid, just calculate that.\n"));
status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid);
- if (!NT_STATUS_IS_OK(status)) goto failed;
-
- *unixid = talloc(mem_ctx, struct unixid);
- if (*unixid == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto failed;
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
}
- (*unixid)->id = rid;
- (*unixid)->type = ID_TYPE_GID;
+
+ unixid->id = rid;
+ unixid->type = ID_TYPE_GID;
talloc_free(tmp_ctx);
return NT_STATUS_OK;
@@ -348,8 +344,8 @@ NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
ldap_encode_ndr_dom_sid(tmp_ctx, sid));
if (ret != LDB_SUCCESS) {
DEBUG(1, ("Search failed: %s\n", ldb_errstring(ldb)));
- status = NT_STATUS_NONE_MAPPED;
- goto failed;
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NONE_MAPPED;
}
if (res->count == 1) {
@@ -359,30 +355,24 @@ NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
-1);
if (new_xid == (uint32_t) -1) {
DEBUG(1, ("Invalid xid mapping.\n"));
- status = NT_STATUS_NONE_MAPPED;
- goto failed;
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NONE_MAPPED;
}
if (type == NULL) {
DEBUG(1, ("Invalid type for mapping entry.\n"));
- status = NT_STATUS_NONE_MAPPED;
- goto failed;
- }
-
- *unixid = talloc(mem_ctx, struct unixid);
- if (*unixid == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto failed;
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NONE_MAPPED;
}
- (*unixid)->id = new_xid;
+ unixid->id = new_xid;
if (strcmp(type, "ID_TYPE_BOTH") == 0) {
- (*unixid)->type = ID_TYPE_BOTH;
+ unixid->type = ID_TYPE_BOTH;
} else if (strcmp(type, "ID_TYPE_UID") == 0) {
- (*unixid)->type = ID_TYPE_UID;
+ unixid->type = ID_TYPE_UID;
} else {
- (*unixid)->type = ID_TYPE_GID;
+ unixid->type = ID_TYPE_GID;
}
talloc_free(tmp_ctx);
@@ -414,7 +404,7 @@ NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
goto failed;
}
- /*FIXME: if lp_idmap_trusted_only() == true, check if SID can be
+ /*FIXME: if lpcfg_idmap_trusted_only() == true, check if SID can be
* resolved here. */
ret = idmap_get_bounds(idmap_ctx, &low, &high);
@@ -605,14 +595,8 @@ NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, TALLOC_CTX *mem_ctx,
goto failed;
}
- *unixid = talloc(mem_ctx, struct unixid);
- if (*unixid == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto failed;
- }
-
- (*unixid)->id = new_xid;
- (*unixid)->type = ID_TYPE_BOTH;
+ unixid->id = new_xid;
+ unixid->type = ID_TYPE_BOTH;
talloc_free(tmp_ctx);
return NT_STATUS_OK;
@@ -636,27 +620,31 @@ failed:
*/
NTSTATUS idmap_xids_to_sids(struct idmap_context *idmap_ctx,
- TALLOC_CTX *mem_ctx, int count,
- struct id_mapping *id)
+ TALLOC_CTX *mem_ctx,
+ struct id_map **id)
{
- int i;
- int error_count = 0;
-
- for (i = 0; i < count; ++i) {
- id[i].status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
- id[i].unixid, &id[i].sid);
- if (NT_STATUS_EQUAL(id[i].status, NT_STATUS_RETRY)) {
- id[i].status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
- id[i].unixid,
- &id[i].sid);
+ unsigned int i, error_count = 0;
+ NTSTATUS status;
+
+ for (i = 0; id && id[i]; i++) {
+ status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
+ &id[i]->xid, &id[i]->sid);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
+ status = idmap_xid_to_sid(idmap_ctx, mem_ctx,
+ &id[i]->xid,
+ &id[i]->sid);
}
- if (!NT_STATUS_IS_OK(id[i].status)) {
- DEBUG(1, ("idmapping xid_to_sid failed for id[%d]\n", i));
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("idmapping xid_to_sid failed for id[%d]=%lu: %s\n",
+ i, (unsigned long)id[i]->xid.id, nt_errstr(status)));
error_count++;
+ id[i]->status = ID_UNMAPPED;
+ } else {
+ id[i]->status = ID_MAPPED;
}
}
- if (error_count == count) {
+ if (error_count == i) {
/* Mapping did not work at all. */
return NT_STATUS_NONE_MAPPED;
} else if (error_count > 0) {
@@ -681,27 +669,33 @@ NTSTATUS idmap_xids_to_sids(struct idmap_context *idmap_ctx,
*/
NTSTATUS idmap_sids_to_xids(struct idmap_context *idmap_ctx,
- TALLOC_CTX *mem_ctx, int count,
- struct id_mapping *id)
+ TALLOC_CTX *mem_ctx,
+ struct id_map **id)
{
- int i;
- int error_count = 0;
-
- for (i = 0; i < count; ++i) {
- id[i].status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
- id[i].sid, &id[i].unixid);
- if (NT_STATUS_EQUAL(id[i].status, NT_STATUS_RETRY)) {
- id[i].status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
- id[i].sid,
- &id[i].unixid);
+ unsigned int i, error_count = 0;
+ NTSTATUS status;
+
+ for (i = 0; id && id[i]; i++) {
+ status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
+ id[i]->sid, &id[i]->xid);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
+ status = idmap_sid_to_xid(idmap_ctx, mem_ctx,
+ id[i]->sid,
+ &id[i]->xid);
}
- if (!NT_STATUS_IS_OK(id[i].status)) {
- DEBUG(1, ("idmapping sid_to_xid failed for id[%d]\n", i));
+ if (!NT_STATUS_IS_OK(status)) {
+ char *str = dom_sid_string(mem_ctx, id[i]->sid);
+ DEBUG(1, ("idmapping sid_to_xid failed for id[%d]=%s: %s\n",
+ i, str, nt_errstr(status)));
+ talloc_free(str);
error_count++;
+ id[i]->status = ID_UNMAPPED;
+ } else {
+ id[i]->status = ID_MAPPED;
}
}
- if (error_count == count) {
+ if (error_count == i) {
/* Mapping did not work at all. */
return NT_STATUS_NONE_MAPPED;
} else if (error_count > 0) {
diff --git a/source4/winbind/idmap.h b/source4/winbind/idmap.h
index 7429466bed..bf048e9758 100644
--- a/source4/winbind/idmap.h
+++ b/source4/winbind/idmap.h
@@ -19,10 +19,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _IDMAP_H_
-#define _IDMAP_H_
+#ifndef _WINBIND_IDMAP_H_
+#define _WINBIND_IDMAP_H_
-#include "librpc/gen_ndr/winbind.h"
+#include "librpc/gen_ndr/idmap.h"
struct idmap_context {
struct loadparm_context *lp_ctx;
diff --git a/source4/winbind/wb_async_helpers.c b/source4/winbind/wb_async_helpers.c
index a50a0fe473..5d530ca149 100644
--- a/source4/winbind/wb_async_helpers.c
+++ b/source4/winbind/wb_async_helpers.c
@@ -21,23 +21,18 @@
*/
#include "includes.h"
+#include <tevent.h>
#include "libcli/composite/composite.h"
#include "winbind/wb_async_helpers.h"
-#include "lib/messaging/irpc.h"
-#include "librpc/gen_ndr/irpc.h"
-#include "auth/credentials/credentials.h"
#include "libcli/security/security.h"
-#include "libcli/auth/libcli_auth.h"
-#include "librpc/gen_ndr/ndr_netlogon_c.h"
#include "librpc/gen_ndr/ndr_lsa_c.h"
#include "librpc/gen_ndr/ndr_samr_c.h"
-#include "winbind/wb_helper.h"
struct lsa_lookupsids_state {
struct composite_context *ctx;
- int num_sids;
+ uint32_t num_sids;
struct lsa_LookupSids r;
struct lsa_SidArray sids;
struct lsa_TransNameArray names;
@@ -46,18 +41,18 @@ struct lsa_lookupsids_state {
struct wb_sid_object **result;
};
-static void lsa_lookupsids_recv_names(struct rpc_request *req);
+static void lsa_lookupsids_recv_names(struct tevent_req *subreq);
struct composite_context *wb_lsa_lookupsids_send(TALLOC_CTX *mem_ctx,
struct dcerpc_pipe *lsa_pipe,
struct policy_handle *handle,
- int num_sids,
+ uint32_t num_sids,
const struct dom_sid **sids)
{
struct composite_context *result;
- struct rpc_request *req;
struct lsa_lookupsids_state *state;
- int i;
+ uint32_t i;
+ struct tevent_req *subreq;
result = composite_create(mem_ctx, lsa_pipe->conn->event_ctx);
if (result == NULL) goto failed;
@@ -94,11 +89,13 @@ struct composite_context *wb_lsa_lookupsids_send(TALLOC_CTX *mem_ctx,
state->r.out.count = &state->count;
state->r.out.domains = &state->domains;
- req = dcerpc_lsa_LookupSids_send(lsa_pipe, state, &state->r);
- if (req == NULL) goto failed;
+ subreq = dcerpc_lsa_LookupSids_r_send(state,
+ result->event_ctx,
+ lsa_pipe->binding_handle,
+ &state->r);
+ if (subreq == NULL) goto failed;
+ tevent_req_set_callback(subreq, lsa_lookupsids_recv_names, state);
- req->async.callback = lsa_lookupsids_recv_names;
- req->async.private_data = state;
return result;
failed:
@@ -106,14 +103,15 @@ struct composite_context *wb_lsa_lookupsids_send(TALLOC_CTX *mem_ctx,
return NULL;
}
-static void lsa_lookupsids_recv_names(struct rpc_request *req)
+static void lsa_lookupsids_recv_names(struct tevent_req *subreq)
{
struct lsa_lookupsids_state *state =
- talloc_get_type(req->async.private_data,
- struct lsa_lookupsids_state);
- int i;
+ tevent_req_callback_data(subreq,
+ struct lsa_lookupsids_state);
+ uint32_t i;
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_lsa_LookupSids_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->r.out.result;
if (!NT_STATUS_IS_OK(state->ctx->status) &&
@@ -195,20 +193,20 @@ struct lsa_lookupnames_state {
struct wb_sid_object **result;
};
-static void lsa_lookupnames_recv_sids(struct rpc_request *req);
+static void lsa_lookupnames_recv_sids(struct tevent_req *subreq);
struct composite_context *wb_lsa_lookupnames_send(TALLOC_CTX *mem_ctx,
struct dcerpc_pipe *lsa_pipe,
struct policy_handle *handle,
- int num_names,
+ uint32_t num_names,
const char **names)
{
struct composite_context *result;
- struct rpc_request *req;
struct lsa_lookupnames_state *state;
+ struct tevent_req *subreq;
struct lsa_String *lsa_names;
- int i;
+ uint32_t i;
result = composite_create(mem_ctx, lsa_pipe->conn->event_ctx);
if (result == NULL) goto failed;
@@ -243,11 +241,13 @@ struct composite_context *wb_lsa_lookupnames_send(TALLOC_CTX *mem_ctx,
state->r.out.sids = &state->sids;
state->r.out.domains = &state->domains;
- req = dcerpc_lsa_LookupNames_send(lsa_pipe, state, &state->r);
- if (req == NULL) goto failed;
+ subreq = dcerpc_lsa_LookupNames_r_send(state,
+ result->event_ctx,
+ lsa_pipe->binding_handle,
+ &state->r);
+ if (subreq == NULL) goto failed;
+ tevent_req_set_callback(subreq, lsa_lookupnames_recv_sids, state);
- req->async.callback = lsa_lookupnames_recv_sids;
- req->async.private_data = state;
return result;
failed:
@@ -255,14 +255,15 @@ struct composite_context *wb_lsa_lookupnames_send(TALLOC_CTX *mem_ctx,
return NULL;
}
-static void lsa_lookupnames_recv_sids(struct rpc_request *req)
+static void lsa_lookupnames_recv_sids(struct tevent_req *subreq)
{
struct lsa_lookupnames_state *state =
- talloc_get_type(req->async.private_data,
- struct lsa_lookupnames_state);
- int i;
+ tevent_req_callback_data(subreq,
+ struct lsa_lookupnames_state);
+ uint32_t i;
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_lsa_LookupNames_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->r.out.result;
if (!NT_STATUS_IS_OK(state->ctx->status) &&
@@ -322,7 +323,7 @@ struct samr_getuserdomgroups_state {
struct composite_context *ctx;
struct dcerpc_pipe *samr_pipe;
- int num_rids;
+ uint32_t num_rids;
uint32_t *rids;
struct samr_RidWithAttributeArray *rid_array;
@@ -333,9 +334,9 @@ struct samr_getuserdomgroups_state {
struct samr_Close c;
};
-static void samr_usergroups_recv_open(struct rpc_request *req);
-static void samr_usergroups_recv_groups(struct rpc_request *req);
-static void samr_usergroups_recv_close(struct rpc_request *req);
+static void samr_usergroups_recv_open(struct tevent_req *subreq);
+static void samr_usergroups_recv_groups(struct tevent_req *subreq);
+static void samr_usergroups_recv_close(struct tevent_req *subreq);
struct composite_context *wb_samr_userdomgroups_send(TALLOC_CTX *mem_ctx,
struct dcerpc_pipe *samr_pipe,
@@ -343,8 +344,8 @@ struct composite_context *wb_samr_userdomgroups_send(TALLOC_CTX *mem_ctx,
uint32_t rid)
{
struct composite_context *result;
- struct rpc_request *req;
struct samr_getuserdomgroups_state *state;
+ struct tevent_req *subreq;
result = composite_create(mem_ctx, samr_pipe->conn->event_ctx);
if (result == NULL) goto failed;
@@ -364,11 +365,13 @@ struct composite_context *wb_samr_userdomgroups_send(TALLOC_CTX *mem_ctx,
state->o.in.rid = rid;
state->o.out.user_handle = state->user_handle;
- req = dcerpc_samr_OpenUser_send(state->samr_pipe, state, &state->o);
- if (req == NULL) goto failed;
+ subreq = dcerpc_samr_OpenUser_r_send(state,
+ result->event_ctx,
+ state->samr_pipe->binding_handle,
+ &state->o);
+ if (subreq == NULL) goto failed;
+ tevent_req_set_callback(subreq, samr_usergroups_recv_open, state);
- req->async.callback = samr_usergroups_recv_open;
- req->async.private_data = state;
return result;
failed:
@@ -376,13 +379,14 @@ struct composite_context *wb_samr_userdomgroups_send(TALLOC_CTX *mem_ctx,
return NULL;
}
-static void samr_usergroups_recv_open(struct rpc_request *req)
+static void samr_usergroups_recv_open(struct tevent_req *subreq)
{
struct samr_getuserdomgroups_state *state =
- talloc_get_type(req->async.private_data,
- struct samr_getuserdomgroups_state);
+ tevent_req_callback_data(subreq,
+ struct samr_getuserdomgroups_state);
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_samr_OpenUser_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->o.out.result;
if (!composite_is_ok(state->ctx)) return;
@@ -390,19 +394,22 @@ static void samr_usergroups_recv_open(struct rpc_request *req)
state->g.in.user_handle = state->user_handle;
state->g.out.rids = &state->rid_array;
- req = dcerpc_samr_GetGroupsForUser_send(state->samr_pipe, state,
- &state->g);
- composite_continue_rpc(state->ctx, req, samr_usergroups_recv_groups,
- state);
+ subreq = dcerpc_samr_GetGroupsForUser_r_send(state,
+ state->ctx->event_ctx,
+ state->samr_pipe->binding_handle,
+ &state->g);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, samr_usergroups_recv_groups, state);
}
-static void samr_usergroups_recv_groups(struct rpc_request *req)
+static void samr_usergroups_recv_groups(struct tevent_req *subreq)
{
struct samr_getuserdomgroups_state *state =
- talloc_get_type(req->async.private_data,
- struct samr_getuserdomgroups_state);
+ tevent_req_callback_data(subreq,
+ struct samr_getuserdomgroups_state);
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_samr_GetGroupsForUser_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->g.out.result;
if (!composite_is_ok(state->ctx)) return;
@@ -410,18 +417,22 @@ static void samr_usergroups_recv_groups(struct rpc_request *req)
state->c.in.handle = state->user_handle;
state->c.out.handle = state->user_handle;
- req = dcerpc_samr_Close_send(state->samr_pipe, state, &state->c);
- composite_continue_rpc(state->ctx, req, samr_usergroups_recv_close,
- state);
+ subreq = dcerpc_samr_Close_r_send(state,
+ state->ctx->event_ctx,
+ state->samr_pipe->binding_handle,
+ &state->c);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, samr_usergroups_recv_close, state);
}
-static void samr_usergroups_recv_close(struct rpc_request *req)
+static void samr_usergroups_recv_close(struct tevent_req *subreq)
{
struct samr_getuserdomgroups_state *state =
- talloc_get_type(req->async.private_data,
- struct samr_getuserdomgroups_state);
+ tevent_req_callback_data(subreq,
+ struct samr_getuserdomgroups_state);
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_samr_Close_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->c.out.result;
if (!composite_is_ok(state->ctx)) return;
@@ -431,13 +442,13 @@ static void samr_usergroups_recv_close(struct rpc_request *req)
NTSTATUS wb_samr_userdomgroups_recv(struct composite_context *ctx,
TALLOC_CTX *mem_ctx,
- int *num_rids, uint32_t **rids)
+ uint32_t *num_rids, uint32_t **rids)
{
struct samr_getuserdomgroups_state *state =
talloc_get_type(ctx->private_data,
struct samr_getuserdomgroups_state);
- int i;
+ uint32_t i;
NTSTATUS status = composite_wait(ctx);
if (!NT_STATUS_IS_OK(status)) goto done;
diff --git a/source4/winbind/wb_cmd_getdcname.c b/source4/winbind/wb_cmd_getdcname.c
index 66dcbf9d7b..f3c2482579 100644
--- a/source4/winbind/wb_cmd_getdcname.c
+++ b/source4/winbind/wb_cmd_getdcname.c
@@ -34,7 +34,7 @@ struct cmd_getdcname_state {
};
static void getdcname_recv_domain(struct composite_context *ctx);
-static void getdcname_recv_dcname(struct rpc_request *req);
+static void getdcname_recv_dcname(struct tevent_req *subreq);
struct composite_context *wb_cmd_getdcname_send(TALLOC_CTX *mem_ctx,
struct wbsrv_service *service,
@@ -72,7 +72,7 @@ static void getdcname_recv_domain(struct composite_context *ctx)
talloc_get_type(ctx->async.private_data,
struct cmd_getdcname_state);
struct wbsrv_domain *domain;
- struct rpc_request *req;
+ struct tevent_req *subreq;
state->ctx->status = wb_sid2domain_recv(ctx, &domain);
if (!composite_is_ok(state->ctx)) return;
@@ -83,20 +83,23 @@ static void getdcname_recv_domain(struct composite_context *ctx)
state->g.in.domainname = state->domain_name;
state->g.out.dcname = talloc(state, const char *);
- req = dcerpc_netr_GetAnyDCName_send(domain->netlogon_pipe, state,
- &state->g);
- if (composite_nomem(req, state->ctx)) return;
+ subreq = dcerpc_netr_GetAnyDCName_r_send(state,
+ state->ctx->event_ctx,
+ domain->netlogon_pipe->binding_handle,
+ &state->g);
+ if (composite_nomem(subreq, state->ctx)) return;
- composite_continue_rpc(state->ctx, req, getdcname_recv_dcname, state);
+ tevent_req_set_callback(subreq, getdcname_recv_dcname, state);
}
-static void getdcname_recv_dcname(struct rpc_request *req)
+static void getdcname_recv_dcname(struct tevent_req *subreq)
{
struct cmd_getdcname_state *state =
- talloc_get_type(req->async.private_data,
- struct cmd_getdcname_state);
+ tevent_req_callback_data(subreq,
+ struct cmd_getdcname_state);
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_netr_GetAnyDCName_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = werror_to_ntstatus(state->g.out.result);
if (!composite_is_ok(state->ctx)) return;
@@ -111,6 +114,11 @@ NTSTATUS wb_cmd_getdcname_recv(struct composite_context *c,
struct cmd_getdcname_state *state =
talloc_get_type(c->private_data, struct cmd_getdcname_state);
NTSTATUS status = composite_wait(c);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN)) {
+ /* special case: queried DC is PDC */
+ state->g.out.dcname = &state->g.in.logon_server;
+ status = NT_STATUS_OK;
+ }
if (NT_STATUS_IS_OK(status)) {
const char *p = *(state->g.out.dcname);
if (*p == '\\') p += 1;
diff --git a/source4/winbind/wb_cmd_getgrent.c b/source4/winbind/wb_cmd_getgrent.c
new file mode 100644
index 0000000000..79a3aff852
--- /dev/null
+++ b/source4/winbind/wb_cmd_getgrent.c
@@ -0,0 +1,124 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Command backend for getgrent
+
+ Copyright (C) Matthieu Patou 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "winbind/wb_server.h"
+#include "smbd/service_task.h"
+
+struct cmd_getgrent_state {
+ struct composite_context *ctx;
+ struct wbsrv_service *service;
+
+ struct wbsrv_grent *grent;
+ uint32_t max_groups;
+
+ uint32_t num_groups;
+ struct winbindd_gr *result;
+};
+
+static void cmd_getgrent_recv_grnam(struct composite_context *ctx);
+#if 0 /*FIXME: implement this*/
+static void cmd_getgrent_recv_user_list(struct composite_context *ctx);
+#endif
+
+struct composite_context *wb_cmd_getgrent_send(TALLOC_CTX *mem_ctx,
+ struct wbsrv_service *service, struct wbsrv_grent *grent,
+ uint32_t max_groups)
+{
+ struct composite_context *ctx, *result;
+ struct cmd_getgrent_state *state;
+
+ DEBUG(5, ("wb_cmd_getgrent_send called\n"));
+
+ result = composite_create(mem_ctx, service->task->event_ctx);
+ if (!result) return NULL;
+
+ state = talloc(mem_ctx, struct cmd_getgrent_state);
+ if (composite_nomem(state, result)) return result;
+
+ state->ctx = result;
+ result->private_data = state;
+ state->service = service;
+ state->grent = grent;
+ state->max_groups = max_groups;
+ state->num_groups = 0;
+
+ /* If there are groups left in the libnet_GroupList and we're below the
+ * maximum number of groups to get per winbind getgrent call, use
+ * getgrnam to get the winbindd_gr struct */
+ if (grent->page_index < grent->group_list->out.count) {
+ int idx = grent->page_index;
+ char *groupname = talloc_strdup(state,
+ grent->group_list->out.groups[idx].groupname);
+
+ grent->page_index++;
+ ctx = wb_cmd_getgrnam_send(state, service, groupname);
+ if (composite_nomem(ctx, state->ctx)) return result;
+
+ composite_continue(state->ctx, ctx, cmd_getgrent_recv_grnam,
+ state);
+ } else {
+ /* If there is no valid group left, call libnet_GroupList to get a new
+ * list of group. */
+ composite_error(state->ctx, NT_STATUS_NO_MORE_ENTRIES);
+ }
+ return result;
+}
+
+static void cmd_getgrent_recv_grnam(struct composite_context *ctx)
+{
+ struct cmd_getgrent_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct cmd_getgrent_state);
+ struct winbindd_gr *gr;
+
+ DEBUG(5, ("cmd_getgrent_recv_grnam called\n"));
+
+ state->ctx->status = wb_cmd_getgrnam_recv(ctx, state, &gr);
+ if (!composite_is_ok(state->ctx)) return;
+
+ /*FIXME: Cheat for now and only get one group per call */
+ state->result = gr;
+
+ composite_done(state->ctx);
+}
+
+NTSTATUS wb_cmd_getgrent_recv(struct composite_context *ctx,
+ TALLOC_CTX *mem_ctx, struct winbindd_gr **gr,
+ uint32_t *num_groups)
+{
+ NTSTATUS status = composite_wait(ctx);
+
+ DEBUG(5, ("wb_cmd_getgrent_recv called\n"));
+
+ if (NT_STATUS_IS_OK(status)) {
+ struct cmd_getgrent_state *state =
+ talloc_get_type(ctx->private_data,
+ struct cmd_getgrent_state);
+ *gr = talloc_steal(mem_ctx, state->result);
+ /*FIXME: Cheat and only get one group */
+ *num_groups = 1;
+ }
+
+ talloc_free(ctx);
+ return status;
+}
diff --git a/source4/winbind/wb_cmd_getgrgid.c b/source4/winbind/wb_cmd_getgrgid.c
index 80f4e9cfc3..fe946ed257 100644
--- a/source4/winbind/wb_cmd_getgrgid.c
+++ b/source4/winbind/wb_cmd_getgrgid.c
@@ -22,13 +22,7 @@
#include "includes.h"
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
-#include "winbind/wb_helper.h"
#include "smbd/service_task.h"
-#include "libnet/libnet_proto.h"
-#include "param/param.h"
-#include "libcli/security/proto.h"
-#include "auth/credentials/credentials.h"
struct cmd_getgrgid_state {
struct composite_context *ctx;
@@ -136,7 +130,7 @@ static void cmd_getgrgid_recv_group_info(struct composite_context *ctx)
DEBUG(5, ("cmd_getgrgid_recv_group_info called\n"));
- gr = talloc(state, struct winbindd_gr);
+ gr = talloc_zero(state, struct winbindd_gr);
if (composite_nomem(gr, state->ctx)) return;
group_info = talloc(state, struct libnet_GroupInfo);
diff --git a/source4/winbind/wb_cmd_getgrnam.c b/source4/winbind/wb_cmd_getgrnam.c
index bfc30fc7a6..7073209306 100644
--- a/source4/winbind/wb_cmd_getgrnam.c
+++ b/source4/winbind/wb_cmd_getgrnam.c
@@ -22,12 +22,8 @@
#include "includes.h"
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
-#include "param/param.h"
#include "winbind/wb_helper.h"
#include "smbd/service_task.h"
-#include "libnet/libnet_proto.h"
-#include "libcli/security/proto.h"
struct cmd_getgrnam_state {
struct composite_context *ctx;
diff --git a/source4/winbind/wb_cmd_getgroups.c b/source4/winbind/wb_cmd_getgroups.c
new file mode 100644
index 0000000000..29c5205369
--- /dev/null
+++ b/source4/winbind/wb_cmd_getgroups.c
@@ -0,0 +1,223 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Backend for getgroups
+
+ Copyright (C) Matthieu Patou 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "winbind/wb_server.h"
+#include "smbd/service_task.h"
+#include "libcli/security/security.h"
+
+struct cmd_getgroups_state {
+ struct composite_context *ctx;
+ struct wbsrv_service *service;
+ char* username;
+ uint32_t num_groups;
+ uint32_t current_group;
+ struct dom_sid **sids;
+
+ gid_t *gids;
+};
+
+/* The idea is to get the groups for a user
+ We receive one user from this we search for his uid
+ From the uid we search for his SID
+ From the SID we search for the list of groups
+ And with the list of groups we search for each group its gid
+*/
+static void cmd_getgroups_recv_pwnam(struct composite_context *ctx);
+static void wb_getgroups_uid2sid_recv(struct composite_context *ctx);
+static void wb_getgroups_userdomsgroups_recv(struct composite_context *ctx);
+static void cmd_getgroups_recv_gid(struct composite_context *ctx);
+
+/*
+ Ask for the uid from the username
+*/
+struct composite_context *wb_cmd_getgroups_send(TALLOC_CTX *mem_ctx,
+ struct wbsrv_service *service,
+ const char* username)
+{
+ struct composite_context *ctx, *result;
+ struct cmd_getgroups_state *state;
+
+ DEBUG(5, ("wb_cmd_getgroups_send called\n"));
+
+ result = composite_create(mem_ctx, service->task->event_ctx);
+ if (!result) return NULL;
+
+ state = talloc(mem_ctx, struct cmd_getgroups_state);
+ if (composite_nomem(state, result)) return result;
+
+ state->ctx = result;
+ result->private_data = state;
+ state->service = service;
+ state->num_groups = 0;
+
+ state->username = talloc_strdup(state,username);
+ if (composite_nomem(state->username, result)) return result;
+
+ ctx = wb_cmd_getpwnam_send(state, service, username);
+ if (composite_nomem(ctx, result)) return result;
+
+ composite_continue(result, ctx, cmd_getgroups_recv_pwnam, state);
+ return result;
+}
+
+/*
+ Receive the uid and send request for SID
+*/
+static void cmd_getgroups_recv_pwnam(struct composite_context *ctx)
+{
+ struct composite_context *res;
+ struct cmd_getgroups_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct cmd_getgroups_state);
+ struct winbindd_pw *pw;
+ struct wbsrv_service *service = state->service;
+
+ DEBUG(5, ("cmd_getgroups_recv_pwnam called\n"));
+
+ state->ctx->status = wb_cmd_getpwnam_recv(ctx, state, &pw);
+ if (composite_is_ok(state->ctx)) {
+ res = wb_uid2sid_send(state, service, pw->pw_uid);
+ if (res == NULL) {
+ composite_error(state->ctx, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ DEBUG(6, ("cmd_getgroups_recv_pwnam uid %d\n",pw->pw_uid));
+
+ composite_continue(ctx, res, wb_getgroups_uid2sid_recv, state);
+ }
+}
+
+/*
+ Receive the SID and request groups through the userdomgroups helper
+*/
+static void wb_getgroups_uid2sid_recv(struct composite_context *ctx)
+{
+ struct composite_context *res;
+ struct cmd_getgroups_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct cmd_getgroups_state);
+ NTSTATUS status;
+ struct dom_sid *sid;
+ char *sid_str;
+
+ DEBUG(5, ("wb_getgroups_uid2sid_recv called\n"));
+
+ status = wb_uid2sid_recv(ctx, state, &sid);
+ if(NT_STATUS_IS_OK(status)) {
+ sid_str = dom_sid_string(state, sid);
+
+ /* If the conversion failed, bail out with a failure. */
+ if (sid_str != NULL) {
+ DEBUG(7, ("wb_getgroups_uid2sid_recv SID = %s\n",sid_str));
+ /* Ok got the SID now get the groups */
+ res = wb_cmd_userdomgroups_send(state, state->service, sid);
+ if (res == NULL) {
+ composite_error(state->ctx,
+ NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ composite_continue(ctx, res, wb_getgroups_userdomsgroups_recv, state);
+ } else {
+ composite_error(state->ctx, NT_STATUS_UNSUCCESSFUL);
+ }
+ }
+}
+
+/*
+ Receive groups and search for uid for the first group
+*/
+static void wb_getgroups_userdomsgroups_recv(struct composite_context *ctx) {
+ struct cmd_getgroups_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct cmd_getgroups_state);
+ uint32_t num_sids;
+ struct dom_sid **sids;
+
+ DEBUG(5, ("wb_getgroups_userdomsgroups_recv called\n"));
+ state->ctx->status = wb_cmd_userdomgroups_recv(ctx,state,&num_sids,&sids);
+ if (!composite_is_ok(state->ctx)) return;
+
+ DEBUG(5, ("wb_getgroups_userdomsgroups_recv %d groups\n",num_sids));
+
+ state->sids=sids;
+ state->num_groups=num_sids;
+ state->current_group=0;
+
+ if(num_sids > 0) {
+ state->gids = talloc_array(state, gid_t, state->num_groups);
+ ctx = wb_sid2gid_send(state, state->service, state->sids[state->current_group]);
+ composite_continue(state->ctx, ctx, cmd_getgroups_recv_gid, state);
+ } else {
+ composite_done(state->ctx);
+ }
+}
+
+/*
+ Receive and uid the previous searched group and request the uid for the next one
+*/
+static void cmd_getgroups_recv_gid(struct composite_context *ctx)
+{
+ struct cmd_getgroups_state *state =
+ talloc_get_type(ctx->async.private_data,
+ struct cmd_getgroups_state);
+ gid_t gid;
+
+ DEBUG(5, ("cmd_getgroups_recv_gid called\n"));
+
+ state->ctx->status = wb_sid2gid_recv(ctx, &gid);
+ if(!composite_is_ok(state->ctx)) return;
+
+ state->gids[state->current_group] = gid;
+ DEBUG(5, ("cmd_getgroups_recv_gid group %d \n",state->current_group));
+
+ state->current_group++;
+ if(state->current_group < state->num_groups ) {
+ ctx = wb_sid2gid_send(state, state->service, state->sids[state->current_group]);
+ composite_continue(state->ctx, ctx, cmd_getgroups_recv_gid, state);
+ } else {
+ composite_done(state->ctx);
+ }
+}
+
+/*
+ Return list of uids when finished
+*/
+NTSTATUS wb_cmd_getgroups_recv(struct composite_context *ctx,
+ TALLOC_CTX *mem_ctx, gid_t **groups,
+ uint32_t *num_groups)
+{
+ NTSTATUS status = composite_wait(ctx);
+
+ DEBUG(5, ("wb_cmd_getgroups_recv called\n"));
+
+ if (NT_STATUS_IS_OK(status)) {
+ struct cmd_getgroups_state *state =
+ talloc_get_type(ctx->private_data,
+ struct cmd_getgroups_state);
+ *groups = talloc_steal(mem_ctx, state->gids);
+ *num_groups = state->num_groups;
+ }
+ talloc_free(ctx);
+ return status;
+}
diff --git a/source4/winbind/wb_cmd_getpwent.c b/source4/winbind/wb_cmd_getpwent.c
index 980a8a4d92..45b966377a 100644
--- a/source4/winbind/wb_cmd_getpwent.c
+++ b/source4/winbind/wb_cmd_getpwent.c
@@ -22,10 +22,7 @@
#include "includes.h"
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
-#include "winbind/wb_helper.h"
#include "smbd/service_task.h"
-#include "libnet/libnet_proto.h"
struct cmd_getpwent_state {
struct composite_context *ctx;
diff --git a/source4/winbind/wb_cmd_getpwnam.c b/source4/winbind/wb_cmd_getpwnam.c
index be43684f82..ac723593d2 100644
--- a/source4/winbind/wb_cmd_getpwnam.c
+++ b/source4/winbind/wb_cmd_getpwnam.c
@@ -22,11 +22,9 @@
#include "includes.h"
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
#include "param/param.h"
#include "winbind/wb_helper.h"
#include "smbd/service_task.h"
-#include "libnet/libnet_proto.h"
#include "libcli/security/security.h"
struct cmd_getpwnam_state {
@@ -126,13 +124,13 @@ static void cmd_getpwnam_recv_user_info(struct composite_context *ctx)
WBSRV_SAMBA3_SET_STRING(pw->pw_passwd, "*");
WBSRV_SAMBA3_SET_STRING(pw->pw_gecos, user_info->out.full_name);
WBSRV_SAMBA3_SET_STRING(pw->pw_dir,
- lp_template_homedir(state->service->task->lp_ctx));
+ lpcfg_template_homedir(state->service->task->lp_ctx));
all_string_sub(pw->pw_dir, "%WORKGROUP%", state->workgroup_name,
sizeof(fstring) - 1);
all_string_sub(pw->pw_dir, "%ACCOUNTNAME%", user_info->out.account_name,
sizeof(fstring) - 1);
WBSRV_SAMBA3_SET_STRING(pw->pw_shell,
- lp_template_shell(state->service->task->lp_ctx));
+ lpcfg_template_shell(state->service->task->lp_ctx));
state->group_sid = dom_sid_dup(state, user_info->out.primary_group_sid);
if(composite_nomem(state->group_sid, state->ctx)) return;
diff --git a/source4/winbind/wb_cmd_getpwuid.c b/source4/winbind/wb_cmd_getpwuid.c
index b4e3d972f8..f6f3cb282e 100644
--- a/source4/winbind/wb_cmd_getpwuid.c
+++ b/source4/winbind/wb_cmd_getpwuid.c
@@ -22,13 +22,8 @@
#include "includes.h"
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
-#include "winbind/wb_helper.h"
#include "smbd/service_task.h"
-#include "libnet/libnet_proto.h"
#include "param/param.h"
-#include "libcli/security/proto.h"
-#include "auth/credentials/credentials.h"
struct cmd_getpwuid_state {
struct composite_context *ctx;
@@ -150,13 +145,13 @@ static void cmd_getpwuid_recv_user_info(struct composite_context *ctx)
WBSRV_SAMBA3_SET_STRING(pw->pw_passwd, "*");
WBSRV_SAMBA3_SET_STRING(pw->pw_gecos, user_info->out.full_name);
WBSRV_SAMBA3_SET_STRING(pw->pw_dir,
- lp_template_homedir(state->service->task->lp_ctx));
+ lpcfg_template_homedir(state->service->task->lp_ctx));
all_string_sub(pw->pw_dir, "%WORKGROUP%", state->workgroup,
sizeof(fstring) - 1);
all_string_sub(pw->pw_dir, "%ACCOUNTNAME%", user_info->out.account_name,
sizeof(fstring) - 1);
WBSRV_SAMBA3_SET_STRING(pw->pw_shell,
- lp_template_shell(state->service->task->lp_ctx));
+ lpcfg_template_shell(state->service->task->lp_ctx));
pw->pw_uid = state->uid;
diff --git a/source4/winbind/wb_cmd_list_groups.c b/source4/winbind/wb_cmd_list_groups.c
index 04a4fc39df..db256761d3 100644
--- a/source4/winbind/wb_cmd_list_groups.c
+++ b/source4/winbind/wb_cmd_list_groups.c
@@ -22,10 +22,7 @@
#include "includes.h"
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
-#include "winbind/wb_helper.h"
#include "smbd/service_task.h"
-#include "libnet/libnet_proto.h"
struct cmd_list_groups_state {
struct composite_context *ctx;
@@ -35,6 +32,7 @@ struct cmd_list_groups_state {
char *domain_name;
uint32_t resume_index;
char *result;
+ uint32_t num_groups;
};
static void cmd_list_groups_recv_domain(struct composite_context *ctx);
@@ -58,6 +56,7 @@ struct composite_context *wb_cmd_list_groups_send(TALLOC_CTX *mem_ctx,
result->private_data = state;
state->service = service;
state->resume_index = 0;
+ state->num_groups = 0;
state->result = talloc_strdup(state, "");
if (composite_nomem(state->result, state->ctx)) return result;
@@ -92,13 +91,14 @@ static void cmd_list_groups_recv_domain(struct composite_context *ctx)
state->ctx->status = wb_sid2domain_recv(ctx, &domain);
if (!composite_is_ok(state->ctx)) return;
+ /* we use this entry also for context purposes (libnet_GroupList) */
state->domain = domain;
/* If this is non-null, we've looked up the domain given in the winbind
- * request, otherwise we'll just use the default name.*/
+ * request, otherwise we'll just use the default name .*/
if (state->domain_name == NULL) {
state->domain_name = talloc_strdup(state,
- domain->libnet_ctx->samr.name);
+ state->domain->libnet_ctx->samr.name);
if (composite_nomem(state->domain_name, state->ctx)) return;
}
@@ -113,10 +113,11 @@ static void cmd_list_groups_recv_domain(struct composite_context *ctx)
group_list->in.page_size = 128;
group_list->in.resume_index = state->resume_index;
- ctx = libnet_GroupList_send(domain->libnet_ctx, state, group_list,NULL);
+ ctx = libnet_GroupList_send(state->domain->libnet_ctx, state,
+ group_list, NULL);
composite_continue(state->ctx, ctx, cmd_list_groups_recv_group_list,
- state);
+ state);
}
static void cmd_list_groups_recv_group_list(struct composite_context *ctx)
@@ -136,7 +137,8 @@ static void cmd_list_groups_recv_group_list(struct composite_context *ctx)
/* If NTSTATUS is neither OK nor MORE_ENTRIES, something broke */
if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
+ !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
composite_error(state->ctx, status);
return;
}
@@ -145,16 +147,19 @@ static void cmd_list_groups_recv_group_list(struct composite_context *ctx)
DEBUG(5, ("Appending group '%s'\n",
group_list->out.groups[i].groupname));
state->result = talloc_asprintf_append_buffer(state->result,
- "%s,",
- group_list->out.groups[i].groupname);
+ "%s,",
+ group_list->out.groups[i].groupname);
+ state->num_groups++;
}
/* If the status is OK, we're finished, there's no more groups.
* So we'll trim off the trailing ',' and are done.*/
if (NT_STATUS_IS_OK(status)) {
- int str_len = strlen(state->result);
+ size_t str_len = strlen(state->result);
DEBUG(5, ("list_GroupList_recv returned NT_STATUS_OK\n"));
- state->result[str_len - 1] = '\0';
+ if (str_len > 0) {
+ state->result[str_len - 1] = '\0';
+ }
composite_done(state->ctx);
return;
}
@@ -171,15 +176,15 @@ static void cmd_list_groups_recv_group_list(struct composite_context *ctx)
group_list->in.resume_index = group_list->out.resume_index;
ctx = libnet_GroupList_send(state->domain->libnet_ctx, state,group_list,
- NULL);
+ NULL);
composite_continue(state->ctx, ctx, cmd_list_groups_recv_group_list,
- state);
+ state);
}
NTSTATUS wb_cmd_list_groups_recv(struct composite_context *ctx,
TALLOC_CTX *mem_ctx, uint32_t *extra_data_len,
- char **extra_data)
+ char **extra_data, uint32_t *num_groups)
{
NTSTATUS status = composite_wait(ctx);
@@ -191,6 +196,7 @@ NTSTATUS wb_cmd_list_groups_recv(struct composite_context *ctx,
*extra_data_len = strlen(state->result);
*extra_data = talloc_steal(mem_ctx, state->result);
+ *num_groups = state->num_groups;
}
talloc_free(ctx);
diff --git a/source4/winbind/wb_cmd_list_trustdom.c b/source4/winbind/wb_cmd_list_trustdom.c
index fe98ce2f6a..5f132ef12f 100644
--- a/source4/winbind/wb_cmd_list_trustdom.c
+++ b/source4/winbind/wb_cmd_list_trustdom.c
@@ -33,7 +33,7 @@ struct cmd_list_trustdom_state {
struct composite_context *ctx;
struct dcerpc_pipe *lsa_pipe;
struct policy_handle *lsa_policy;
- int num_domains;
+ uint32_t num_domains;
struct wb_dom_info **domains;
uint32_t resume_handle;
@@ -43,7 +43,7 @@ struct cmd_list_trustdom_state {
static void cmd_list_trustdoms_recv_domain(struct composite_context *ctx);
static void cmd_list_trustdoms_recv_lsa(struct composite_context *ctx);
-static void cmd_list_trustdoms_recv_doms(struct rpc_request *req);
+static void cmd_list_trustdoms_recv_doms(struct tevent_req *subreq);
struct composite_context *wb_cmd_list_trustdoms_send(TALLOC_CTX *mem_ctx,
struct wbsrv_service *service)
@@ -94,7 +94,7 @@ static void cmd_list_trustdoms_recv_lsa(struct composite_context *ctx)
struct cmd_list_trustdom_state *state =
talloc_get_type(ctx->async.private_data,
struct cmd_list_trustdom_state);
- struct rpc_request *req;
+ struct tevent_req *subreq;
state->ctx->status = wb_init_lsa_recv(ctx, state,
&state->lsa_pipe,
@@ -114,19 +114,23 @@ static void cmd_list_trustdoms_recv_lsa(struct composite_context *ctx)
state->r.out.resume_handle = &state->resume_handle;
state->r.out.domains = &state->domainlist;
- req = dcerpc_lsa_EnumTrustDom_send(state->lsa_pipe, state, &state->r);
- composite_continue_rpc(state->ctx, req, cmd_list_trustdoms_recv_doms,
- state);
+ subreq = dcerpc_lsa_EnumTrustDom_r_send(state,
+ state->ctx->event_ctx,
+ state->lsa_pipe->binding_handle,
+ &state->r);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, cmd_list_trustdoms_recv_doms, state);
}
-static void cmd_list_trustdoms_recv_doms(struct rpc_request *req)
+static void cmd_list_trustdoms_recv_doms(struct tevent_req *subreq)
{
struct cmd_list_trustdom_state *state =
- talloc_get_type(req->async.private_data,
- struct cmd_list_trustdom_state);
- int i, old_num_domains;
+ tevent_req_callback_data(subreq,
+ struct cmd_list_trustdom_state);
+ uint32_t i, old_num_domains;
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_lsa_EnumTrustDom_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->r.out.result;
@@ -147,7 +151,7 @@ static void cmd_list_trustdoms_recv_doms(struct rpc_request *req)
composite_nomem(state->domains, state->ctx)) return;
for (i=0; i<state->r.out.domains->count; i++) {
- int j = i+old_num_domains;
+ uint32_t j = i+old_num_domains;
state->domains[j] = talloc(state->domains,
struct wb_dom_info);
if (composite_nomem(state->domains[i], state->ctx)) return;
@@ -173,14 +177,17 @@ static void cmd_list_trustdoms_recv_doms(struct rpc_request *req)
state->r.out.resume_handle = &state->resume_handle;
state->r.out.domains = &state->domainlist;
- req = dcerpc_lsa_EnumTrustDom_send(state->lsa_pipe, state, &state->r);
- composite_continue_rpc(state->ctx, req, cmd_list_trustdoms_recv_doms,
- state);
+ subreq = dcerpc_lsa_EnumTrustDom_r_send(state,
+ state->ctx->event_ctx,
+ state->lsa_pipe->binding_handle,
+ &state->r);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, cmd_list_trustdoms_recv_doms, state);
}
NTSTATUS wb_cmd_list_trustdoms_recv(struct composite_context *ctx,
TALLOC_CTX *mem_ctx,
- int *num_domains,
+ uint32_t *num_domains,
struct wb_dom_info ***domains)
{
NTSTATUS status = composite_wait(ctx);
diff --git a/source4/winbind/wb_cmd_list_users.c b/source4/winbind/wb_cmd_list_users.c
index 755d45786b..03544f6585 100644
--- a/source4/winbind/wb_cmd_list_users.c
+++ b/source4/winbind/wb_cmd_list_users.c
@@ -22,10 +22,7 @@
#include "includes.h"
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
-#include "winbind/wb_helper.h"
#include "smbd/service_task.h"
-#include "libnet/libnet_proto.h"
struct cmd_list_users_state {
struct composite_context *ctx;
@@ -35,6 +32,7 @@ struct cmd_list_users_state {
char *domain_name;
uint32_t resume_index;
char *result;
+ uint32_t num_users;
};
static void cmd_list_users_recv_domain(struct composite_context *ctx);
@@ -58,6 +56,7 @@ struct composite_context *wb_cmd_list_users_send(TALLOC_CTX *mem_ctx,
result->private_data = state;
state->service = service;
state->resume_index = 0;
+ state->num_users = 0;
state->result = talloc_strdup(state, "");
if (composite_nomem(state->result, state->ctx)) return result;
@@ -136,7 +135,8 @@ static void cmd_list_users_recv_user_list(struct composite_context *ctx)
/* If NTSTATUS is neither OK nor MORE_ENTRIES, something broke */
if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
+ !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
+ !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
composite_error(state->ctx, status);
return;
}
@@ -145,6 +145,7 @@ static void cmd_list_users_recv_user_list(struct composite_context *ctx)
DEBUG(5, ("Appending user '%s'\n", user_list->out.users[i].username));
state->result = talloc_asprintf_append_buffer(state->result, "%s,",
user_list->out.users[i].username);
+ state->num_users++;
}
/* If the status is OK, we're finished, there's no more users.
@@ -177,7 +178,7 @@ static void cmd_list_users_recv_user_list(struct composite_context *ctx)
NTSTATUS wb_cmd_list_users_recv(struct composite_context *ctx,
TALLOC_CTX *mem_ctx, uint32_t *extra_data_len,
- char **extra_data)
+ char **extra_data, uint32_t *num_users)
{
NTSTATUS status = composite_wait(ctx);
@@ -189,6 +190,7 @@ NTSTATUS wb_cmd_list_users_recv(struct composite_context *ctx,
*extra_data_len = strlen(state->result);
*extra_data = talloc_steal(mem_ctx, state->result);
+ *num_users = state->num_users;
}
talloc_free(ctx);
diff --git a/source4/winbind/wb_cmd_lookupname.c b/source4/winbind/wb_cmd_lookupname.c
index 9839e2cd80..5178187ea8 100644
--- a/source4/winbind/wb_cmd_lookupname.c
+++ b/source4/winbind/wb_cmd_lookupname.c
@@ -22,7 +22,6 @@
#include "includes.h"
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
#include "winbind/wb_helper.h"
#include "smbd/service_task.h"
diff --git a/source4/winbind/wb_cmd_lookupsid.c b/source4/winbind/wb_cmd_lookupsid.c
index 2d72ae2072..57d859fdf9 100644
--- a/source4/winbind/wb_cmd_lookupsid.c
+++ b/source4/winbind/wb_cmd_lookupsid.c
@@ -42,7 +42,7 @@ struct composite_context *wb_cmd_lookupsid_send(TALLOC_CTX *mem_ctx,
struct composite_context *result, *ctx;
struct cmd_lookupsid_state *state;
-
+ DEBUG(5, ("wb_cmd_lookupsid_send called\n"));
result = composite_create(mem_ctx, service->task->event_ctx);
if (result == NULL) goto failed;
diff --git a/source4/winbind/wb_cmd_setgrent.c b/source4/winbind/wb_cmd_setgrent.c
new file mode 100644
index 0000000000..452d9e736a
--- /dev/null
+++ b/source4/winbind/wb_cmd_setgrent.c
@@ -0,0 +1,171 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Command backend for setgrent
+
+ Copyright (C) Matthieu Patou 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "winbind/wb_server.h"
+#include "smbd/service_task.h"
+
+struct cmd_setgrent_state {
+ struct composite_context *ctx;
+ struct wbsrv_service *service;
+ struct libnet_context *libnet_ctx;
+
+ struct wbsrv_grent *result;
+ char *domain_name;
+};
+
+static void cmd_setgrent_recv_domain(struct composite_context *ctx);
+static void cmd_setgrent_recv_group_list(struct composite_context *ctx);
+
+struct composite_context *wb_cmd_setgrent_send(TALLOC_CTX *mem_ctx,
+ struct wbsrv_service *service)
+{
+ struct composite_context *ctx, *result;
+ struct cmd_setgrent_state *state;
+
+ DEBUG(5, ("wb_cmd_setgrent_send called\n"));
+
+ result = composite_create(mem_ctx, service->task->event_ctx);
+ if (!result) return NULL;
+
+ state = talloc(mem_ctx, struct cmd_setgrent_state);
+ if (composite_nomem(state, result)) return result;
+
+ state->ctx = result;
+ result->private_data = state;
+ state->service = service;
+
+ state->result = talloc(state, struct wbsrv_grent);
+ if (composite_nomem(state->result, state->ctx)) return result;
+
+ ctx = wb_sid2domain_send(state, service, service->primary_sid);
+ if (composite_nomem(ctx, state->ctx)) return result;
+
+ composite_continue(state->ctx, ctx, cmd_setgrent_recv_domain, state);
+ return result;
+}
+
+static void cmd_setgrent_recv_domain(struct composite_context *ctx)
+{
+ struct cmd_setgrent_state *state = talloc_get_type(
+ ctx->async.private_data, struct cmd_setgrent_state);
+ struct wbsrv_domain *domain;
+ struct libnet_GroupList *group_list;
+
+ DEBUG(5, ("cmd_setgrent_recv_domain called\n"));
+
+ state->ctx->status = wb_sid2domain_recv(ctx, &domain);
+ if (!composite_is_ok(state->ctx)) return;
+
+ state->libnet_ctx = domain->libnet_ctx;
+
+ group_list = talloc(state->result, struct libnet_GroupList);
+ if (composite_nomem(group_list, state->ctx)) return;
+
+ state->domain_name = talloc_strdup(state,
+ domain->libnet_ctx->samr.name);
+ group_list->in.domain_name = talloc_strdup(state,
+ domain->libnet_ctx->samr.name);
+ if (composite_nomem(group_list->in.domain_name, state->ctx)) return;
+
+ /* Page size recommended by Rafal */
+ group_list->in.page_size = 128;
+
+ /* Always get the start of the list */
+ group_list->in.resume_index = 0;
+
+ ctx = libnet_GroupList_send(domain->libnet_ctx, state->result, group_list,
+ NULL);
+
+ state->result->page_index = -1;
+ composite_continue(state->ctx, ctx, cmd_setgrent_recv_group_list, state);
+}
+
+static void cmd_setgrent_recv_group_list(struct composite_context *ctx)
+{
+ struct cmd_setgrent_state *state = talloc_get_type(
+ ctx->async.private_data, struct cmd_setgrent_state);
+ struct libnet_GroupList *group_list;
+ struct libnet_GroupList *group_list_send;
+ DEBUG(5, ("cmd_setgrent_recv_group_list called\n"));
+
+ group_list = talloc(state->result, struct libnet_GroupList);
+ if (composite_nomem(group_list, state->ctx)) return;
+
+ state->ctx->status = libnet_GroupList_recv(ctx, state->result,
+ group_list);
+ if (NT_STATUS_IS_OK(state->ctx->status) ||
+ NT_STATUS_EQUAL(state->ctx->status, STATUS_MORE_ENTRIES)) {
+ if( state->result->page_index == -1) { /* First run*/
+ state->result->group_list = group_list;
+ state->result->page_index = 0;
+ state->result->libnet_ctx = state->libnet_ctx;
+ } else {
+ int i;
+ struct grouplist *tmp;
+ tmp = state->result->group_list->out.groups;
+ state->result->group_list->out.groups = talloc_realloc(state->result,tmp,struct grouplist,
+ state->result->group_list->out.count+group_list->out.count);
+ tmp = state->result->group_list->out.groups;
+ for(i=0;i<group_list->out.count;i++ ) {
+ tmp[i+state->result->group_list->out.count].groupname = talloc_steal(state->result,group_list->out.groups[i].groupname);
+ }
+ state->result->group_list->out.count += group_list->out.count;
+ talloc_free(group_list);
+ }
+
+
+ if (NT_STATUS_IS_OK(state->ctx->status) ) {
+ composite_done(state->ctx);
+ } else {
+ group_list_send = talloc(state->result, struct libnet_GroupList);
+ if (composite_nomem(group_list_send, state->ctx)) return;
+ group_list_send->in.domain_name = talloc_strdup(state, state->domain_name);
+ group_list_send->in.resume_index = group_list->out.resume_index;
+ group_list_send->in.page_size = 128;
+ ctx = libnet_GroupList_send(state->libnet_ctx, state->result, group_list_send, NULL);
+ composite_continue(state->ctx, ctx, cmd_setgrent_recv_group_list, state);
+ }
+ } else {
+ composite_error(state->ctx, state->ctx->status);
+ }
+ return;
+}
+
+NTSTATUS wb_cmd_setgrent_recv(struct composite_context *ctx,
+ TALLOC_CTX *mem_ctx, struct wbsrv_grent **grent)
+{
+ NTSTATUS status = composite_wait(ctx);
+
+ DEBUG(5, ("wb_cmd_setgrent_recv called\n"));
+
+ if (NT_STATUS_IS_OK(status)) {
+ struct cmd_setgrent_state *state =
+ talloc_get_type(ctx->private_data,
+ struct cmd_setgrent_state);
+
+ *grent = talloc_steal(mem_ctx, state->result);
+ }
+
+ talloc_free(ctx);
+ return status;
+}
diff --git a/source4/winbind/wb_cmd_setpwent.c b/source4/winbind/wb_cmd_setpwent.c
index 50ab2fdff6..8164d6f199 100644
--- a/source4/winbind/wb_cmd_setpwent.c
+++ b/source4/winbind/wb_cmd_setpwent.c
@@ -22,10 +22,7 @@
#include "includes.h"
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
-#include "winbind/wb_helper.h"
#include "smbd/service_task.h"
-#include "libnet/libnet_proto.h"
struct cmd_setpwent_state {
struct composite_context *ctx;
@@ -33,6 +30,7 @@ struct cmd_setpwent_state {
struct libnet_context *libnet_ctx;
struct wbsrv_pwent *result;
+ char *domain_name;
};
static void cmd_setpwent_recv_domain(struct composite_context *ctx);
@@ -83,6 +81,8 @@ static void cmd_setpwent_recv_domain(struct composite_context *ctx)
user_list = talloc(state->result, struct libnet_UserList);
if (composite_nomem(user_list, state->ctx)) return;
+ state->domain_name = talloc_strdup(state,
+ domain->libnet_ctx->samr.name);
user_list->in.domain_name = talloc_strdup(state,
domain->libnet_ctx->samr.name);
if (composite_nomem(user_list->in.domain_name, state->ctx)) return;
@@ -96,6 +96,7 @@ static void cmd_setpwent_recv_domain(struct composite_context *ctx)
ctx = libnet_UserList_send(domain->libnet_ctx, state->result, user_list,
NULL);
+ state->result->page_index = -1;
composite_continue(state->ctx, ctx, cmd_setpwent_recv_user_list, state);
}
@@ -104,21 +105,52 @@ static void cmd_setpwent_recv_user_list(struct composite_context *ctx)
struct cmd_setpwent_state *state = talloc_get_type(
ctx->async.private_data, struct cmd_setpwent_state);
struct libnet_UserList *user_list;
-
+ struct libnet_UserList *user_list_send;
DEBUG(5, ("cmd_setpwent_recv_user_list called\n"));
user_list = talloc(state->result, struct libnet_UserList);
if (composite_nomem(user_list, state->ctx)) return;
state->ctx->status = libnet_UserList_recv(ctx, state->result,
- user_list);
- if (!composite_is_ok(state->ctx)) return;
-
- state->result->user_list = user_list;
- state->result->page_index = 0;
- state->result->libnet_ctx = state->libnet_ctx;
-
- composite_done(state->ctx);
+ user_list);
+ if (NT_STATUS_IS_OK(state->ctx->status) ||
+ NT_STATUS_EQUAL(state->ctx->status, STATUS_MORE_ENTRIES)) {
+ if (state->result->page_index == -1) { /* First run*/
+ state->result->user_list = user_list;
+ state->result->page_index = 0;
+ state->result->libnet_ctx = state->libnet_ctx;
+ } else {
+ int i, cnt = state->result->user_list->out.count
+ + user_list->out.count;
+ struct userlist *tmp;
+ tmp = state->result->user_list->out.users;
+ state->result->user_list->out.users = talloc_realloc(state->result,
+ tmp, struct userlist,
+ cnt);
+ tmp = state->result->user_list->out.users;
+ for(i=0;i<user_list->out.count;i++ ) {
+ tmp[state->result->user_list->out.count + i].username
+ = talloc_strdup(state->result, user_list->out.users[i].username);
+ }
+ state->result->user_list->out.count = cnt;
+ talloc_free(user_list);
+ }
+
+ if (NT_STATUS_IS_OK(state->ctx->status) ) {
+ composite_done(state->ctx);
+ } else {
+ user_list_send = talloc(state->result, struct libnet_UserList);
+ if (composite_nomem(user_list_send, state->ctx)) return;
+ user_list_send->in.domain_name = talloc_strdup(state, state->domain_name);
+ user_list_send->in.resume_index = user_list->out.resume_index;
+ user_list_send->in.page_size = 128;
+ ctx = libnet_UserList_send(state->libnet_ctx, state->result, user_list_send, NULL);
+ composite_continue(state->ctx, ctx, cmd_setpwent_recv_user_list, state);
+ }
+ } else {
+ composite_error(state->ctx, state->ctx->status);
+ }
+ return;
}
NTSTATUS wb_cmd_setpwent_recv(struct composite_context *ctx,
diff --git a/source4/winbind/wb_cmd_userdomgroups.c b/source4/winbind/wb_cmd_userdomgroups.c
index 649fe489cc..c1258a94d2 100644
--- a/source4/winbind/wb_cmd_userdomgroups.c
+++ b/source4/winbind/wb_cmd_userdomgroups.c
@@ -30,7 +30,7 @@ struct cmd_userdomgroups_state {
struct composite_context *ctx;
struct dom_sid *dom_sid;
uint32_t user_rid;
- int num_rids;
+ uint32_t num_rids;
uint32_t *rids;
};
@@ -104,12 +104,12 @@ static void userdomgroups_recv_rids(struct composite_context *ctx)
NTSTATUS wb_cmd_userdomgroups_recv(struct composite_context *c,
TALLOC_CTX *mem_ctx,
- int *num_sids, struct dom_sid ***sids)
+ uint32_t *num_sids, struct dom_sid ***sids)
{
struct cmd_userdomgroups_state *state =
talloc_get_type(c->private_data,
struct cmd_userdomgroups_state);
- int i;
+ uint32_t i;
NTSTATUS status;
status = composite_wait(c);
@@ -139,7 +139,7 @@ done:
NTSTATUS wb_cmd_userdomgroups(TALLOC_CTX *mem_ctx,
struct wbsrv_service *service,
const struct dom_sid *sid,
- int *num_sids, struct dom_sid ***sids)
+ uint32_t *num_sids, struct dom_sid ***sids)
{
struct composite_context *c =
wb_cmd_userdomgroups_send(mem_ctx, service, sid);
diff --git a/source4/winbind/wb_cmd_usersids.c b/source4/winbind/wb_cmd_usersids.c
index b414cf6313..da4cb80c7b 100644
--- a/source4/winbind/wb_cmd_usersids.c
+++ b/source4/winbind/wb_cmd_usersids.c
@@ -34,20 +34,20 @@ struct cmd_usersids_state {
struct composite_context *ctx;
struct wbsrv_service *service;
struct dom_sid *user_sid;
- int num_domgroups;
+ uint32_t num_domgroups;
struct dom_sid **domgroups;
struct lsa_SidArray lsa_sids;
struct samr_Ids rids;
struct samr_GetAliasMembership r;
- int num_sids;
+ uint32_t num_sids;
struct dom_sid **sids;
};
static void usersids_recv_domgroups(struct composite_context *ctx);
static void usersids_recv_domain(struct composite_context *ctx);
-static void usersids_recv_aliases(struct rpc_request *req);
+static void usersids_recv_aliases(struct tevent_req *subreq);
struct composite_context *wb_cmd_usersids_send(TALLOC_CTX *mem_ctx,
struct wbsrv_service *service,
@@ -102,9 +102,9 @@ static void usersids_recv_domain(struct composite_context *ctx)
struct cmd_usersids_state *state =
talloc_get_type(ctx->async.private_data,
struct cmd_usersids_state);
- struct rpc_request *req;
+ struct tevent_req *subreq;
struct wbsrv_domain *domain;
- int i;
+ uint32_t i;
state->ctx->status = wb_sid2domain_recv(ctx, &domain);
if (!composite_is_ok(state->ctx)) return;
@@ -126,19 +126,23 @@ static void usersids_recv_domain(struct composite_context *ctx)
state->r.in.sids = &state->lsa_sids;
state->r.out.rids = &state->rids;
- req = dcerpc_samr_GetAliasMembership_send(domain->libnet_ctx->samr.pipe, state,
- &state->r);
- composite_continue_rpc(state->ctx, req, usersids_recv_aliases, state);
+ subreq = dcerpc_samr_GetAliasMembership_r_send(state,
+ state->ctx->event_ctx,
+ domain->libnet_ctx->samr.pipe->binding_handle,
+ &state->r);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, usersids_recv_aliases, state);
}
-static void usersids_recv_aliases(struct rpc_request *req)
+static void usersids_recv_aliases(struct tevent_req *subreq)
{
struct cmd_usersids_state *state =
- talloc_get_type(req->async.private_data,
- struct cmd_usersids_state);
- int i;
+ tevent_req_callback_data(subreq,
+ struct cmd_usersids_state);
+ uint32_t i;
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_samr_GetAliasMembership_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->r.out.result;
if (!composite_is_ok(state->ctx)) return;
@@ -168,7 +172,7 @@ static void usersids_recv_aliases(struct rpc_request *req)
NTSTATUS wb_cmd_usersids_recv(struct composite_context *ctx,
TALLOC_CTX *mem_ctx,
- int *num_sids, struct dom_sid ***sids)
+ uint32_t *num_sids, struct dom_sid ***sids)
{
NTSTATUS status = composite_wait(ctx);
if (NT_STATUS_IS_OK(status)) {
@@ -184,7 +188,7 @@ NTSTATUS wb_cmd_usersids_recv(struct composite_context *ctx,
NTSTATUS wb_cmd_usersids(TALLOC_CTX *mem_ctx, struct wbsrv_service *service,
const struct dom_sid *sid,
- int *num_sids, struct dom_sid ***sids)
+ uint32_t *num_sids, struct dom_sid ***sids)
{
struct composite_context *c =
wb_cmd_usersids_send(mem_ctx, service, sid);
diff --git a/source4/winbind/wb_connect_lsa.c b/source4/winbind/wb_connect_lsa.c
index a728f8abe4..01bd23bd78 100644
--- a/source4/winbind/wb_connect_lsa.c
+++ b/source4/winbind/wb_connect_lsa.c
@@ -24,7 +24,6 @@
#include "includes.h"
#include "libcli/composite/composite.h"
-#include "libcli/raw/libcliraw.h"
#include "librpc/gen_ndr/ndr_lsa_c.h"
#include "winbind/wb_server.h"
@@ -44,7 +43,7 @@ struct init_lsa_state {
};
static void init_lsa_recv_pipe(struct composite_context *ctx);
-static void init_lsa_recv_openpol(struct rpc_request *req);
+static void init_lsa_recv_openpol(struct tevent_req *subreq);
struct composite_context *wb_init_lsa_send(TALLOC_CTX *mem_ctx,
struct wbsrv_domain *domain)
@@ -77,10 +76,10 @@ struct composite_context *wb_init_lsa_send(TALLOC_CTX *mem_ctx,
static void init_lsa_recv_pipe(struct composite_context *ctx)
{
- struct rpc_request *req;
struct init_lsa_state *state =
talloc_get_type(ctx->async.private_data,
struct init_lsa_state);
+ struct tevent_req *subreq;
state->ctx->status = dcerpc_secondary_auth_connection_recv(ctx, state,
&state->lsa_pipe);
@@ -97,18 +96,22 @@ static void init_lsa_recv_pipe(struct composite_context *ctx)
state->openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
state->openpolicy.out.handle = state->handle;
- req = dcerpc_lsa_OpenPolicy2_send(state->lsa_pipe, state,
- &state->openpolicy);
- composite_continue_rpc(state->ctx, req, init_lsa_recv_openpol, state);
+ subreq = dcerpc_lsa_OpenPolicy2_r_send(state,
+ state->ctx->event_ctx,
+ state->lsa_pipe->binding_handle,
+ &state->openpolicy);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, init_lsa_recv_openpol, state);
}
-static void init_lsa_recv_openpol(struct rpc_request *req)
+static void init_lsa_recv_openpol(struct tevent_req *subreq)
{
struct init_lsa_state *state =
- talloc_get_type(req->async.private_data,
- struct init_lsa_state);
+ tevent_req_callback_data(subreq,
+ struct init_lsa_state);
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_lsa_OpenPolicy2_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->openpolicy.out.result;
if (!composite_is_ok(state->ctx)) return;
diff --git a/source4/winbind/wb_connect_sam.c b/source4/winbind/wb_connect_sam.c
index efd715b164..06937b2dee 100644
--- a/source4/winbind/wb_connect_sam.c
+++ b/source4/winbind/wb_connect_sam.c
@@ -23,7 +23,6 @@
#include "includes.h"
#include "libcli/composite/composite.h"
-#include "libcli/raw/libcliraw.h"
#include "libcli/security/security.h"
#include "librpc/gen_ndr/ndr_samr_c.h"
#include "winbind/wb_server.h"
@@ -45,8 +44,8 @@ struct connect_samr_state {
};
static void connect_samr_recv_pipe(struct composite_context *ctx);
-static void connect_samr_recv_conn(struct rpc_request *req);
-static void connect_samr_recv_open(struct rpc_request *req);
+static void connect_samr_recv_conn(struct tevent_req *subreq);
+static void connect_samr_recv_open(struct tevent_req *subreq);
struct composite_context *wb_connect_samr_send(TALLOC_CTX *mem_ctx,
struct wbsrv_domain *domain)
@@ -82,10 +81,10 @@ struct composite_context *wb_connect_samr_send(TALLOC_CTX *mem_ctx,
static void connect_samr_recv_pipe(struct composite_context *ctx)
{
- struct rpc_request *req;
struct connect_samr_state *state =
talloc_get_type(ctx->async.private_data,
struct connect_samr_state);
+ struct tevent_req *subreq;
state->ctx->status = dcerpc_secondary_auth_connection_recv(ctx, state,
&state->samr_pipe);
@@ -100,18 +99,22 @@ static void connect_samr_recv_pipe(struct composite_context *ctx)
state->c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
state->c.out.connect_handle = state->connect_handle;
- req = dcerpc_samr_Connect2_send(state->samr_pipe, state, &state->c);
- composite_continue_rpc(state->ctx, req, connect_samr_recv_conn, state);
- return;
+ subreq = dcerpc_samr_Connect2_r_send(state,
+ state->ctx->event_ctx,
+ state->samr_pipe->binding_handle,
+ &state->c);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, connect_samr_recv_conn, state);
}
-static void connect_samr_recv_conn(struct rpc_request *req)
+static void connect_samr_recv_conn(struct tevent_req *subreq)
{
struct connect_samr_state *state =
- talloc_get_type(req->async.private_data,
- struct connect_samr_state);
+ tevent_req_callback_data(subreq,
+ struct connect_samr_state);
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_samr_Connect2_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->c.out.result;
if (!composite_is_ok(state->ctx)) return;
@@ -124,18 +127,22 @@ static void connect_samr_recv_conn(struct rpc_request *req)
state->o.in.sid = state->sid;
state->o.out.domain_handle = state->domain_handle;
- req = dcerpc_samr_OpenDomain_send(state->samr_pipe, state, &state->o);
- composite_continue_rpc(state->ctx, req,
- connect_samr_recv_open, state);
+ subreq = dcerpc_samr_OpenDomain_r_send(state,
+ state->ctx->event_ctx,
+ state->samr_pipe->binding_handle,
+ &state->o);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, connect_samr_recv_open, state);
}
-static void connect_samr_recv_open(struct rpc_request *req)
+static void connect_samr_recv_open(struct tevent_req *subreq)
{
struct connect_samr_state *state =
- talloc_get_type(req->async.private_data,
- struct connect_samr_state);
+ tevent_req_callback_data(subreq,
+ struct connect_samr_state);
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_samr_OpenDomain_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->o.out.result;
if (!composite_is_ok(state->ctx)) return;
diff --git a/source4/winbind/wb_dom_info.c b/source4/winbind/wb_dom_info.c
index 4fcbf3a6e5..5402c1cf62 100644
--- a/source4/winbind/wb_dom_info.c
+++ b/source4/winbind/wb_dom_info.c
@@ -26,27 +26,28 @@
#include "libcli/security/security.h"
#include "winbind/wb_server.h"
#include "smbd/service_task.h"
-#include "librpc/gen_ndr/ndr_irpc.h"
-#include "librpc/gen_ndr/samr.h"
-#include "lib/messaging/irpc.h"
-#include "libcli/finddcs.h"
-#include "param/param.h"
+#include "libcli/finddc.h"
struct get_dom_info_state {
struct composite_context *ctx;
struct wb_dom_info *info;
};
-static void get_dom_info_recv_addrs(struct composite_context *ctx);
+static void get_dom_info_recv_addrs(struct tevent_req *req);
struct composite_context *wb_get_dom_info_send(TALLOC_CTX *mem_ctx,
struct wbsrv_service *service,
const char *domain_name,
+ const char *dns_domain_name,
const struct dom_sid *sid)
{
- struct composite_context *result, *ctx;
+ struct composite_context *result;
+ struct tevent_req *req;
struct get_dom_info_state *state;
struct dom_sid *dom_sid;
+ struct finddcs finddcs_io;
+
+ DEBUG(5, ("wb_get_dom_info_send called\n"));
result = composite_create(mem_ctx, service->task->event_ctx);
if (result == NULL) goto failed;
@@ -67,17 +68,21 @@ struct composite_context *wb_get_dom_info_send(TALLOC_CTX *mem_ctx,
dom_sid = dom_sid_dup(mem_ctx, sid);
if (dom_sid == NULL) goto failed;
- ctx = finddcs_send(mem_ctx, lp_netbios_name(service->task->lp_ctx),
- lp_nbt_port(service->task->lp_ctx),
- domain_name, NBT_NAME_LOGON,
- dom_sid,
- lp_iconv_convenience(service->task->lp_ctx),
- lp_resolve_context(service->task->lp_ctx),
- service->task->event_ctx,
- service->task->msg_ctx);
- if (ctx == NULL) goto failed;
-
- composite_continue(state->ctx, ctx, get_dom_info_recv_addrs, state);
+ ZERO_STRUCT(finddcs_io);
+ finddcs_io.in.domain_name = dns_domain_name;
+ finddcs_io.in.domain_sid = dom_sid;
+ finddcs_io.in.minimum_dc_flags = NBT_SERVER_LDAP | NBT_SERVER_DS;
+ if (service->sec_channel_type == SEC_CHAN_RODC) {
+ finddcs_io.in.minimum_dc_flags |= NBT_SERVER_WRITABLE;
+ }
+
+ req = finddcs_cldap_send(mem_ctx, &finddcs_io,
+ lpcfg_resolve_context(service->task->lp_ctx),
+ service->task->event_ctx);
+ if (req == NULL) goto failed;
+
+ tevent_req_set_callback(req, get_dom_info_recv_addrs, state);
+
return result;
failed:
@@ -85,17 +90,28 @@ struct composite_context *wb_get_dom_info_send(TALLOC_CTX *mem_ctx,
return NULL;
}
-static void get_dom_info_recv_addrs(struct composite_context *ctx)
+static void get_dom_info_recv_addrs(struct tevent_req *req)
{
- struct get_dom_info_state *state =
- talloc_get_type(ctx->async.private_data,
- struct get_dom_info_state);
+ struct get_dom_info_state *state = tevent_req_callback_data(req, struct get_dom_info_state);
+ struct finddcs finddcs_io;
- state->ctx->status = finddcs_recv(ctx, state->info,
- &state->info->num_dcs,
- &state->info->dcs);
+ state->info->dc = talloc(state->info, struct nbt_dc_name);
+
+ state->ctx->status = finddcs_cldap_recv(req, state->info, &finddcs_io);
if (!composite_is_ok(state->ctx)) return;
+ if (finddcs_io.out.netlogon.ntver != NETLOGON_NT_VERSION_5EX) {
+ /* the finddcs code should have mapped the response to
+ the type we want */
+ DEBUG(0,(__location__ ": unexpected ntver 0x%08x in finddcs response\n",
+ finddcs_io.out.netlogon.ntver));
+ state->ctx->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+ if (!composite_is_ok(state->ctx)) return;
+ }
+
+ state->info->dc->address = finddcs_io.out.address;
+ state->info->dc->name = finddcs_io.out.netlogon.data.nt5_ex.pdc_dns_name;
+
composite_done(state->ctx);
}
@@ -117,10 +133,11 @@ NTSTATUS wb_get_dom_info_recv(struct composite_context *ctx,
NTSTATUS wb_get_dom_info(TALLOC_CTX *mem_ctx,
struct wbsrv_service *service,
const char *domain_name,
+ const char *dns_domain_name,
const struct dom_sid *sid,
struct wb_dom_info **result)
{
struct composite_context *ctx =
- wb_get_dom_info_send(mem_ctx, service, domain_name, sid);
+ wb_get_dom_info_send(mem_ctx, service, domain_name, dns_domain_name, sid);
return wb_get_dom_info_recv(ctx, mem_ctx, result);
}
diff --git a/source4/winbind/wb_dom_info_trusted.c b/source4/winbind/wb_dom_info_trusted.c
index c3bc754f69..af887c854c 100644
--- a/source4/winbind/wb_dom_info_trusted.c
+++ b/source4/winbind/wb_dom_info_trusted.c
@@ -27,7 +27,6 @@
#include "smbd/service_task.h"
#include "librpc/gen_ndr/ndr_netlogon_c.h"
#include "libcli/libcli.h"
-#include "param/param.h"
struct trusted_dom_info_state {
struct composite_context *ctx;
@@ -41,8 +40,8 @@ struct trusted_dom_info_state {
};
static void trusted_dom_info_recv_domain(struct composite_context *ctx);
-static void trusted_dom_info_recv_dsr(struct rpc_request *req);
-static void trusted_dom_info_recv_dcname(struct rpc_request *req);
+static void trusted_dom_info_recv_dsr(struct tevent_req *subreq);
+static void trusted_dom_info_recv_dcname(struct tevent_req *subreq);
static void trusted_dom_info_recv_dcaddr(struct composite_context *ctx);
struct composite_context *wb_trusted_dom_info_send(TALLOC_CTX *mem_ctx,
@@ -89,7 +88,7 @@ static void trusted_dom_info_recv_domain(struct composite_context *ctx)
struct trusted_dom_info_state *state =
talloc_get_type(ctx->async.private_data,
struct trusted_dom_info_state);
- struct rpc_request *req;
+ struct tevent_req *subreq;
state->ctx->status = wb_sid2domain_recv(ctx, &state->my_domain);
if (!composite_is_ok(state->ctx)) return;
@@ -107,25 +106,28 @@ static void trusted_dom_info_recv_domain(struct composite_context *ctx)
state->d.out.info = talloc(state, struct netr_DsRGetDCNameInfo *);
if (composite_nomem(state->d.out.info, state->ctx)) return;
- req = dcerpc_netr_DsRGetDCName_send(state->my_domain->netlogon_pipe,
- state, &state->d);
- composite_continue_rpc(state->ctx, req, trusted_dom_info_recv_dsr,
- state);
+ subreq = dcerpc_netr_DsRGetDCName_r_send(state,
+ state->ctx->event_ctx,
+ state->my_domain->netlogon_pipe->binding_handle,
+ &state->d);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, trusted_dom_info_recv_dsr, state);
}
/*
* dcerpc_netr_DsRGetDCName has replied
*/
-static void trusted_dom_info_recv_dsr(struct rpc_request *req)
+static void trusted_dom_info_recv_dsr(struct tevent_req *subreq)
{
struct trusted_dom_info_state *state =
- talloc_get_type(req->async.private_data,
- struct trusted_dom_info_state);
+ tevent_req_callback_data(subreq,
+ struct trusted_dom_info_state);
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_netr_DsRGetDCName_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(state->ctx->status)) {
- DEBUG(9, ("dcerpc_ndr_request_recv returned %s\n",
+ DEBUG(9, ("dcerpc_netr_DsRGetDCName_recv returned %s\n",
nt_errstr(state->ctx->status)));
goto fallback;
}
@@ -139,17 +141,16 @@ static void trusted_dom_info_recv_dsr(struct rpc_request *req)
}
/* Hey, that was easy! */
- state->info->num_dcs = 1;
- state->info->dcs = talloc(state->info, struct nbt_dc_name);
- state->info->dcs[0].name = talloc_steal(state->info,
+ state->info->dc = talloc(state->info, struct nbt_dc_name);
+ state->info->dc->name = talloc_steal(state->info,
(*state->d.out.info)->dc_unc);
- if (*state->info->dcs[0].name == '\\') state->info->dcs[0].name++;
- if (*state->info->dcs[0].name == '\\') state->info->dcs[0].name++;
+ if (*state->info->dc->name == '\\') state->info->dc->name++;
+ if (*state->info->dc->name == '\\') state->info->dc->name++;
- state->info->dcs[0].address = talloc_steal(state->info,
+ state->info->dc->address = talloc_steal(state->info,
(*state->d.out.info)->dc_address);
- if (*state->info->dcs[0].address == '\\') state->info->dcs[0].address++;
- if (*state->info->dcs[0].address == '\\') state->info->dcs[0].address++;
+ if (*state->info->dc->address == '\\') state->info->dc->address++;
+ if (*state->info->dc->address == '\\') state->info->dc->address++;
state->info->dns_name = talloc_steal(state->info,
(*state->d.out.info)->domain_name);
@@ -165,37 +166,38 @@ static void trusted_dom_info_recv_dsr(struct rpc_request *req)
state->g.in.domainname = state->info->name;
state->g.out.dcname = talloc(state, const char *);
- req = dcerpc_netr_GetAnyDCName_send(state->my_domain->netlogon_pipe,
- state, &state->g);
- if (composite_nomem(req, state->ctx)) return;
+ subreq = dcerpc_netr_GetAnyDCName_r_send(state,
+ state->ctx->event_ctx,
+ state->my_domain->netlogon_pipe->binding_handle,
+ &state->g);
+ if (composite_nomem(subreq, state->ctx)) return;
- composite_continue_rpc(state->ctx, req, trusted_dom_info_recv_dcname,
- state);
+ tevent_req_set_callback(subreq, trusted_dom_info_recv_dcname, state);
}
-static void trusted_dom_info_recv_dcname(struct rpc_request *req)
+static void trusted_dom_info_recv_dcname(struct tevent_req *subreq)
{
struct trusted_dom_info_state *state =
- talloc_get_type(req->async.private_data,
- struct trusted_dom_info_state);
+ tevent_req_callback_data(subreq,
+ struct trusted_dom_info_state);
struct composite_context *ctx;
struct nbt_name name;
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_netr_GetAnyDCName_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = werror_to_ntstatus(state->g.out.result);
if (!composite_is_ok(state->ctx)) return;
/* Hey, that was easy! */
- state->info->num_dcs = 1;
- state->info->dcs = talloc(state->info, struct nbt_dc_name);
- state->info->dcs[0].name = talloc_steal(state->info,
+ state->info->dc = talloc(state->info, struct nbt_dc_name);
+ state->info->dc->name = talloc_steal(state->info,
*(state->g.out.dcname));
- if (*state->info->dcs[0].name == '\\') state->info->dcs[0].name++;
- if (*state->info->dcs[0].name == '\\') state->info->dcs[0].name++;
+ if (*state->info->dc->name == '\\') state->info->dc->name++;
+ if (*state->info->dc->name == '\\') state->info->dc->name++;
- make_nbt_name(&name, state->info->dcs[0].name, 0x20);
- ctx = resolve_name_send(lp_resolve_context(state->service->task->lp_ctx), state,
+ make_nbt_name(&name, state->info->dc->name, 0x20);
+ ctx = resolve_name_send(lpcfg_resolve_context(state->service->task->lp_ctx), state,
&name, state->service->task->event_ctx);
composite_continue(state->ctx, ctx, trusted_dom_info_recv_dcaddr,
@@ -209,7 +211,7 @@ static void trusted_dom_info_recv_dcaddr(struct composite_context *ctx)
struct trusted_dom_info_state);
state->ctx->status = resolve_name_recv(ctx, state->info,
- &state->info->dcs[0].address);
+ &state->info->dc->address);
if (!composite_is_ok(state->ctx)) return;
composite_done(state->ctx);
diff --git a/source4/winbind/wb_gid2sid.c b/source4/winbind/wb_gid2sid.c
index 834d869845..67a145e909 100644
--- a/source4/winbind/wb_gid2sid.c
+++ b/source4/winbind/wb_gid2sid.c
@@ -23,9 +23,6 @@
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
#include "smbd/service_task.h"
-#include "winbind/wb_helper.h"
-#include "libcli/security/proto.h"
-#include "winbind/idmap.h"
struct gid2sid_state {
struct composite_context *ctx;
@@ -40,8 +37,7 @@ struct composite_context *wb_gid2sid_send(TALLOC_CTX *mem_ctx,
{
struct composite_context *result, *ctx;
struct gid2sid_state *state;
- struct unixid *unixid;
- struct id_mapping *ids;
+ struct id_map *ids;
DEBUG(5, ("wb_gid2sid_send called\n"));
@@ -55,14 +51,10 @@ struct composite_context *wb_gid2sid_send(TALLOC_CTX *mem_ctx,
result->private_data = state;
state->service = service;
- unixid = talloc(result, struct unixid);
- if (composite_nomem(unixid, result)) return result;
- unixid->id = gid;
- unixid->type = ID_TYPE_GID;
-
- ids = talloc(result, struct id_mapping);
+ ids = talloc(result, struct id_map);
if (composite_nomem(ids, result)) return result;
- ids->unixid = unixid;
+ ids->xid.id = gid;
+ ids->xid.type = ID_TYPE_GID;
ids->sid = NULL;
ctx = wb_xids2sids_send(result, service, 1, ids);
@@ -76,12 +68,12 @@ static void gid2sid_recv_sid(struct composite_context *ctx)
{
struct gid2sid_state *state = talloc_get_type(ctx->async.private_data,
struct gid2sid_state);
- struct id_mapping *ids = NULL;
+ struct id_map *ids = NULL;
state->ctx->status = wb_xids2sids_recv(ctx, &ids);
if (!composite_is_ok(state->ctx)) return;
- if (!NT_STATUS_IS_OK(ids->status)) {
- composite_error(state->ctx, ids->status);
+ if (ids->status != ID_MAPPED) {
+ composite_error(state->ctx, NT_STATUS_UNSUCCESSFUL);
return;
}
diff --git a/source4/winbind/wb_init_domain.c b/source4/winbind/wb_init_domain.c
index 1f560c17ce..50a6af05fd 100644
--- a/source4/winbind/wb_init_domain.c
+++ b/source4/winbind/wb_init_domain.c
@@ -22,20 +22,15 @@
#include "includes.h"
#include "libcli/composite/composite.h"
-#include "libcli/smb_composite/smb_composite.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
-#include "winbind/wb_helper.h"
#include "smbd/service_task.h"
#include "librpc/gen_ndr/ndr_netlogon.h"
#include "librpc/gen_ndr/ndr_lsa_c.h"
#include "librpc/gen_ndr/ndr_samr_c.h"
#include "libcli/libcli.h"
-#include "libcli/auth/credentials.h"
#include "libcli/security/security.h"
-#include "libcli/ldap/ldap_client.h"
#include "auth/credentials/credentials.h"
#include "param/param.h"
@@ -75,8 +70,8 @@ struct init_domain_state {
static void init_domain_recv_netlogonpipe(struct composite_context *ctx);
static void init_domain_recv_lsa_pipe(struct composite_context *ctx);
-static void init_domain_recv_lsa_policy(struct rpc_request *req);
-static void init_domain_recv_queryinfo(struct rpc_request *req);
+static void init_domain_recv_lsa_policy(struct tevent_req *subreq);
+static void init_domain_recv_queryinfo(struct tevent_req *subreq);
static void init_domain_recv_samr(struct composite_context *ctx);
static struct dcerpc_binding *init_domain_binding(struct init_domain_state *state,
@@ -133,16 +128,8 @@ struct composite_context *wb_init_domain_send(TALLOC_CTX *mem_ctx,
state->domain->info = talloc_reference(state->domain, dom_info);
if (state->domain->info == NULL) goto failed;
- /* Caller should check, but to be safe: */
- if (dom_info->num_dcs < 1) {
- goto failed;
- }
-
- /* For now, we just pick the first. The next step will be to
- * walk the entire list. Also need to fix finddcs() to return
- * the entire list */
- state->domain->dc_name = dom_info->dcs[0].name;
- state->domain->dc_address = dom_info->dcs[0].address;
+ state->domain->dc_name = dom_info->dc->name;
+ state->domain->dc_address = dom_info->dc->address;
state->domain->libnet_ctx = libnet_context_init(service->task->event_ctx,
service->task->lp_ctx);
@@ -163,14 +150,14 @@ struct composite_context *wb_init_domain_send(TALLOC_CTX *mem_ctx,
state->domain->netlogon_pipe = NULL;
if ((!cli_credentials_is_anonymous(state->domain->libnet_ctx->cred)) &&
- ((lp_server_role(service->task->lp_ctx) == ROLE_DOMAIN_MEMBER) ||
- (lp_server_role(service->task->lp_ctx) == ROLE_DOMAIN_CONTROLLER)) &&
+ ((lpcfg_server_role(service->task->lp_ctx) == ROLE_DOMAIN_MEMBER) ||
+ (lpcfg_server_role(service->task->lp_ctx) == ROLE_DOMAIN_CONTROLLER)) &&
(dom_sid_equal(state->domain->info->sid,
state->service->primary_sid))) {
state->domain->netlogon_binding->flags |= DCERPC_SCHANNEL;
/* For debugging, it can be a real pain if all the traffic is encrypted */
- if (lp_winbind_sealed_pipes(service->task->lp_ctx)) {
+ if (lpcfg_winbind_sealed_pipes(service->task->lp_ctx)) {
state->domain->netlogon_binding->flags |= (DCERPC_SIGN | DCERPC_SEAL );
} else {
state->domain->netlogon_binding->flags |= (DCERPC_SIGN);
@@ -216,7 +203,7 @@ static void init_domain_recv_netlogonpipe(struct composite_context *ctx)
state->domain->lsa_binding = init_domain_binding(state, &ndr_table_lsarpc);
/* For debugging, it can be a real pain if all the traffic is encrypted */
- if (lp_winbind_sealed_pipes(state->service->task->lp_ctx)) {
+ if (lpcfg_winbind_sealed_pipes(state->service->task->lp_ctx)) {
state->domain->lsa_binding->flags |= (DCERPC_SIGN | DCERPC_SEAL );
} else {
state->domain->lsa_binding->flags |= (DCERPC_SIGN);
@@ -269,10 +256,10 @@ static bool retry_with_schannel(struct init_domain_state *state,
*/
static void init_domain_recv_lsa_pipe(struct composite_context *ctx)
{
- struct rpc_request *req;
struct init_domain_state *state =
talloc_get_type(ctx->async.private_data,
struct init_domain_state);
+ struct tevent_req *subreq;
state->ctx->status = dcerpc_secondary_auth_connection_recv(ctx, state->domain,
&state->domain->libnet_ctx->lsa.pipe);
@@ -299,22 +286,25 @@ static void init_domain_recv_lsa_pipe(struct composite_context *ctx)
state->lsa_openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
state->lsa_openpolicy.out.handle = &state->domain->libnet_ctx->lsa.handle;
- req = dcerpc_lsa_OpenPolicy2_send(state->domain->libnet_ctx->lsa.pipe, state,
- &state->lsa_openpolicy);
-
- composite_continue_rpc(state->ctx, req, init_domain_recv_lsa_policy, state);
+ subreq = dcerpc_lsa_OpenPolicy2_r_send(state,
+ state->ctx->event_ctx,
+ state->domain->libnet_ctx->lsa.pipe->binding_handle,
+ &state->lsa_openpolicy);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, init_domain_recv_lsa_policy, state);
}
/* Receive a policy handle (or not, and retry the authentication) and
* obtain some basic information about the domain */
-static void init_domain_recv_lsa_policy(struct rpc_request *req)
+static void init_domain_recv_lsa_policy(struct tevent_req *subreq)
{
struct init_domain_state *state =
- talloc_get_type(req->async.private_data,
- struct init_domain_state);
+ tevent_req_callback_data(subreq,
+ struct init_domain_state);
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_lsa_OpenPolicy2_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if ((!NT_STATUS_IS_OK(state->ctx->status)
|| !NT_STATUS_IS_OK(state->lsa_openpolicy.out.result))) {
if (retry_with_schannel(state, state->domain->lsa_binding,
@@ -334,20 +324,24 @@ static void init_domain_recv_lsa_policy(struct rpc_request *req)
state->queryinfo.in.level = LSA_POLICY_INFO_ACCOUNT_DOMAIN;
state->queryinfo.out.info = &state->info;
- req = dcerpc_lsa_QueryInfoPolicy_send(state->domain->libnet_ctx->lsa.pipe, state,
- &state->queryinfo);
- composite_continue_rpc(state->ctx, req,
- init_domain_recv_queryinfo, state);
+ subreq = dcerpc_lsa_QueryInfoPolicy_r_send(state,
+ state->ctx->event_ctx,
+ state->domain->libnet_ctx->lsa.pipe->binding_handle,
+ &state->queryinfo);
+ if (composite_nomem(subreq, state->ctx)) return;
+ tevent_req_set_callback(subreq, init_domain_recv_queryinfo, state);
}
-static void init_domain_recv_queryinfo(struct rpc_request *req)
+static void init_domain_recv_queryinfo(struct tevent_req *subreq)
{
struct init_domain_state *state =
- talloc_get_type(req->async.private_data, struct init_domain_state);
+ tevent_req_callback_data(subreq,
+ struct init_domain_state);
struct lsa_DomainInfo *dominfo;
struct composite_context *ctx;
- state->ctx->status = dcerpc_ndr_request_recv(req);
+ state->ctx->status = dcerpc_lsa_QueryInfoPolicy_r_recv(subreq, state);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(state->ctx)) return;
state->ctx->status = state->queryinfo.out.result;
if (!composite_is_ok(state->ctx)) return;
diff --git a/source4/winbind/wb_irpc.c b/source4/winbind/wb_irpc.c
index 801c2e7dfa..1eed89fd41 100644
--- a/source4/winbind/wb_irpc.c
+++ b/source4/winbind/wb_irpc.c
@@ -22,7 +22,6 @@
#include "winbind/wb_server.h"
#include "lib/messaging/irpc.h"
#include "libcli/composite/composite.h"
-#include "libcli/security/proto.h"
#include "librpc/gen_ndr/ndr_winbind.h"
#include "smbd/service_task.h"
@@ -72,6 +71,52 @@ static void wb_irpc_SamLogon_callback(struct composite_context *ctx)
irpc_send_reply(s->msg, status);
}
+struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state {
+ struct irpc_message *msg;
+ struct winbind_DsrUpdateReadOnlyServerDnsRecords *req;
+};
+
+static void wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback(struct composite_context *ctx);
+
+static NTSTATUS wb_irpc_DsrUpdateReadOnlyServerDnsRecords(struct irpc_message *msg,
+ struct winbind_DsrUpdateReadOnlyServerDnsRecords *req)
+{
+ struct wbsrv_service *service = talloc_get_type(msg->private_data,
+ struct wbsrv_service);
+ struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state *s;
+ struct composite_context *ctx;
+
+ DEBUG(5, ("wb_irpc_DsrUpdateReadOnlyServerDnsRecords called\n"));
+
+ s = talloc(msg, struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state);
+ NT_STATUS_HAVE_NO_MEMORY(s);
+
+ s->msg = msg;
+ s->req = req;
+
+ ctx = wb_update_rodc_dns_send(msg, service, req);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback;
+ ctx->async.private_data = s;
+
+ msg->defer_reply = true;
+ return NT_STATUS_OK;
+}
+
+static void wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback(struct composite_context *ctx)
+{
+ struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state *s = talloc_get_type(ctx->async.private_data,
+ struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state);
+ NTSTATUS status;
+
+ DEBUG(5, ("wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback called\n"));
+
+ status = wb_update_rodc_dns_recv(ctx, s, s->req);
+
+ irpc_send_reply(s->msg, status);
+}
+
struct wb_irpc_get_idmap_state {
struct irpc_message *msg;
struct winbind_get_idmap *req;
@@ -86,7 +131,7 @@ static NTSTATUS wb_irpc_get_idmap(struct irpc_message *msg,
struct wbsrv_service *service = talloc_get_type(msg->private_data,
struct wbsrv_service);
struct wb_irpc_get_idmap_state *s;
- struct composite_context *ctx;
+ struct composite_context *ctx = NULL;
DEBUG(5, ("wb_irpc_get_idmap called\n"));
@@ -150,6 +195,10 @@ NTSTATUS wbsrv_init_irpc(struct wbsrv_service *service)
wb_irpc_SamLogon, service);
NT_STATUS_NOT_OK_RETURN(status);
+ status = IRPC_REGISTER(service->task->msg_ctx, winbind, WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS,
+ wb_irpc_DsrUpdateReadOnlyServerDnsRecords, service);
+ NT_STATUS_NOT_OK_RETURN(status);
+
status = IRPC_REGISTER(service->task->msg_ctx, winbind, WINBIND_GET_IDMAP,
wb_irpc_get_idmap, service);
NT_STATUS_NOT_OK_RETURN(status);
diff --git a/source4/winbind/wb_name2domain.c b/source4/winbind/wb_name2domain.c
index e19703b1e5..9da3d43ebc 100644
--- a/source4/winbind/wb_name2domain.c
+++ b/source4/winbind/wb_name2domain.c
@@ -24,7 +24,6 @@
#include "winbind/wb_server.h"
#include "smbd/service_task.h"
#include "winbind/wb_helper.h"
-#include "param/param.h"
struct name2domain_state {
struct composite_context *ctx;
diff --git a/source4/winbind/wb_pam_auth.c b/source4/winbind/wb_pam_auth.c
index b2579fd6df..e09addac73 100644
--- a/source4/winbind/wb_pam_auth.c
+++ b/source4/winbind/wb_pam_auth.c
@@ -27,7 +27,6 @@
#include "auth/credentials/credentials.h"
#include "libcli/auth/libcli_auth.h"
#include "librpc/gen_ndr/ndr_netlogon.h"
-#include "librpc/gen_ndr/ndr_netlogon_c.h"
#include "librpc/gen_ndr/winbind.h"
#include "param/param.h"
@@ -143,8 +142,7 @@ static void pam_auth_crap_recv_logon(struct composite_context *ctx)
if (!composite_is_ok(state->ctx)) return;
ndr_err = ndr_push_struct_blob(
- &tmp_blob, state, lp_iconv_convenience(state->lp_ctx),
- state->req->out.validation.sam3,
+ &tmp_blob, state, state->req->out.validation.sam3,
(ndr_push_flags_fn_t)ndr_push_netr_SamInfo3);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
state->ctx->status = ndr_map_error2ntstatus(ndr_err);
@@ -179,7 +177,7 @@ static void pam_auth_crap_recv_logon(struct composite_context *ctx)
state->unix_username = talloc_asprintf(state, "%s%s%s",
state->domain_name,
- lp_winbind_separator(state->lp_ctx),
+ lpcfg_winbind_separator(state->lp_ctx),
state->user_name);
if (composite_nomem(state->unix_username, state->ctx)) return;
@@ -221,11 +219,11 @@ struct composite_context *wb_cmd_pam_auth_send(TALLOC_CTX *mem_ctx,
const char *user, *domain;
DATA_BLOB chal, nt_resp, lm_resp, names_blob;
int flags = CLI_CRED_NTLM_AUTH;
- if (lp_client_lanman_auth(service->task->lp_ctx)) {
+ if (lpcfg_client_lanman_auth(service->task->lp_ctx)) {
flags |= CLI_CRED_LANMAN_AUTH;
}
- if (lp_client_ntlmv2_auth(service->task->lp_ctx)) {
+ if (lpcfg_client_ntlmv2_auth(service->task->lp_ctx)) {
flags |= CLI_CRED_NTLMv2_AUTH;
}
@@ -260,11 +258,31 @@ struct composite_context *wb_cmd_pam_auth_send(TALLOC_CTX *mem_ctx,
chal, nt_resp, lm_resp);
}
-NTSTATUS wb_cmd_pam_auth_recv(struct composite_context *c)
+NTSTATUS wb_cmd_pam_auth_recv(struct composite_context *c,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *info3,
+ struct netr_UserSessionKey *user_session_key,
+ struct netr_LMSessionKey *lm_key,
+ char **unix_username)
{
- struct pam_auth_crap_state *state =
- talloc_get_type(c->private_data, struct pam_auth_crap_state);
- NTSTATUS status = composite_wait(c);
- talloc_free(state);
- return status;
+ struct pam_auth_crap_state *state =
+ talloc_get_type(c->private_data, struct pam_auth_crap_state);
+ NTSTATUS status = composite_wait(c);
+ if (NT_STATUS_IS_OK(status)) {
+ if (info3) {
+ info3->length = state->info3.length;
+ info3->data = talloc_steal(mem_ctx, state->info3.data);
+ }
+ if (user_session_key) {
+ *user_session_key = state->user_session_key;
+ }
+ if (lm_key) {
+ *lm_key = state->lm_key;
+ }
+ if (unix_username) {
+ *unix_username = talloc_steal(mem_ctx, state->unix_username);
+ }
+ }
+ talloc_free(state);
+ return status;
}
diff --git a/source4/winbind/wb_sam_logon.c b/source4/winbind/wb_sam_logon.c
index fa3d6032c8..028871a21b 100644
--- a/source4/winbind/wb_sam_logon.c
+++ b/source4/winbind/wb_sam_logon.c
@@ -27,7 +27,6 @@
#include "smbd/service_task.h"
#include "auth/credentials/credentials.h"
#include "libcli/auth/libcli_auth.h"
-#include "librpc/gen_ndr/ndr_netlogon.h"
#include "librpc/gen_ndr/ndr_netlogon_c.h"
#include "librpc/gen_ndr/winbind.h"
@@ -44,7 +43,7 @@ struct wb_sam_logon_state {
};
static void wb_sam_logon_recv_domain(struct composite_context *ctx);
-static void wb_sam_logon_recv_samlogon(struct rpc_request *req);
+static void wb_sam_logon_recv_samlogon(struct tevent_req *subreq);
/*
Find the connection to the DC (or find an existing connection)
@@ -79,8 +78,8 @@ static void wb_sam_logon_recv_domain(struct composite_context *creq)
{
struct wb_sam_logon_state *s = talloc_get_type(creq->async.private_data,
struct wb_sam_logon_state);
- struct rpc_request *req;
struct wbsrv_domain *domain;
+ struct tevent_req *subreq;
s->ctx->status = wb_sid2domain_recv(creq, &domain);
if (!composite_is_ok(s->ctx)) return;
@@ -114,8 +113,12 @@ static void wb_sam_logon_recv_domain(struct composite_context *creq)
s->r_mem_ctx = talloc_new(s);
if (composite_nomem(s->r_mem_ctx, s->ctx)) return;
- req = dcerpc_netr_LogonSamLogon_send(domain->netlogon_pipe, s->r_mem_ctx, &s->r);
- composite_continue_rpc(s->ctx, req, wb_sam_logon_recv_samlogon, s);
+ subreq = dcerpc_netr_LogonSamLogon_r_send(s,
+ s->ctx->event_ctx,
+ domain->netlogon_pipe->binding_handle,
+ &s->r);
+ if (composite_nomem(subreq, s->ctx)) return;
+ tevent_req_set_callback(subreq, wb_sam_logon_recv_samlogon, s);
}
/*
@@ -123,12 +126,13 @@ static void wb_sam_logon_recv_domain(struct composite_context *creq)
Check the SamLogon reply and decrypt the session keys
*/
-static void wb_sam_logon_recv_samlogon(struct rpc_request *req)
+static void wb_sam_logon_recv_samlogon(struct tevent_req *subreq)
{
- struct wb_sam_logon_state *s = talloc_get_type(req->async.private_data,
+ struct wb_sam_logon_state *s = tevent_req_callback_data(subreq,
struct wb_sam_logon_state);
- s->ctx->status = dcerpc_ndr_request_recv(req);
+ s->ctx->status = dcerpc_netr_LogonSamLogon_r_recv(subreq, s->r_mem_ctx);
+ TALLOC_FREE(subreq);
if (!composite_is_ok(s->ctx)) return;
s->ctx->status = s->r.out.result;
diff --git a/source4/winbind/wb_samba3_cmd.c b/source4/winbind/wb_samba3_cmd.c
index b219615b1e..7ceee4193e 100644
--- a/source4/winbind/wb_samba3_cmd.c
+++ b/source4/winbind/wb_samba3_cmd.c
@@ -23,17 +23,117 @@
#include "includes.h"
#include "winbind/wb_server.h"
-#include "winbind/wb_async_helpers.h"
#include "param/param.h"
#include "winbind/wb_helper.h"
#include "libcli/composite/composite.h"
#include "version.h"
-#include "librpc/gen_ndr/netlogon.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
#include "libcli/security/security.h"
-#include "auth/ntlm/pam_errors.h"
+#include "../libcli/auth/pam_errors.h"
#include "auth/credentials/credentials.h"
#include "smbd/service_task.h"
+/*
+ support the old Samba3 TXT form of the info3
+ */
+static NTSTATUS wb_samba3_append_info3_as_txt(TALLOC_CTX *mem_ctx,
+ struct wbsrv_samba3_call *s3call,
+ DATA_BLOB info3b)
+{
+ struct netr_SamInfo3 *info3;
+ char *ex;
+ uint32_t i;
+ enum ndr_err_code ndr_err;
+
+ info3 = talloc(mem_ctx, struct netr_SamInfo3);
+ NT_STATUS_HAVE_NO_MEMORY(info3);
+
+ /* The Samba3 protocol has a redundent 4 bytes at the start */
+ info3b.data += 4;
+ info3b.length -= 4;
+
+ ndr_err = ndr_pull_struct_blob(&info3b,
+ mem_ctx,
+ info3,
+ (ndr_pull_flags_fn_t)ndr_pull_netr_SamInfo3);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return ndr_map_error2ntstatus(ndr_err);
+ }
+
+ s3call->response->data.auth.info3.logon_time =
+ nt_time_to_unix(info3->base.last_logon);
+ s3call->response->data.auth.info3.logoff_time =
+ nt_time_to_unix(info3->base.last_logoff);
+ s3call->response->data.auth.info3.kickoff_time =
+ nt_time_to_unix(info3->base.acct_expiry);
+ s3call->response->data.auth.info3.pass_last_set_time =
+ nt_time_to_unix(info3->base.last_password_change);
+ s3call->response->data.auth.info3.pass_can_change_time =
+ nt_time_to_unix(info3->base.allow_password_change);
+ s3call->response->data.auth.info3.pass_must_change_time =
+ nt_time_to_unix(info3->base.force_password_change);
+
+ s3call->response->data.auth.info3.logon_count = info3->base.logon_count;
+ s3call->response->data.auth.info3.bad_pw_count = info3->base.bad_password_count;
+
+ s3call->response->data.auth.info3.user_rid = info3->base.rid;
+ s3call->response->data.auth.info3.group_rid = info3->base.primary_gid;
+ fstrcpy(s3call->response->data.auth.info3.dom_sid, dom_sid_string(mem_ctx, info3->base.domain_sid));
+
+ s3call->response->data.auth.info3.num_groups = info3->base.groups.count;
+ s3call->response->data.auth.info3.user_flgs = info3->base.user_flags;
+
+ s3call->response->data.auth.info3.acct_flags = info3->base.acct_flags;
+ s3call->response->data.auth.info3.num_other_sids = info3->sidcount;
+
+ fstrcpy(s3call->response->data.auth.info3.user_name,
+ info3->base.account_name.string);
+ fstrcpy(s3call->response->data.auth.info3.full_name,
+ info3->base.full_name.string);
+ fstrcpy(s3call->response->data.auth.info3.logon_script,
+ info3->base.logon_script.string);
+ fstrcpy(s3call->response->data.auth.info3.profile_path,
+ info3->base.profile_path.string);
+ fstrcpy(s3call->response->data.auth.info3.home_dir,
+ info3->base.home_directory.string);
+ fstrcpy(s3call->response->data.auth.info3.dir_drive,
+ info3->base.home_drive.string);
+
+ fstrcpy(s3call->response->data.auth.info3.logon_srv,
+ info3->base.logon_server.string);
+ fstrcpy(s3call->response->data.auth.info3.logon_dom,
+ info3->base.domain.string);
+
+ ex = talloc_strdup(mem_ctx, "");
+ NT_STATUS_HAVE_NO_MEMORY(ex);
+
+ for (i=0; i < info3->base.groups.count; i++) {
+ ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n",
+ info3->base.groups.rids[i].rid,
+ info3->base.groups.rids[i].attributes);
+ NT_STATUS_HAVE_NO_MEMORY(ex);
+ }
+
+ for (i=0; i < info3->sidcount; i++) {
+ char *sid;
+
+ sid = dom_sid_string(mem_ctx, info3->sids[i].sid);
+ NT_STATUS_HAVE_NO_MEMORY(sid);
+
+ ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n",
+ sid,
+ info3->sids[i].attributes);
+ NT_STATUS_HAVE_NO_MEMORY(ex);
+
+ talloc_free(sid);
+ }
+
+ s3call->response->extra_data.data = ex;
+ s3call->response->length += talloc_get_size(ex);
+
+ return NT_STATUS_OK;
+}
+
/*
Send off the reply to an async Samba3 query, handling filling in the PAM, NTSTATUS and string errors.
*/
@@ -41,7 +141,7 @@
static void wbsrv_samba3_async_auth_epilogue(NTSTATUS status,
struct wbsrv_samba3_call *s3call)
{
- struct winbindd_response *resp = &s3call->response;
+ struct winbindd_response *resp = s3call->response;
if (!NT_STATUS_IS_OK(status)) {
resp->result = WINBINDD_ERROR;
} else {
@@ -66,7 +166,7 @@ static void wbsrv_samba3_async_auth_epilogue(NTSTATUS status,
static void wbsrv_samba3_async_epilogue(NTSTATUS status,
struct wbsrv_samba3_call *s3call)
{
- struct winbindd_response *resp = &s3call->response;
+ struct winbindd_response *resp = s3call->response;
if (NT_STATUS_IS_OK(status)) {
resp->result = WINBINDD_OK;
} else {
@@ -82,64 +182,66 @@ static void wbsrv_samba3_async_epilogue(NTSTATUS status,
NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call)
{
- s3call->response.result = WINBINDD_OK;
- s3call->response.data.interface_version = WINBIND_INTERFACE_VERSION;
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->data.interface_version = WINBIND_INTERFACE_VERSION;
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_info(struct wbsrv_samba3_call *s3call)
{
- s3call->response.result = WINBINDD_OK;
- s3call->response.data.info.winbind_separator = *lp_winbind_separator(s3call->wbconn->lp_ctx);
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.info.samba_version,
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->data.info.winbind_separator = *lpcfg_winbind_separator(s3call->wbconn->lp_ctx);
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.info.samba_version,
SAMBA_VERSION_STRING);
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_domain_name(struct wbsrv_samba3_call *s3call)
{
- s3call->response.result = WINBINDD_OK;
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.domain_name,
- lp_workgroup(s3call->wbconn->lp_ctx));
+ s3call->response->result = WINBINDD_OK;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.domain_name,
+ lpcfg_workgroup(s3call->wbconn->lp_ctx));
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_netbios_name(struct wbsrv_samba3_call *s3call)
{
- s3call->response.result = WINBINDD_OK;
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.netbios_name,
- lp_netbios_name(s3call->wbconn->lp_ctx));
+ s3call->response->result = WINBINDD_OK;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.netbios_name,
+ lpcfg_netbios_name(s3call->wbconn->lp_ctx));
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_priv_pipe_dir(struct wbsrv_samba3_call *s3call)
{
- const char *path = s3call->wbconn->listen_socket->service->priv_socket_path;
- s3call->response.result = WINBINDD_OK;
- s3call->response.extra_data.data = discard_const(path);
+ struct loadparm_context *lp_ctx = s3call->wbconn->listen_socket->service->task->lp_ctx;
+ const char *priv_socket_dir = lpcfg_winbindd_privileged_socket_directory(lp_ctx);
- s3call->response.length += strlen(path) + 1;
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->extra_data.data = discard_const(priv_socket_dir);
+
+ s3call->response->length += strlen(priv_socket_dir) + 1;
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
{
- s3call->response.result = WINBINDD_OK;
+ s3call->response->result = WINBINDD_OK;
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_domain_info(struct wbsrv_samba3_call *s3call)
{
DEBUG(5, ("wbsrv_samba3_domain_info called, stub\n"));
- s3call->response.result = WINBINDD_OK;
- fstrcpy(s3call->response.data.domain_info.name,
- s3call->request.domain_name);
- fstrcpy(s3call->response.data.domain_info.alt_name,
- s3call->request.domain_name);
- fstrcpy(s3call->response.data.domain_info.sid, "S-1-2-3-4");
- s3call->response.data.domain_info.native_mode = false;
- s3call->response.data.domain_info.active_directory = false;
- s3call->response.data.domain_info.primary = false;
+ s3call->response->result = WINBINDD_OK;
+ fstrcpy(s3call->response->data.domain_info.name,
+ s3call->request->domain_name);
+ fstrcpy(s3call->response->data.domain_info.alt_name,
+ s3call->request->domain_name);
+ fstrcpy(s3call->response->data.domain_info.sid, "S-1-2-3-4");
+ s3call->response->data.domain_info.native_mode = false;
+ s3call->response->data.domain_info.active_directory = false;
+ s3call->response->data.domain_info.primary = false;
return NT_STATUS_OK;
}
@@ -196,7 +298,7 @@ static void check_machacc_recv(struct composite_context *ctx)
struct wbsrv_samba3_call);
NTSTATUS status;
- status = wb_cmd_pam_auth_recv(ctx);
+ status = wb_cmd_pam_auth_recv(ctx, s3call, NULL, NULL, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) goto done;
@@ -220,7 +322,7 @@ NTSTATUS wbsrv_samba3_getdcname(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_getdcname called\n"));
ctx = wb_cmd_getdcname_send(s3call, service,
- s3call->request.domain_name);
+ s3call->request->domain_name);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = getdcname_recv_dc;
@@ -240,8 +342,8 @@ static void getdcname_recv_dc(struct composite_context *ctx)
status = wb_cmd_getdcname_recv(ctx, s3call, &dcname);
if (!NT_STATUS_IS_OK(status)) goto done;
- s3call->response.result = WINBINDD_OK;
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.dc_name, dcname);
+ s3call->response->result = WINBINDD_OK;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.dc_name, dcname);
done:
wbsrv_samba3_async_epilogue(status, s3call);
@@ -260,10 +362,10 @@ NTSTATUS wbsrv_samba3_userdomgroups(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_userdomgroups called\n"));
- sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
+ sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
if (sid == NULL) {
DEBUG(5, ("Could not parse sid %s\n",
- s3call->request.data.sid));
+ s3call->request->data.sid));
return NT_STATUS_NO_MEMORY;
}
@@ -282,7 +384,7 @@ static void userdomgroups_recv_groups(struct composite_context *ctx)
struct wbsrv_samba3_call *s3call =
talloc_get_type(ctx->async.private_data,
struct wbsrv_samba3_call);
- int i, num_sids;
+ uint32_t i, num_sids;
struct dom_sid **sids;
char *sids_string;
NTSTATUS status;
@@ -306,10 +408,10 @@ static void userdomgroups_recv_groups(struct composite_context *ctx)
goto done;
}
- s3call->response.result = WINBINDD_OK;
- s3call->response.extra_data.data = sids_string;
- s3call->response.length += strlen(sids_string)+1;
- s3call->response.data.num_entries = num_sids;
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->extra_data.data = sids_string;
+ s3call->response->length += strlen(sids_string)+1;
+ s3call->response->data.num_entries = num_sids;
done:
wbsrv_samba3_async_epilogue(status, s3call);
@@ -327,10 +429,10 @@ NTSTATUS wbsrv_samba3_usersids(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_usersids called\n"));
- sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
+ sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
if (sid == NULL) {
DEBUG(5, ("Could not parse sid %s\n",
- s3call->request.data.sid));
+ s3call->request->data.sid));
return NT_STATUS_NO_MEMORY;
}
@@ -349,7 +451,7 @@ static void usersids_recv_sids(struct composite_context *ctx)
struct wbsrv_samba3_call *s3call =
talloc_get_type(ctx->async.private_data,
struct wbsrv_samba3_call);
- int i, num_sids;
+ uint32_t i, num_sids;
struct dom_sid **sids;
char *sids_string;
NTSTATUS status;
@@ -372,10 +474,10 @@ static void usersids_recv_sids(struct composite_context *ctx)
}
}
- s3call->response.result = WINBINDD_OK;
- s3call->response.extra_data.data = sids_string;
- s3call->response.length += strlen(sids_string);
- s3call->response.data.num_entries = num_sids;
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->extra_data.data = sids_string;
+ s3call->response->length += strlen(sids_string);
+ s3call->response->data.num_entries = num_sids;
/* Hmmmm. Nasty protocol -- who invented the zeros between the
* SIDs? Hmmm. Could have been me -- vl */
@@ -406,8 +508,8 @@ NTSTATUS wbsrv_samba3_lookupname(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_lookupname called\n"));
ctx = wb_cmd_lookupname_send(s3call, service,
- s3call->request.data.name.dom_name,
- s3call->request.data.name.name);
+ s3call->request->data.name.dom_name,
+ s3call->request->data.name.name);
NT_STATUS_HAVE_NO_MEMORY(ctx);
/* setup the callbacks */
@@ -428,9 +530,9 @@ static void lookupname_recv_sid(struct composite_context *ctx)
status = wb_cmd_lookupname_recv(ctx, s3call, &sid);
if (!NT_STATUS_IS_OK(status)) goto done;
- s3call->response.result = WINBINDD_OK;
- s3call->response.data.sid.type = sid->type;
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid,
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->data.sid.type = sid->type;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid,
dom_sid_string(s3call, sid->sid));
done:
@@ -452,10 +554,10 @@ NTSTATUS wbsrv_samba3_lookupsid(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_lookupsid called\n"));
- sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
+ sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
if (sid == NULL) {
DEBUG(5, ("Could not parse sid %s\n",
- s3call->request.data.sid));
+ s3call->request->data.sid));
return NT_STATUS_NO_MEMORY;
}
@@ -480,17 +582,43 @@ static void lookupsid_recv_name(struct composite_context *ctx)
status = wb_cmd_lookupsid_recv(ctx, s3call, &sid);
if (!NT_STATUS_IS_OK(status)) goto done;
- s3call->response.result = WINBINDD_OK;
- s3call->response.data.name.type = sid->type;
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.name.dom_name,
+ s3call->response->result = WINBINDD_OK;
+ s3call->response->data.name.type = sid->type;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.name.dom_name,
sid->domain);
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.name.name, sid->name);
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.name.name, sid->name);
done:
wbsrv_samba3_async_epilogue(status, s3call);
}
/*
+ This is a stub function in order to limit error message in the pam_winbind module
+*/
+NTSTATUS wbsrv_samba3_pam_logoff(struct wbsrv_samba3_call *s3call)
+{
+ NTSTATUS status;
+ struct winbindd_response *resp = s3call->response;
+
+ status = NT_STATUS_OK;
+
+ DEBUG(5, ("wbsrv_samba3_pam_logoff called\n"));
+ DEBUG(10, ("Winbind logoff not implemented\n"));
+ resp->result = WINBINDD_OK;
+
+ WBSRV_SAMBA3_SET_STRING(resp->data.auth.nt_status_string,
+ nt_errstr(status));
+ WBSRV_SAMBA3_SET_STRING(resp->data.auth.error_string,
+ get_friendly_nt_error_msg(status));
+
+ resp->data.auth.pam_error = nt_status_to_pam(status);
+ resp->data.auth.nt_status = NT_STATUS_V(status);
+ DEBUG(5, ("wbsrv_samba3_pam_logoff called\n"));
+
+ return NT_STATUS_OK;
+}
+
+/*
Challenge-response authentication. This interface is used by
ntlm_auth and the smbd auth subsystem to pass NTLM authentication
requests along a common pipe to the domain controller.
@@ -511,19 +639,19 @@ NTSTATUS wbsrv_samba3_pam_auth_crap(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_pam_auth_crap called\n"));
- chal.data = s3call->request.data.auth_crap.chal;
- chal.length = sizeof(s3call->request.data.auth_crap.chal);
- nt_resp.data = (uint8_t *)s3call->request.data.auth_crap.nt_resp;
- nt_resp.length = s3call->request.data.auth_crap.nt_resp_len;
- lm_resp.data = (uint8_t *)s3call->request.data.auth_crap.lm_resp;
- lm_resp.length = s3call->request.data.auth_crap.lm_resp_len;
+ chal.data = s3call->request->data.auth_crap.chal;
+ chal.length = sizeof(s3call->request->data.auth_crap.chal);
+ nt_resp.data = (uint8_t *)s3call->request->data.auth_crap.nt_resp;
+ nt_resp.length = s3call->request->data.auth_crap.nt_resp_len;
+ lm_resp.data = (uint8_t *)s3call->request->data.auth_crap.lm_resp;
+ lm_resp.length = s3call->request->data.auth_crap.lm_resp_len;
ctx = wb_cmd_pam_auth_crap_send(
s3call, service,
- s3call->request.data.auth_crap.logon_parameters,
- s3call->request.data.auth_crap.domain,
- s3call->request.data.auth_crap.user,
- s3call->request.data.auth_crap.workstation,
+ s3call->request->data.auth_crap.logon_parameters,
+ s3call->request->data.auth_crap.domain,
+ s3call->request->data.auth_crap.user,
+ s3call->request->data.auth_crap.workstation,
chal, nt_resp, lm_resp);
NT_STATUS_HAVE_NO_MEMORY(ctx);
@@ -548,26 +676,34 @@ static void pam_auth_crap_recv(struct composite_context *ctx)
&user_session_key, &lm_key, &unix_username);
if (!NT_STATUS_IS_OK(status)) goto done;
- if (s3call->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
- memcpy(s3call->response.data.auth.user_session_key,
+ if (s3call->request->flags & WBFLAG_PAM_USER_SESSION_KEY) {
+ memcpy(s3call->response->data.auth.user_session_key,
&user_session_key.key,
- sizeof(s3call->response.data.auth.user_session_key));
+ sizeof(s3call->response->data.auth.user_session_key));
+ }
+
+ if (s3call->request->flags & WBFLAG_PAM_INFO3_TEXT) {
+ status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
}
- if (s3call->request.flags & WBFLAG_PAM_INFO3_NDR) {
- s3call->response.extra_data.data = info3.data;
- s3call->response.length += info3.length;
+ if (s3call->request->flags & WBFLAG_PAM_INFO3_NDR) {
+ s3call->response->extra_data.data = info3.data;
+ s3call->response->length += info3.length;
}
- if (s3call->request.flags & WBFLAG_PAM_LMKEY) {
- memcpy(s3call->response.data.auth.first_8_lm_hash,
+ if (s3call->request->flags & WBFLAG_PAM_LMKEY) {
+ memcpy(s3call->response->data.auth.first_8_lm_hash,
lm_key.key,
- sizeof(s3call->response.data.auth.first_8_lm_hash));
+ sizeof(s3call->response->data.auth.first_8_lm_hash));
}
- if (s3call->request.flags & WBFLAG_PAM_UNIX_NAME) {
- s3call->response.extra_data.data = unix_username;
- s3call->response.length += strlen(unix_username)+1;
+ if (s3call->request->flags & WBFLAG_PAM_UNIX_NAME) {
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.auth.unix_username,unix_username);
}
done:
@@ -592,7 +728,7 @@ NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call)
char *user, *domain;
if (!wb_samba3_split_username(s3call, s3call->wbconn->lp_ctx,
- s3call->request.data.auth.user,
+ s3call->request->data.auth.user,
&domain, &user)) {
return NT_STATUS_NO_SUCH_USER;
}
@@ -605,7 +741,7 @@ NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call)
cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
- cli_credentials_set_password(credentials, s3call->request.data.auth.pass, CRED_SPECIFIED);
+ cli_credentials_set_password(credentials, s3call->request->data.auth.pass, CRED_SPECIFIED);
ctx = wb_cmd_pam_auth_send(s3call, service, credentials);
NT_STATUS_HAVE_NO_MEMORY(ctx);
@@ -622,11 +758,47 @@ static void pam_auth_recv(struct composite_context *ctx)
talloc_get_type(ctx->async.private_data,
struct wbsrv_samba3_call);
NTSTATUS status;
+ DATA_BLOB info3;
+ struct netr_UserSessionKey user_session_key;
+ struct netr_LMSessionKey lm_key;
+ char *unix_username;
- status = wb_cmd_pam_auth_recv(ctx);
+ status = wb_cmd_pam_auth_recv(ctx, s3call, &info3,
+ &user_session_key, &lm_key, &unix_username);
if (!NT_STATUS_IS_OK(status)) goto done;
+ if (s3call->request->flags & WBFLAG_PAM_USER_SESSION_KEY) {
+ memcpy(s3call->response->data.auth.user_session_key,
+ &user_session_key.key,
+ sizeof(s3call->response->data.auth.user_session_key));
+ }
+
+ if (s3call->request->flags & WBFLAG_PAM_INFO3_TEXT) {
+ status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
+ nt_errstr(status)));
+ goto done;
+ }
+ }
+
+ if (s3call->request->flags & WBFLAG_PAM_INFO3_NDR) {
+ s3call->response->extra_data.data = info3.data;
+ s3call->response->length += info3.length;
+ }
+
+ if (s3call->request->flags & WBFLAG_PAM_LMKEY) {
+ memcpy(s3call->response->data.auth.first_8_lm_hash,
+ lm_key.key,
+ sizeof(s3call->response->data.auth.first_8_lm_hash));
+ }
+
+ if (s3call->request->flags & WBFLAG_PAM_UNIX_NAME) {
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.auth.unix_username,unix_username);
+ }
+
+
done:
wbsrv_samba3_async_auth_epilogue(status, s3call);
}
@@ -659,7 +831,7 @@ static void list_trustdom_recv_doms(struct composite_context *ctx)
struct wbsrv_samba3_call *s3call =
talloc_get_type(ctx->async.private_data,
struct wbsrv_samba3_call);
- int i, num_domains;
+ uint32_t i, num_domains;
struct wb_dom_info **domains;
NTSTATUS status;
char *result;
@@ -686,10 +858,11 @@ static void list_trustdom_recv_doms(struct composite_context *ctx)
goto done;
}
- s3call->response.result = WINBINDD_OK;
+ s3call->response->result = WINBINDD_OK;
if (num_domains > 0) {
- s3call->response.extra_data.data = result;
- s3call->response.length += strlen(result)+1;
+ s3call->response->extra_data.data = result;
+ s3call->response->length += strlen(result)+1;
+ s3call->response->data.num_entries = num_domains;
}
done:
@@ -707,7 +880,7 @@ NTSTATUS wbsrv_samba3_list_groups(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba4_list_groups called\n"));
ctx = wb_cmd_list_groups_send(s3call, service,
- s3call->request.domain_name);
+ s3call->request->domain_name);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = list_groups_recv;
@@ -723,18 +896,20 @@ static void list_groups_recv(struct composite_context *ctx)
struct wbsrv_samba3_call);
uint32_t extra_data_len;
char *extra_data;
+ uint32_t num_groups;
NTSTATUS status;
DEBUG(5, ("list_groups_recv called\n"));
status = wb_cmd_list_groups_recv(ctx, s3call, &extra_data_len,
- &extra_data);
+ &extra_data, &num_groups);
if (NT_STATUS_IS_OK(status)) {
- s3call->response.extra_data.data = extra_data;
- s3call->response.length += extra_data_len;
+ s3call->response->extra_data.data = extra_data;
+ s3call->response->length += extra_data_len;
if (extra_data) {
- s3call->response.length += 1;
+ s3call->response->length += 1;
+ s3call->response->data.num_entries = num_groups;
}
}
@@ -754,7 +929,7 @@ NTSTATUS wbsrv_samba3_list_users(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_list_users called\n"));
ctx = wb_cmd_list_users_send(s3call, service,
- s3call->request.domain_name);
+ s3call->request->domain_name);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = list_users_recv;
@@ -770,18 +945,20 @@ static void list_users_recv(struct composite_context *ctx)
struct wbsrv_samba3_call);
uint32_t extra_data_len;
char *extra_data;
+ uint32_t num_users;
NTSTATUS status;
DEBUG(5, ("list_users_recv called\n"));
status = wb_cmd_list_users_recv(ctx, s3call, &extra_data_len,
- &extra_data);
+ &extra_data, &num_users);
if (NT_STATUS_IS_OK(status)) {
- s3call->response.extra_data.data = extra_data;
- s3call->response.length += extra_data_len;
+ s3call->response->extra_data.data = extra_data;
+ s3call->response->length += extra_data_len;
if (extra_data) {
- s3call->response.length += 1;
+ s3call->response->length += 1;
+ s3call->response->data.num_entries = num_users;
}
}
@@ -801,7 +978,7 @@ NTSTATUS wbsrv_samba3_getpwnam(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_getpwnam called\n"));
ctx = wb_cmd_getpwnam_send(s3call, service,
- s3call->request.data.username);
+ s3call->request->data.username);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = getpwnam_recv;
@@ -822,7 +999,7 @@ static void getpwnam_recv(struct composite_context *ctx)
status = wb_cmd_getpwnam_recv(ctx, s3call, &pw);
if(NT_STATUS_IS_OK(status))
- s3call->response.data.pw = *pw;
+ s3call->response->data.pw = *pw;
wbsrv_samba3_async_epilogue(status, s3call);
}
@@ -837,7 +1014,7 @@ NTSTATUS wbsrv_samba3_getpwuid(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_getpwuid called\n"));
ctx = wb_cmd_getpwuid_send(s3call, service,
- s3call->request.data.uid);
+ s3call->request->data.uid);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = getpwuid_recv;
@@ -858,7 +1035,7 @@ static void getpwuid_recv(struct composite_context *ctx)
status = wb_cmd_getpwuid_recv(ctx, s3call, &pw);
if (NT_STATUS_IS_OK(status))
- s3call->response.data.pw = *pw;
+ s3call->response->data.pw = *pw;
wbsrv_samba3_async_epilogue(status, s3call);
}
@@ -916,7 +1093,7 @@ NTSTATUS wbsrv_samba3_getpwent(struct wbsrv_samba3_call *s3call)
NT_STATUS_HAVE_NO_MEMORY(pwent);
ctx = wb_cmd_getpwent_send(s3call, service, pwent,
- s3call->request.data.num_entries);
+ s3call->request->data.num_entries);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = getpwent_recv;
@@ -940,9 +1117,9 @@ static void getpwent_recv(struct composite_context *ctx)
if (NT_STATUS_IS_OK(status)) {
uint32_t extra_len = sizeof(struct winbindd_pw) * num_users;
- s3call->response.data.num_entries = num_users;
- s3call->response.extra_data.data = pw;
- s3call->response.length += extra_len;
+ s3call->response->data.num_entries = num_users;
+ s3call->response->extra_data.data = pw;
+ s3call->response->length += extra_len;
}
wbsrv_samba3_async_epilogue(status, s3call);
@@ -958,7 +1135,7 @@ NTSTATUS wbsrv_samba3_endpwent(struct wbsrv_samba3_call *s3call)
talloc_free(pwent);
s3call->wbconn->protocol_private_data = NULL;
- s3call->response.result = WINBINDD_OK;
+ s3call->response->result = WINBINDD_OK;
return NT_STATUS_OK;
}
@@ -974,7 +1151,7 @@ NTSTATUS wbsrv_samba3_getgrnam(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_getgrnam called\n"));
ctx = wb_cmd_getgrnam_send(s3call, service,
- s3call->request.data.groupname);
+ s3call->request->data.groupname);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = getgrnam_recv;
@@ -995,7 +1172,7 @@ static void getgrnam_recv(struct composite_context *ctx)
status = wb_cmd_getgrnam_recv(ctx, s3call, &gr);
if(NT_STATUS_IS_OK(status))
- s3call->response.data.gr = *gr;
+ s3call->response->data.gr = *gr;
wbsrv_samba3_async_epilogue(status, s3call);
}
@@ -1010,7 +1187,7 @@ NTSTATUS wbsrv_samba3_getgrgid(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_getgrgid called\n"));
ctx = wb_cmd_getgrgid_send(s3call, service,
- s3call->request.data.gid);
+ s3call->request->data.gid);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = getgrgid_recv;
@@ -1031,36 +1208,143 @@ static void getgrgid_recv(struct composite_context *ctx)
status = wb_cmd_getgrgid_recv(ctx, s3call, &gr);
if (NT_STATUS_IS_OK(status))
- s3call->response.data.gr = *gr;
+ s3call->response->data.gr = *gr;
wbsrv_samba3_async_epilogue(status, s3call);
}
+static void getgroups_recv(struct composite_context *ctx);
+
NTSTATUS wbsrv_samba3_getgroups(struct wbsrv_samba3_call *s3call)
{
+ struct composite_context *ctx;
+ struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
+
DEBUG(5, ("wbsrv_samba3_getgroups called\n"));
- s3call->response.result = WINBINDD_ERROR;
+ /* S3 code do the same so why not ... */
+ s3call->request->data.username[sizeof(s3call->request->data.username)-1]='\0';
+ ctx = wb_cmd_getgroups_send(s3call, service, s3call->request->data.username);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = getgroups_recv;
+ ctx->async.private_data = s3call;
+ s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
return NT_STATUS_OK;
}
+static void getgroups_recv(struct composite_context *ctx)
+{
+ struct wbsrv_samba3_call *s3call =
+ talloc_get_type(ctx->async.private_data,
+ struct wbsrv_samba3_call);
+ gid_t *gids;
+ uint32_t num_groups;
+ NTSTATUS status;
+ DEBUG(5, ("getgroups_recv called\n"));
+
+ status = wb_cmd_getgroups_recv(ctx, s3call, &gids, &num_groups);
+ if (NT_STATUS_IS_OK(status)) {
+ uint32_t extra_len = sizeof(gid_t) * num_groups;
+
+ s3call->response->data.num_entries = num_groups;
+ s3call->response->extra_data.data = gids;
+ s3call->response->length += extra_len;
+ } else {
+ s3call->response->result = WINBINDD_ERROR;
+ }
+
+ wbsrv_samba3_async_epilogue(status, s3call);
+}
+
+static void setgrent_recv(struct composite_context *ctx);
+
NTSTATUS wbsrv_samba3_setgrent(struct wbsrv_samba3_call *s3call)
{
+ struct composite_context *ctx;
+ struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
+
DEBUG(5, ("wbsrv_samba3_setgrent called\n"));
- s3call->response.result = WINBINDD_OK;
+
+ ctx = wb_cmd_setgrent_send(s3call, service);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = setgrent_recv;
+ ctx->async.private_data = s3call;
+ s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
return NT_STATUS_OK;
}
+static void setgrent_recv(struct composite_context *ctx)
+{
+ struct wbsrv_samba3_call *s3call =
+ talloc_get_type(ctx->async.private_data,
+ struct wbsrv_samba3_call);
+ NTSTATUS status;
+ struct wbsrv_grent *grent;
+
+ DEBUG(5, ("setpwent_recv called\n"));
+
+ status = wb_cmd_setgrent_recv(ctx, s3call->wbconn, &grent);
+ if (NT_STATUS_IS_OK(status)) {
+ s3call->wbconn->protocol_private_data = grent;
+ }
+
+ wbsrv_samba3_async_epilogue(status, s3call);
+}
+
+static void getgrent_recv(struct composite_context *ctx);
+
NTSTATUS wbsrv_samba3_getgrent(struct wbsrv_samba3_call *s3call)
{
+ struct composite_context *ctx;
+ struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
+ struct wbsrv_grent *grent;
+
DEBUG(5, ("wbsrv_samba3_getgrent called\n"));
- s3call->response.result = WINBINDD_ERROR;
+
+ NT_STATUS_HAVE_NO_MEMORY(s3call->wbconn->protocol_private_data);
+
+ grent = talloc_get_type(s3call->wbconn->protocol_private_data,
+ struct wbsrv_grent);
+ NT_STATUS_HAVE_NO_MEMORY(grent);
+
+ ctx = wb_cmd_getgrent_send(s3call, service, grent,
+ s3call->request->data.num_entries);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = getgrent_recv;
+ ctx->async.private_data = s3call;
+ s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
return NT_STATUS_OK;
}
+static void getgrent_recv(struct composite_context *ctx)
+{
+ struct wbsrv_samba3_call *s3call =
+ talloc_get_type(ctx->async.private_data,
+ struct wbsrv_samba3_call);
+ NTSTATUS status;
+ struct winbindd_gr *gr;
+ uint32_t num_groups;
+
+ DEBUG(5, ("getgrent_recv called\n"));
+
+ status = wb_cmd_getgrent_recv(ctx, s3call, &gr, &num_groups);
+ if (NT_STATUS_IS_OK(status)) {
+ uint32_t extra_len = sizeof(struct winbindd_gr) * num_groups;
+
+ s3call->response->data.num_entries = num_groups;
+ s3call->response->extra_data.data = gr;
+ s3call->response->length += extra_len;
+ }
+
+ wbsrv_samba3_async_epilogue(status, s3call);
+}
+
NTSTATUS wbsrv_samba3_endgrent(struct wbsrv_samba3_call *s3call)
{
DEBUG(5, ("wbsrv_samba3_endgrent called\n"));
- s3call->response.result = WINBINDD_OK;
+ s3call->response->result = WINBINDD_OK;
return NT_STATUS_OK;
}
@@ -1075,7 +1359,7 @@ NTSTATUS wbsrv_samba3_sid2uid(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_sid2uid called\n"));
- sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
+ sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
NT_STATUS_HAVE_NO_MEMORY(sid);
ctx = wb_sid2uid_send(s3call, service, sid);
@@ -1097,7 +1381,7 @@ static void sid2uid_recv(struct composite_context *ctx)
DEBUG(5, ("sid2uid_recv called\n"));
- status = wb_sid2uid_recv(ctx, &s3call->response.data.uid);
+ status = wb_sid2uid_recv(ctx, &s3call->response->data.uid);
wbsrv_samba3_async_epilogue(status, s3call);
}
@@ -1113,7 +1397,7 @@ NTSTATUS wbsrv_samba3_sid2gid(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_sid2gid called\n"));
- sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
+ sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
NT_STATUS_HAVE_NO_MEMORY(sid);
ctx = wb_sid2gid_send(s3call, service, sid);
@@ -1135,7 +1419,7 @@ static void sid2gid_recv(struct composite_context *ctx)
DEBUG(5, ("sid2gid_recv called\n"));
- status = wb_sid2gid_recv(ctx, &s3call->response.data.gid);
+ status = wb_sid2gid_recv(ctx, &s3call->response->data.gid);
wbsrv_samba3_async_epilogue(status, s3call);
}
@@ -1150,7 +1434,7 @@ NTSTATUS wbsrv_samba3_uid2sid(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_uid2sid called\n"));
- ctx = wb_uid2sid_send(s3call, service, s3call->request.data.uid);
+ ctx = wb_uid2sid_send(s3call, service, s3call->request->data.uid);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = uid2sid_recv;
@@ -1181,8 +1465,8 @@ static void uid2sid_recv(struct composite_context *ctx)
/* But we assume this worked, so we'll set the string. Work
* done. */
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid, sid_str);
- s3call->response.data.sid.type = SID_NAME_USER;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid, sid_str);
+ s3call->response->data.sid.type = SID_NAME_USER;
}
wbsrv_samba3_async_epilogue(status, s3call);
@@ -1198,7 +1482,7 @@ NTSTATUS wbsrv_samba3_gid2sid(struct wbsrv_samba3_call *s3call)
DEBUG(5, ("wbsrv_samba3_gid2sid called\n"));
- ctx = wb_gid2sid_send(s3call, service, s3call->request.data.gid);
+ ctx = wb_gid2sid_send(s3call, service, s3call->request->data.gid);
NT_STATUS_HAVE_NO_MEMORY(ctx);
ctx->async.fn = gid2sid_recv;
@@ -1226,8 +1510,8 @@ static void gid2sid_recv(struct composite_context *ctx)
if (sid_str == NULL)
wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
- WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid, sid_str);
- s3call->response.data.sid.type = SID_NAME_DOMAIN;
+ WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid, sid_str);
+ s3call->response->data.sid.type = SID_NAME_DOMAIN;
}
wbsrv_samba3_async_epilogue(status, s3call);
diff --git a/source4/winbind/wb_samba3_protocol.c b/source4/winbind/wb_samba3_protocol.c
index 250525cfb2..4bb0582cd2 100644
--- a/source4/winbind/wb_samba3_protocol.c
+++ b/source4/winbind/wb_samba3_protocol.c
@@ -23,6 +23,7 @@
#include "winbind/wb_server.h"
#include "smbd/service_stream.h"
#include "lib/stream/packet.h"
+#include "lib/tsocket/tsocket.h"
/*
work out if a packet is complete for protocols that use a 32 bit host byte
@@ -43,38 +44,34 @@ NTSTATUS wbsrv_samba3_packet_full_request(void *private_data, DATA_BLOB blob, si
}
-NTSTATUS wbsrv_samba3_pull_request(DATA_BLOB blob, struct wbsrv_connection *wbconn,
- struct wbsrv_samba3_call **_call)
+NTSTATUS wbsrv_samba3_pull_request(struct wbsrv_samba3_call *call)
{
- struct wbsrv_samba3_call *call;
-
- if (blob.length != sizeof(call->request)) {
+ if (call->in.length != sizeof(*call->request)) {
DEBUG(0,("wbsrv_samba3_pull_request: invalid blob length %lu should be %lu\n"
" make sure you use the correct winbind client tools!\n",
- (long)blob.length, (long)sizeof(call->request)));
+ (long)call->in.length, (long)sizeof(*call->request)));
return NT_STATUS_INVALID_PARAMETER;
}
- call = talloc_zero(wbconn, struct wbsrv_samba3_call);
- NT_STATUS_HAVE_NO_MEMORY(call);
+ call->request = talloc_zero(call, struct winbindd_request);
+ NT_STATUS_HAVE_NO_MEMORY(call->request);
/* the packet layout is the same as the in memory layout of the request, so just copy it */
- memcpy(&call->request, blob.data, sizeof(call->request));
+ memcpy(call->request, call->in.data, sizeof(*call->request));
- call->wbconn = wbconn;
- call->event_ctx = call->wbconn->conn->event.ctx;
-
- *_call = call;
return NT_STATUS_OK;
}
NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_samba3_call *s3call)
{
- DEBUG(10, ("Got winbind samba3 request %d\n", s3call->request.cmd));
+ DEBUG(10, ("Got winbind samba3 request %d\n", s3call->request->cmd));
+
+ s3call->response = talloc_zero(s3call, struct winbindd_response);
+ NT_STATUS_HAVE_NO_MEMORY(s3call->request);
- s3call->response.length = sizeof(s3call->response);
+ s3call->response->length = sizeof(*s3call->response);
- switch(s3call->request.cmd) {
+ switch(s3call->request->cmd) {
case WINBINDD_INTERFACE_VERSION:
return wbsrv_samba3_interface_version(s3call);
@@ -178,19 +175,17 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_samba3_call *s3call)
case WINBINDD_DOMAIN_INFO:
return wbsrv_samba3_domain_info(s3call);
- /* Unimplemented commands */
+ case WINBINDD_PAM_LOGOFF:
+ return wbsrv_samba3_pam_logoff(s3call);
+ /* Unimplemented commands */
case WINBINDD_GETPWSID:
case WINBINDD_PAM_CHAUTHTOK:
- case WINBINDD_PAM_LOGOFF:
case WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP:
case WINBINDD_LOOKUPRIDS:
case WINBINDD_SIDS_TO_XIDS:
case WINBINDD_ALLOCATE_UID:
case WINBINDD_ALLOCATE_GID:
- case WINBINDD_SET_MAPPING:
- case WINBINDD_REMOVE_MAPPING:
- case WINBINDD_SET_HWM:
case WINBINDD_SHOW_SEQUENCE:
case WINBINDD_WINS_BYIP:
case WINBINDD_WINS_BYNAME:
@@ -199,54 +194,54 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_samba3_call *s3call)
case WINBINDD_DSGETDCNAME:
case WINBINDD_INIT_CONNECTION:
case WINBINDD_DUAL_SIDS2XIDS:
- case WINBINDD_DUAL_SET_MAPPING:
- case WINBINDD_DUAL_REMOVE_MAPPING:
- case WINBINDD_DUAL_SET_HWM:
case WINBINDD_DUAL_USERINFO:
case WINBINDD_DUAL_GETSIDALIASES:
case WINBINDD_DUAL_NDRCMD:
case WINBINDD_CCACHE_NTLMAUTH:
case WINBINDD_NUM_CMDS:
DEBUG(10, ("Unimplemented winbind samba3 request %d\n",
- s3call->request.cmd));
+ s3call->request->cmd));
break;
}
- s3call->response.result = WINBINDD_ERROR;
+ s3call->response->result = WINBINDD_ERROR;
return NT_STATUS_OK;
}
-static NTSTATUS wbsrv_samba3_push_reply(struct wbsrv_samba3_call *call, TALLOC_CTX *mem_ctx, DATA_BLOB *_blob)
+static NTSTATUS wbsrv_samba3_push_reply(struct wbsrv_samba3_call *call)
{
- DATA_BLOB blob;
uint8_t *extra_data;
size_t extra_data_len = 0;
- extra_data = (uint8_t *)call->response.extra_data.data;
+ extra_data = (uint8_t *)call->response->extra_data.data;
if (extra_data != NULL) {
- extra_data_len = call->response.length -
- sizeof(call->response);
+ extra_data_len = call->response->length -
+ sizeof(*call->response);
}
- blob = data_blob_talloc(mem_ctx, NULL, call->response.length);
- NT_STATUS_HAVE_NO_MEMORY(blob.data);
+ call->out = data_blob_talloc(call, NULL, call->response->length);
+ NT_STATUS_HAVE_NO_MEMORY(call->out.data);
/* don't push real pointer values into sockets */
if (extra_data) {
- call->response.extra_data.data = (void *)0xFFFFFFFF;
+ call->response->extra_data.data = (void *)0xFFFFFFFF;
}
- memcpy(blob.data, &call->response, sizeof(call->response));
+
+ memcpy(call->out.data, call->response, sizeof(*call->response));
/* set back the pointer */
- call->response.extra_data.data = extra_data;
+ call->response->extra_data.data = extra_data;
if (extra_data) {
- memcpy(blob.data + sizeof(call->response), extra_data, extra_data_len);
+ memcpy(call->out.data + sizeof(*call->response),
+ extra_data,
+ extra_data_len);
}
- *_blob = blob;
return NT_STATUS_OK;
}
+static void wbsrv_samba3_send_reply_done(struct tevent_req *subreq);
+
/*
* queue a wbsrv_call reply on a wbsrv_connection
* NOTE: that this implies talloc_free(call),
@@ -255,38 +250,68 @@ static NTSTATUS wbsrv_samba3_push_reply(struct wbsrv_samba3_call *call, TALLOC_C
*/
NTSTATUS wbsrv_samba3_send_reply(struct wbsrv_samba3_call *call)
{
- struct wbsrv_connection *wbconn = call->wbconn;
- DATA_BLOB rep;
+ struct wbsrv_connection *wbsrv_conn = call->wbconn;
+ struct tevent_req *subreq;
NTSTATUS status;
- status = wbsrv_samba3_push_reply(call, call, &rep);
+ status = wbsrv_samba3_push_reply(call);
NT_STATUS_NOT_OK_RETURN(status);
- status = packet_send(call->wbconn->packet, rep);
-
- talloc_free(call);
-
- if (!NT_STATUS_IS_OK(status)) {
- wbsrv_terminate_connection(wbconn,
- "failed to packet_send winbindd reply");
- return status;
+ call->out_iov[0].iov_base = (char *) call->out.data;
+ call->out_iov[0].iov_len = call->out.length;
+
+ subreq = tstream_writev_queue_send(call,
+ wbsrv_conn->conn->event.ctx,
+ wbsrv_conn->tstream,
+ wbsrv_conn->send_queue,
+ call->out_iov, 1);
+ if (subreq == NULL) {
+ wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
+ "no memory for tstream_writev_queue_send");
+ return NT_STATUS_NO_MEMORY;
}
- /* the call isn't needed any more */
+ tevent_req_set_callback(subreq, wbsrv_samba3_send_reply_done, call);
+
return status;
}
-NTSTATUS wbsrv_samba3_process(void *private_data, DATA_BLOB blob)
+static void wbsrv_samba3_send_reply_done(struct tevent_req *subreq)
+{
+ struct wbsrv_samba3_call *call = tevent_req_callback_data(subreq,
+ struct wbsrv_samba3_call);
+ int sys_errno;
+ int rc;
+
+ rc = tstream_writev_queue_recv(subreq, &sys_errno);
+ TALLOC_FREE(subreq);
+ if (rc == -1) {
+ const char *reason;
+
+ reason = talloc_asprintf(call, "wbsrv_samba3_send_reply_done: "
+ "tstream_writev_queue_recv() - %d:%s",
+ sys_errno, strerror(sys_errno));
+ if (reason == NULL) {
+ reason = "wbsrv_samba3_send_reply_done: "
+ "tstream_writev_queue_recv() failed";
+ }
+
+ wbsrv_terminate_connection(call->wbconn, reason);
+ return;
+ }
+
+ talloc_free(call);
+}
+
+NTSTATUS wbsrv_samba3_process(struct wbsrv_samba3_call *call)
{
NTSTATUS status;
- struct wbsrv_connection *wbconn = talloc_get_type(private_data,
- struct wbsrv_connection);
- struct wbsrv_samba3_call *call;
- status = wbsrv_samba3_pull_request(blob, wbconn, &call);
+
+ status = wbsrv_samba3_pull_request(call);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
-
+
status = wbsrv_samba3_handle_call(call);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/winbind/wb_server.c b/source4/winbind/wb_server.c
index d3142ff52a..5390dab2f7 100644
--- a/source4/winbind/wb_server.c
+++ b/source4/winbind/wb_server.c
@@ -2,8 +2,9 @@
Unix SMB/CIFS implementation.
Main winbindd server routines
- Copyright (C) Stefan Metzmacher 2005
+ Copyright (C) Stefan Metzmacher 2005-2008
Copyright (C) Andrew Tridgell 2005
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,73 +21,152 @@
*/
#include "includes.h"
-#include "lib/socket/socket.h"
-#include "../lib/util/dlinklist.h"
-#include "lib/events/events.h"
-#include "smbd/service_task.h"
#include "smbd/process_model.h"
-#include "smbd/service_stream.h"
-#include "nsswitch/winbind_nss_config.h"
#include "winbind/wb_server.h"
#include "lib/stream/packet.h"
-#include "smbd/service.h"
-#include "param/secrets.h"
+#include "lib/tsocket/tsocket.h"
+#include "libcli/util/tstream.h"
#include "param/param.h"
+#include "param/secrets.h"
void wbsrv_terminate_connection(struct wbsrv_connection *wbconn, const char *reason)
{
stream_terminate_connection(wbconn->conn, reason);
}
-/*
- called on a tcp recv error
-*/
-static void wbsrv_recv_error(void *private_data, NTSTATUS status)
+static void wbsrv_call_loop(struct tevent_req *subreq)
{
- struct wbsrv_connection *wbconn = talloc_get_type(private_data, struct wbsrv_connection);
- wbsrv_terminate_connection(wbconn, nt_errstr(status));
+ struct wbsrv_connection *wbsrv_conn = tevent_req_callback_data(subreq,
+ struct wbsrv_connection);
+ struct wbsrv_samba3_call *call;
+ NTSTATUS status;
+
+ call = talloc_zero(wbsrv_conn, struct wbsrv_samba3_call);
+ if (call == NULL) {
+ wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
+ "no memory for wbsrv_samba3_call");
+ return;
+ }
+ call->wbconn = wbsrv_conn;
+
+ status = tstream_read_pdu_blob_recv(subreq,
+ call,
+ &call->in);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *reason;
+
+ reason = talloc_asprintf(call, "wbsrv_call_loop: "
+ "tstream_read_pdu_blob_recv() - %s",
+ nt_errstr(status));
+ if (!reason) {
+ reason = nt_errstr(status);
+ }
+
+ wbsrv_terminate_connection(wbsrv_conn, reason);
+ return;
+ }
+
+ DEBUG(10,("Received winbind TCP packet of length %lu from %s\n",
+ (long) call->in.length,
+ tsocket_address_string(wbsrv_conn->conn->remote_address, call)));
+
+ status = wbsrv_samba3_process(call);
+ if (!NT_STATUS_IS_OK(status)) {
+ const char *reason;
+
+ reason = talloc_asprintf(call, "wbsrv_call_loop: "
+ "tstream_read_pdu_blob_recv() - %s",
+ nt_errstr(status));
+ if (!reason) {
+ reason = nt_errstr(status);
+ }
+
+ wbsrv_terminate_connection(wbsrv_conn, reason);
+ return;
+ }
+
+ /*
+ * The winbind pdu's has the length as 4 byte (initial_read_size),
+ * wbsrv_samba3_packet_full_request provides the pdu length then.
+ */
+ subreq = tstream_read_pdu_blob_send(wbsrv_conn,
+ wbsrv_conn->conn->event.ctx,
+ wbsrv_conn->tstream,
+ 4, /* initial_read_size */
+ wbsrv_samba3_packet_full_request,
+ wbsrv_conn);
+ if (subreq == NULL) {
+ wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: "
+ "no memory for tstream_read_pdu_blob_send");
+ return;
+ }
+ tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn);
}
static void wbsrv_accept(struct stream_connection *conn)
{
- struct wbsrv_listen_socket *listen_socket = talloc_get_type(conn->private_data,
- struct wbsrv_listen_socket);
- struct wbsrv_connection *wbconn;
+ struct wbsrv_listen_socket *wbsrv_socket = talloc_get_type(conn->private_data,
+ struct wbsrv_listen_socket);
+ struct wbsrv_connection *wbsrv_conn;
+ struct tevent_req *subreq;
+ int rc;
- wbconn = talloc_zero(conn, struct wbsrv_connection);
- if (!wbconn) {
+ wbsrv_conn = talloc_zero(conn, struct wbsrv_connection);
+ if (wbsrv_conn == NULL) {
stream_terminate_connection(conn, "wbsrv_accept: out of memory");
return;
}
- wbconn->conn = conn;
- wbconn->listen_socket = listen_socket;
- wbconn->lp_ctx = listen_socket->service->task->lp_ctx;
- conn->private_data = wbconn;
-
- wbconn->packet = packet_init(wbconn);
- if (wbconn->packet == NULL) {
- wbsrv_terminate_connection(wbconn, "wbsrv_accept: out of memory");
+
+ wbsrv_conn->send_queue = tevent_queue_create(conn, "wbsrv_accept");
+ if (wbsrv_conn->send_queue == NULL) {
+ stream_terminate_connection(conn,
+ "wbsrv_accept: out of memory");
+ return;
+ }
+
+ TALLOC_FREE(conn->event.fde);
+
+ rc = tstream_bsd_existing_socket(wbsrv_conn,
+ socket_get_fd(conn->socket),
+ &wbsrv_conn->tstream);
+ if (rc < 0) {
+ stream_terminate_connection(conn,
+ "wbsrv_accept: out of memory");
return;
}
- packet_set_private(wbconn->packet, wbconn);
- packet_set_socket(wbconn->packet, conn->socket);
- packet_set_callback(wbconn->packet, wbsrv_samba3_process);
- packet_set_full_request(wbconn->packet, wbsrv_samba3_packet_full_request);
- packet_set_error_handler(wbconn->packet, wbsrv_recv_error);
- packet_set_event_context(wbconn->packet, conn->event.ctx);
- packet_set_fde(wbconn->packet, conn->event.fde);
- packet_set_serialise(wbconn->packet);
+
+ wbsrv_conn->conn = conn;
+ wbsrv_conn->listen_socket = wbsrv_socket;
+ wbsrv_conn->lp_ctx = wbsrv_socket->service->task->lp_ctx;
+ conn->private_data = wbsrv_conn;
+
+ /*
+ * The winbind pdu's has the length as 4 byte (initial_read_size),
+ * wbsrv_samba3_packet_full_request provides the pdu length then.
+ */
+ subreq = tstream_read_pdu_blob_send(wbsrv_conn,
+ wbsrv_conn->conn->event.ctx,
+ wbsrv_conn->tstream,
+ 4, /* initial_read_size */
+ wbsrv_samba3_packet_full_request,
+ wbsrv_conn);
+ if (subreq == NULL) {
+ wbsrv_terminate_connection(wbsrv_conn, "wbsrv_accept: "
+ "no memory for tstream_read_pdu_blob_send");
+ return;
+ }
+ tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn);
}
/*
- receive some data on a winbind connection
+ called on a tcp recv
*/
static void wbsrv_recv(struct stream_connection *conn, uint16_t flags)
{
- struct wbsrv_connection *wbconn = talloc_get_type(conn->private_data,
- struct wbsrv_connection);
- packet_recv(wbconn->packet);
-
+ struct wbsrv_connection *wbsrv_conn = talloc_get_type(conn->private_data,
+ struct wbsrv_connection);
+ wbsrv_terminate_connection(wbsrv_conn, "wbsrv_recv: called");
}
/*
@@ -94,9 +174,10 @@ static void wbsrv_recv(struct stream_connection *conn, uint16_t flags)
*/
static void wbsrv_send(struct stream_connection *conn, uint16_t flags)
{
- struct wbsrv_connection *wbconn = talloc_get_type(conn->private_data,
- struct wbsrv_connection);
- packet_queue_run(wbconn->packet);
+ struct wbsrv_connection *wbsrv_conn = talloc_get_type(conn->private_data,
+ struct wbsrv_connection);
+ /* this should never be triggered! */
+ wbsrv_terminate_connection(wbsrv_conn, "wbsrv_send: called");
}
static const struct stream_server_ops wbsrv_ops = {
@@ -116,13 +197,15 @@ static void winbind_task_init(struct task_server *task)
NTSTATUS status;
struct wbsrv_service *service;
struct wbsrv_listen_socket *listen_socket;
+ char *errstring;
+ struct dom_sid *primary_sid;
task_server_set_title(task, "task[winbind]");
/* within the winbind task we want to be a single process, so
ask for the single process model ops and pass these to the
stream_setup_socket() call. */
- model_ops = process_model_startup(task->event_ctx, "single");
+ model_ops = process_model_startup("single");
if (!model_ops) {
task_server_terminate(task,
"Can't find 'single' process model_ops", true);
@@ -130,14 +213,14 @@ static void winbind_task_init(struct task_server *task)
}
/* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
- if (!directory_create_or_exist(lp_winbindd_socket_directory(task->lp_ctx), geteuid(), 0755)) {
+ if (!directory_create_or_exist(lpcfg_winbindd_socket_directory(task->lp_ctx), geteuid(), 0755)) {
task_server_terminate(task,
"Cannot create winbindd pipe directory", true);
return;
}
/* Make sure the directory for the Samba3 socket exists, and is of the correct permissions */
- if (!directory_create_or_exist(lp_winbindd_privileged_socket_directory(task->lp_ctx), geteuid(), 0750)) {
+ if (!directory_create_or_exist(lpcfg_winbindd_privileged_socket_directory(task->lp_ctx), geteuid(), 0750)) {
task_server_terminate(task,
"Cannot create winbindd privileged pipe directory", true);
return;
@@ -147,11 +230,56 @@ static void winbind_task_init(struct task_server *task)
if (!service) goto nomem;
service->task = task;
- status = wbsrv_setup_domains(service);
- if (!NT_STATUS_IS_OK(status)) {
- task_server_terminate(task, nt_errstr(status), true);
- return;
+
+ /* Find the primary SID, depending if we are a standalone
+ * server (what good is winbind in this case, but anyway...),
+ * or are in a domain as a member or a DC */
+ switch (lpcfg_server_role(service->task->lp_ctx)) {
+ case ROLE_STANDALONE:
+ primary_sid = secrets_get_domain_sid(service,
+ service->task->lp_ctx,
+ lpcfg_netbios_name(service->task->lp_ctx),
+ &service->sec_channel_type,
+ &errstring);
+ if (!primary_sid) {
+ char *message = talloc_asprintf(task,
+ "Cannot start Winbind (standalone configuration): %s: "
+ "Have you provisioned this server (%s) or changed it's name?",
+ errstring, lpcfg_netbios_name(service->task->lp_ctx));
+ task_server_terminate(task, message, true);
+ return;
+ }
+ break;
+ case ROLE_DOMAIN_MEMBER:
+ primary_sid = secrets_get_domain_sid(service,
+ service->task->lp_ctx,
+ lpcfg_workgroup(service->task->lp_ctx),
+ &service->sec_channel_type,
+ &errstring);
+ if (!primary_sid) {
+ char *message = talloc_asprintf(task, "Cannot start Winbind (domain member): %s: "
+ "Have you joined the %s domain?",
+ errstring, lpcfg_workgroup(service->task->lp_ctx));
+ task_server_terminate(task, message, true);
+ return;
+ }
+ break;
+ case ROLE_DOMAIN_CONTROLLER:
+ primary_sid = secrets_get_domain_sid(service,
+ service->task->lp_ctx,
+ lpcfg_workgroup(service->task->lp_ctx),
+ &service->sec_channel_type,
+ &errstring);
+ if (!primary_sid) {
+ char *message = talloc_asprintf(task, "Cannot start Winbind (domain controller): %s: "
+ "Have you provisioned the %s domain?",
+ errstring, lpcfg_workgroup(service->task->lp_ctx));
+ task_server_terminate(task, message, true);
+ return;
+ }
+ break;
}
+ service->primary_sid = primary_sid;
service->idmap_ctx = idmap_init(service, task->event_ctx, task->lp_ctx);
if (service->idmap_ctx == NULL) {
@@ -159,19 +287,22 @@ static void winbind_task_init(struct task_server *task)
return;
}
+ service->priv_pipe_dir = lpcfg_winbindd_privileged_socket_directory(task->lp_ctx);
+ service->pipe_dir = lpcfg_winbindd_socket_directory(task->lp_ctx);
+
/* setup the unprivileged samba3 socket */
listen_socket = talloc(service, struct wbsrv_listen_socket);
if (!listen_socket) goto nomem;
listen_socket->socket_path = talloc_asprintf(listen_socket, "%s/%s",
- lp_winbindd_socket_directory(task->lp_ctx),
- WINBINDD_SAMBA3_SOCKET);
+ service->pipe_dir,
+ WINBINDD_SOCKET_NAME);
if (!listen_socket->socket_path) goto nomem;
listen_socket->service = service;
listen_socket->privileged = false;
- status = stream_setup_socket(task->event_ctx, task->lp_ctx, model_ops,
+ status = stream_setup_socket(task, task->event_ctx, task->lp_ctx, model_ops,
&wbsrv_ops, "unix",
listen_socket->socket_path, &port,
- lp_socket_options(task->lp_ctx),
+ lpcfg_socket_options(task->lp_ctx),
listen_socket);
if (!NT_STATUS_IS_OK(status)) goto listen_failed;
@@ -179,18 +310,16 @@ static void winbind_task_init(struct task_server *task)
listen_socket = talloc(service, struct wbsrv_listen_socket);
if (!listen_socket) goto nomem;
listen_socket->socket_path
- = service->priv_socket_path
= talloc_asprintf(listen_socket, "%s/%s",
- lp_winbindd_privileged_socket_directory(task->lp_ctx),
- WINBINDD_SAMBA3_SOCKET);
- if (!listen_socket->socket_path) goto nomem;
+ service->priv_pipe_dir,
+ WINBINDD_SOCKET_NAME);
if (!listen_socket->socket_path) goto nomem;
listen_socket->service = service;
listen_socket->privileged = true;
- status = stream_setup_socket(task->event_ctx, task->lp_ctx, model_ops,
+ status = stream_setup_socket(task, task->event_ctx, task->lp_ctx, model_ops,
&wbsrv_ops, "unix",
listen_socket->socket_path, &port,
- lp_socket_options(task->lp_ctx),
+ lpcfg_socket_options(task->lp_ctx),
listen_socket);
if (!NT_STATUS_IS_OK(status)) goto listen_failed;
diff --git a/source4/winbind/wb_server.h b/source4/winbind/wb_server.h
index be79872e65..f20bc0aa51 100644
--- a/source4/winbind/wb_server.h
+++ b/source4/winbind/wb_server.h
@@ -24,19 +24,16 @@
#include "winbind/idmap.h"
#include "libnet/libnet.h"
-#define WINBINDD_SAMBA3_SOCKET "pipe"
-/* the privileged socket is in smbd_tmp_dir() */
-#define WINBINDD_SAMBA3_PRIVILEGED_SOCKET "winbind_pipe"
-
/* this struct stores global data for the winbind task */
struct wbsrv_service {
struct task_server *task;
const struct dom_sid *primary_sid;
+ enum netr_SchannelType sec_channel_type;
struct wbsrv_domain *domains;
struct idmap_context *idmap_ctx;
-
- const char *priv_socket_path;
+ const char *priv_pipe_dir;
+ const char *pipe_dir;
};
struct wbsrv_samconn {
@@ -51,9 +48,7 @@ struct wb_dom_info {
const char *name;
const char *dns_name;
const struct dom_sid *sid;
-
- int num_dcs;
- struct nbt_dc_name *dcs;
+ struct nbt_dc_name *dc;
};
struct wbsrv_domain {
@@ -100,12 +95,15 @@ struct wbsrv_connection {
/* how many calls are pending */
uint32_t pending_calls;
- struct packet_context *packet;
+ struct tstream_context *tstream;
+
+ struct tevent_queue *send_queue;
struct loadparm_context *lp_ctx;
};
#define WBSRV_SAMBA3_SET_STRING(dest, src) do { \
+ memset(dest, 0, sizeof(dest));\
safe_strcpy(dest, src, sizeof(dest)-1);\
} while(0)
@@ -122,6 +120,19 @@ struct wbsrv_pwent {
/* The libnet_ctx to use for the libnet_UserList call */
struct libnet_context *libnet_ctx;
};
+/*
+ state of a grent query
+*/
+struct wbsrv_grent {
+ /* Current UserList structure, contains 1+ user structs */
+ struct libnet_GroupList *group_list;
+
+ /* Index of the next user struct in the current UserList struct */
+ uint32_t page_index;
+
+ /* The libnet_ctx to use for the libnet_UserList call */
+ struct libnet_context *libnet_ctx;
+};
/*
state of one request
@@ -148,22 +159,24 @@ struct wbsrv_samba3_call {
/* the connection the call belongs to */
struct wbsrv_connection *wbconn;
- /* the backend should use this event context */
- struct tevent_context *event_ctx;
-
/* here the backend can store stuff like composite_context's ... */
void *private_data;
/* the request structure of the samba3 protocol */
- struct winbindd_request request;
+ struct winbindd_request *request;
/* the response structure of the samba3 protocol*/
- struct winbindd_response response;
+ struct winbindd_response *response;
+
+ DATA_BLOB in;
+ DATA_BLOB out;
+ struct iovec out_iov[1];
};
struct netr_LMSessionKey;
struct netr_UserSessionKey;
struct winbind_SamLogon;
+struct winbind_DsrUpdateReadOnlyServerDnsRecords;
#include "winbind/wb_async_helpers.h"
#include "winbind/wb_proto.h"
diff --git a/source4/winbind/wb_setup_domains.c b/source4/winbind/wb_setup_domains.c
deleted file mode 100644
index 92b91c182f..0000000000
--- a/source4/winbind/wb_setup_domains.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Copyright (C) Stefan Metzmacher 2008
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "winbind/wb_server.h"
-#include "smbd/service_task.h"
-#include "auth/credentials/credentials.h"
-#include "param/secrets.h"
-#include "param/param.h"
-
-NTSTATUS wbsrv_setup_domains(struct wbsrv_service *service)
-{
- const struct dom_sid *primary_sid;
-
- primary_sid = secrets_get_domain_sid(service,
- service->task->event_ctx,
- service->task->lp_ctx,
- lp_workgroup(service->task->lp_ctx));
- if (!primary_sid) {
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
-
- service->primary_sid = primary_sid;
-
- return NT_STATUS_OK;
-}
diff --git a/source4/winbind/wb_sid2domain.c b/source4/winbind/wb_sid2domain.c
index cb9fa3ada2..62854a2b6a 100644
--- a/source4/winbind/wb_sid2domain.c
+++ b/source4/winbind/wb_sid2domain.c
@@ -23,7 +23,6 @@
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
#include "smbd/service_task.h"
-#include "winbind/wb_async_helpers.h"
#include "libcli/security/security.h"
#include "../lib/util/dlinklist.h"
#include "param/param.h"
@@ -63,7 +62,7 @@ struct composite_context *wb_sid2domain_send(TALLOC_CTX *mem_ctx,
{
struct composite_context *result, *ctx;
struct sid2domain_state *state;
-
+ DEBUG(5, ("wb_sid2domain_send called\n"));
result = composite_create(mem_ctx, service->task->event_ctx);
if (result == NULL) goto failed;
@@ -85,7 +84,9 @@ struct composite_context *wb_sid2domain_send(TALLOC_CTX *mem_ctx,
if (dom_sid_equal(service->primary_sid, sid) ||
dom_sid_in_domain(service->primary_sid, sid)) {
- ctx = wb_get_dom_info_send(state, service, lp_workgroup(service->task->lp_ctx),
+ ctx = wb_get_dom_info_send(state, service,
+ lpcfg_workgroup(service->task->lp_ctx),
+ lpcfg_realm(service->task->lp_ctx),
service->primary_sid);
if (ctx == NULL) goto failed;
ctx->async.fn = sid2domain_recv_dom_info;
diff --git a/source4/winbind/wb_sid2gid.c b/source4/winbind/wb_sid2gid.c
index 282d10c9c9..b4026cd635 100644
--- a/source4/winbind/wb_sid2gid.c
+++ b/source4/winbind/wb_sid2gid.c
@@ -23,9 +23,7 @@
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
#include "smbd/service_task.h"
-#include "winbind/wb_helper.h"
#include "libcli/security/security.h"
-#include "winbind/idmap.h"
struct sid2gid_state {
struct composite_context *ctx;
@@ -40,7 +38,7 @@ struct composite_context *wb_sid2gid_send(TALLOC_CTX *mem_ctx,
{
struct composite_context *result, *ctx;
struct sid2gid_state *state;
- struct id_mapping *ids;
+ struct id_map *ids;
DEBUG(5, ("wb_sid2gid_send called\n"));
@@ -54,7 +52,7 @@ struct composite_context *wb_sid2gid_send(TALLOC_CTX *mem_ctx,
result->private_data = state;
state->service = service;
- ids = talloc(result, struct id_mapping);
+ ids = talloc(result, struct id_map);
if (composite_nomem(ids, result)) return result;
ids->sid = dom_sid_dup(result, sid);
@@ -72,19 +70,19 @@ static void sid2gid_recv_gid(struct composite_context *ctx)
struct sid2gid_state *state = talloc_get_type(ctx->async.private_data,
struct sid2gid_state);
- struct id_mapping *ids = NULL;
+ struct id_map *ids = NULL;
state->ctx->status = wb_sids2xids_recv(ctx, &ids);
if (!composite_is_ok(state->ctx)) return;
- if (!NT_STATUS_IS_OK(ids->status)) {
- composite_error(state->ctx, ids->status);
+ if (ids->status != ID_MAPPED) {
+ composite_error(state->ctx, NT_STATUS_UNSUCCESSFUL);
return;
}
- if (ids->unixid->type == ID_TYPE_BOTH ||
- ids->unixid->type == ID_TYPE_GID) {
- state->gid = ids->unixid->id;
+ if (ids->xid.type == ID_TYPE_BOTH ||
+ ids->xid.type == ID_TYPE_GID) {
+ state->gid = ids->xid.id;
composite_done(state->ctx);
} else {
composite_error(state->ctx, NT_STATUS_INVALID_SID);
diff --git a/source4/winbind/wb_sid2uid.c b/source4/winbind/wb_sid2uid.c
index 151f39906b..1fff66f655 100644
--- a/source4/winbind/wb_sid2uid.c
+++ b/source4/winbind/wb_sid2uid.c
@@ -23,9 +23,7 @@
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
#include "smbd/service_task.h"
-#include "winbind/wb_helper.h"
#include "libcli/security/security.h"
-#include "winbind/idmap.h"
struct sid2uid_state {
struct composite_context *ctx;
@@ -40,7 +38,7 @@ struct composite_context *wb_sid2uid_send(TALLOC_CTX *mem_ctx,
{
struct composite_context *result, *ctx;
struct sid2uid_state *state;
- struct id_mapping *ids;
+ struct id_map *ids;
DEBUG(5, ("wb_sid2uid_send called\n"));
@@ -54,7 +52,7 @@ struct composite_context *wb_sid2uid_send(TALLOC_CTX *mem_ctx,
result->private_data = state;
state->service = service;
- ids = talloc(result, struct id_mapping);
+ ids = talloc(result, struct id_map);
if (composite_nomem(ids, result)) return result;
ids->sid = dom_sid_dup(result, sid);
@@ -72,19 +70,19 @@ static void sid2uid_recv_uid(struct composite_context *ctx)
struct sid2uid_state *state = talloc_get_type(ctx->async.private_data,
struct sid2uid_state);
- struct id_mapping *ids = NULL;
+ struct id_map *ids = NULL;
state->ctx->status = wb_sids2xids_recv(ctx, &ids);
if (!composite_is_ok(state->ctx)) return;
- if (!NT_STATUS_IS_OK(ids->status)) {
- composite_error(state->ctx, ids->status);
+ if (ids->status != ID_MAPPED) {
+ composite_error(state->ctx, NT_STATUS_UNSUCCESSFUL);
return;
}
- if (ids->unixid->type == ID_TYPE_BOTH ||
- ids->unixid->type == ID_TYPE_UID) {
- state->uid = ids->unixid->id;
+ if (ids->xid.type == ID_TYPE_BOTH ||
+ ids->xid.type == ID_TYPE_UID) {
+ state->uid = ids->xid.id;
composite_done(state->ctx);
} else {
composite_error(state->ctx, NT_STATUS_INVALID_SID);
diff --git a/source4/winbind/wb_sids2xids.c b/source4/winbind/wb_sids2xids.c
index 6b89caf465..c966c40dc0 100644
--- a/source4/winbind/wb_sids2xids.c
+++ b/source4/winbind/wb_sids2xids.c
@@ -23,23 +23,22 @@
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
#include "smbd/service_task.h"
-#include "winbind/wb_helper.h"
-#include "libcli/security/proto.h"
-#include "winbind/idmap.h"
struct sids2xids_state {
struct composite_context *ctx;
struct wbsrv_service *service;
- struct id_mapping *ids;
+ struct id_map *ids;
int count;
};
struct composite_context *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
struct wbsrv_service *service,
- int count, struct id_mapping *ids)
+ unsigned int count, struct id_map *ids)
{
struct composite_context *result;
struct sids2xids_state *state;
+ struct id_map **pointer_array;
+ unsigned int i;
DEBUG(5, ("wb_sids2xids_send called\n"));
@@ -55,8 +54,19 @@ struct composite_context *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
state->count = count;
state->ids = ids;
+ /* We need to convert between calling conventions here - the
+ * values are filled in by reference, so we just need to
+ * provide pointers to them */
+ pointer_array = talloc_array(state, struct id_map *, count+1);
+ if (composite_nomem(pointer_array, result)) return result;
+
+ for (i=0; i < count; i++) {
+ pointer_array[i] = &ids[i];
+ }
+ pointer_array[i] = NULL;
+
state->ctx->status = idmap_sids_to_xids(service->idmap_ctx, mem_ctx,
- count, state->ids);
+ pointer_array);
if (!composite_is_ok(state->ctx)) return result;
composite_done(state->ctx);
@@ -64,7 +74,7 @@ struct composite_context *wb_sids2xids_send(TALLOC_CTX *mem_ctx,
}
NTSTATUS wb_sids2xids_recv(struct composite_context *ctx,
- struct id_mapping **ids)
+ struct id_map **ids)
{
NTSTATUS status = composite_wait(ctx);
struct sids2xids_state *state = talloc_get_type(ctx->private_data,
@@ -72,6 +82,9 @@ NTSTATUS wb_sids2xids_recv(struct composite_context *ctx,
DEBUG(5, ("wb_sids2xids_recv called\n"));
+ /* We don't have to mess with pointer_array on the way out, as
+ * the results are filled into the pointers the caller
+ * supplied */
*ids = state->ids;
talloc_free(ctx);
diff --git a/source4/winbind/wb_uid2sid.c b/source4/winbind/wb_uid2sid.c
index fd43dd64b9..61b7704167 100644
--- a/source4/winbind/wb_uid2sid.c
+++ b/source4/winbind/wb_uid2sid.c
@@ -23,9 +23,6 @@
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
#include "smbd/service_task.h"
-#include "winbind/wb_helper.h"
-#include "libcli/security/proto.h"
-#include "winbind/idmap.h"
struct uid2sid_state {
struct composite_context *ctx;
@@ -40,8 +37,7 @@ struct composite_context *wb_uid2sid_send(TALLOC_CTX *mem_ctx,
{
struct composite_context *result, *ctx;
struct uid2sid_state *state;
- struct unixid *unixid;
- struct id_mapping *ids;
+ struct id_map *ids;
DEBUG(5, ("wb_uid2sid_send called\n"));
@@ -55,15 +51,11 @@ struct composite_context *wb_uid2sid_send(TALLOC_CTX *mem_ctx,
result->private_data = state;
state->service = service;
- unixid = talloc(result, struct unixid);
- if (composite_nomem(unixid, result)) return result;
- unixid->id = uid;
- unixid->type = ID_TYPE_UID;
-
- ids = talloc(result, struct id_mapping);
+ ids = talloc(result, struct id_map);
if (composite_nomem(ids, result)) return result;
- ids->unixid = unixid;
ids->sid = NULL;
+ ids->xid.id = uid;
+ ids->xid.type = ID_TYPE_UID;
ctx = wb_xids2sids_send(result, service, 1, ids);
if (composite_nomem(ctx, result)) return result;
@@ -76,13 +68,13 @@ static void uid2sid_recv_sid(struct composite_context *ctx)
{
struct uid2sid_state *state = talloc_get_type(ctx->async.private_data,
struct uid2sid_state);
- struct id_mapping *ids = NULL;
+ struct id_map *ids = NULL;
state->ctx->status = wb_xids2sids_recv(ctx, &ids);
if (!composite_is_ok(state->ctx)) return;
- if (!NT_STATUS_IS_OK(ids->status)) {
- composite_error(state->ctx, ids->status);
+ if (ids->status != ID_MAPPED) {
+ composite_error(state->ctx, NT_STATUS_UNSUCCESSFUL);
return;
}
diff --git a/source4/winbind/wb_update_rodc_dns.c b/source4/winbind/wb_update_rodc_dns.c
new file mode 100644
index 0000000000..5ad2d0cbb0
--- /dev/null
+++ b/source4/winbind/wb_update_rodc_dns.c
@@ -0,0 +1,167 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Do a netr_DsrUpdateReadOnlyServerDnsRecords to a remote DC
+
+ Copyright (C) Andrew Bartlett 2010
+ Copyright (C) Andrew Tridgell 2010
+
+ based heavily on wb_sam_logon.c which is copyright:
+
+ Copyright (C) Volker Lendecke 2005
+ Copyright (C) Andrew Bartlett 2005
+ Copyright (C) Stefan Metzmacher 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "winbind/wb_server.h"
+#include "smbd/service_task.h"
+#include "auth/credentials/credentials.h"
+#include "libcli/auth/libcli_auth.h"
+#include "librpc/gen_ndr/ndr_netlogon_c.h"
+#include "librpc/gen_ndr/winbind.h"
+
+struct wb_update_rodc_dns_state {
+ struct composite_context *ctx;
+
+ struct winbind_DsrUpdateReadOnlyServerDnsRecords *req;
+
+ struct netlogon_creds_CredentialState *creds_state;
+ struct netr_Authenticator auth1, auth2;
+
+ TALLOC_CTX *r_mem_ctx;
+ struct netr_DsrUpdateReadOnlyServerDnsRecords r;
+};
+
+static void wb_update_rodc_dns_recv_domain(struct composite_context *ctx);
+static void wb_update_rodc_dns_recv_response(struct tevent_req *subreq);
+
+/*
+ Find the connection to the DC (or find an existing connection)
+*/
+struct composite_context *wb_update_rodc_dns_send(TALLOC_CTX *mem_ctx,
+ struct wbsrv_service *service,
+ struct winbind_DsrUpdateReadOnlyServerDnsRecords *req)
+{
+ struct composite_context *c, *creq;
+ struct wb_update_rodc_dns_state *s;
+
+ c = composite_create(mem_ctx, service->task->event_ctx);
+ if (!c) return NULL;
+
+ s = talloc_zero(c, struct wb_update_rodc_dns_state);
+ if (composite_nomem(s, c)) return c;
+ s->ctx = c;
+ s->req = req;
+
+ c->private_data = s;
+
+ creq = wb_sid2domain_send(s, service, service->primary_sid);
+ composite_continue(c, creq, wb_update_rodc_dns_recv_domain, s);
+ return c;
+}
+
+/*
+ Having finished making the connection to the DC
+ Send of a DsrUpdateReadOnlyServerDnsRecords request to authenticate a user.
+*/
+static void wb_update_rodc_dns_recv_domain(struct composite_context *creq)
+{
+ struct wb_update_rodc_dns_state *s = talloc_get_type(creq->async.private_data,
+ struct wb_update_rodc_dns_state);
+ struct wbsrv_domain *domain;
+ struct tevent_req *subreq;
+
+ s->ctx->status = wb_sid2domain_recv(creq, &domain);
+ if (!composite_is_ok(s->ctx)) return;
+
+ s->creds_state = cli_credentials_get_netlogon_creds(domain->libnet_ctx->cred);
+ netlogon_creds_client_authenticator(s->creds_state, &s->auth1);
+
+ s->r.in.server_name = talloc_asprintf(s, "\\\\%s",
+ dcerpc_server_name(domain->netlogon_pipe));
+ if (composite_nomem(s->r.in.server_name, s->ctx)) return;
+
+ s->r.in.computer_name = cli_credentials_get_workstation(domain->libnet_ctx->cred);
+ s->r.in.credential = &s->auth1;
+ s->r.out.return_authenticator = &s->auth2;
+ s->r.in.site_name = s->req->in.site_name;
+ s->r.in.dns_ttl = s->req->in.dns_ttl;
+ s->r.in.dns_names = s->req->in.dns_names;
+ s->r.out.dns_names = s->req->in.dns_names;
+
+ /*
+ * use a new talloc context for the DsrUpdateReadOnlyServerDnsRecords call
+ * because then we can just to a talloc_steal on this context
+ * in the final _recv() function to give the caller all the content of
+ * the s->r.out.dns_names
+ */
+ s->r_mem_ctx = talloc_new(s);
+ if (composite_nomem(s->r_mem_ctx, s->ctx)) return;
+
+ subreq = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_r_send(s,
+ s->ctx->event_ctx,
+ domain->netlogon_pipe->binding_handle,
+ &s->r);
+ if (composite_nomem(subreq, s->ctx)) return;
+ tevent_req_set_callback(subreq, wb_update_rodc_dns_recv_response, s);
+}
+
+/*
+ NTLM Authentication
+
+ Check the DsrUpdateReadOnlyServerDnsRecords reply and decrypt the session keys
+*/
+static void wb_update_rodc_dns_recv_response(struct tevent_req *subreq)
+{
+ struct wb_update_rodc_dns_state *s = tevent_req_callback_data(subreq,
+ struct wb_update_rodc_dns_state);
+
+ s->ctx->status = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_r_recv(subreq, s->r_mem_ctx);
+ TALLOC_FREE(subreq);
+ if (!composite_is_ok(s->ctx)) return;
+
+ s->ctx->status = s->r.out.result;
+ if (!composite_is_ok(s->ctx)) return;
+
+ if ((s->r.out.return_authenticator == NULL) ||
+ (!netlogon_creds_client_check(s->creds_state,
+ &s->r.out.return_authenticator->cred))) {
+ DEBUG(0, ("Credentials check failed!\n"));
+ composite_error(s->ctx, NT_STATUS_ACCESS_DENIED);
+ return;
+ }
+
+ composite_done(s->ctx);
+}
+
+NTSTATUS wb_update_rodc_dns_recv(struct composite_context *c,
+ TALLOC_CTX *mem_ctx,
+ struct winbind_DsrUpdateReadOnlyServerDnsRecords *req)
+{
+ struct wb_update_rodc_dns_state *s = talloc_get_type(c->private_data,
+ struct wb_update_rodc_dns_state);
+ NTSTATUS status = composite_wait(c);
+
+ if (NT_STATUS_IS_OK(status)) {
+ talloc_steal(mem_ctx, s->r_mem_ctx);
+ req->out.dns_names = s->r.out.dns_names;
+ }
+
+ talloc_free(s);
+ return status;
+}
diff --git a/source4/winbind/wb_utils.c b/source4/winbind/wb_utils.c
index 43effc3028..ffc4aa1950 100644
--- a/source4/winbind/wb_utils.c
+++ b/source4/winbind/wb_utils.c
@@ -31,10 +31,10 @@ bool wb_samba3_split_username(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_c
const char *domuser,
char **domain, char **user)
{
- char *p = strchr(domuser, *lp_winbind_separator(lp_ctx));
+ char *p = strchr(domuser, *lpcfg_winbind_separator(lp_ctx));
if (p == NULL) {
- *domain = talloc_strdup(mem_ctx, lp_workgroup(lp_ctx));
+ *domain = talloc_strdup(mem_ctx, lpcfg_workgroup(lp_ctx));
} else {
*domain = talloc_strndup(mem_ctx, domuser,
PTR_DIFF(p, domuser));
diff --git a/source4/winbind/wb_xids2sids.c b/source4/winbind/wb_xids2sids.c
index a1cf2667ff..aeec2ee5be 100644
--- a/source4/winbind/wb_xids2sids.c
+++ b/source4/winbind/wb_xids2sids.c
@@ -23,23 +23,22 @@
#include "libcli/composite/composite.h"
#include "winbind/wb_server.h"
#include "smbd/service_task.h"
-#include "winbind/wb_helper.h"
-#include "libcli/security/proto.h"
-#include "winbind/idmap.h"
struct xids2sids_state {
struct composite_context *ctx;
struct wbsrv_service *service;
- struct id_mapping *ids;
+ struct id_map *ids;
int count;
};
struct composite_context *wb_xids2sids_send(TALLOC_CTX *mem_ctx,
struct wbsrv_service *service,
- int count, struct id_mapping *ids)
+ unsigned int count, struct id_map *ids)
{
struct composite_context *result;
struct xids2sids_state *state;
+ struct id_map **pointer_array;
+ unsigned int i;
DEBUG(5, ("wb_xids2sids_send called\n"));
@@ -55,8 +54,19 @@ struct composite_context *wb_xids2sids_send(TALLOC_CTX *mem_ctx,
state->count = count;
state->ids = ids;
+ /* We need to convert between calling conventions here - the
+ * values are filled in by reference, so we just need to
+ * provide pointers to them */
+ pointer_array = talloc_array(state, struct id_map *, count+1);
+ if (composite_nomem(pointer_array, result)) return result;
+
+ for (i=0; i < count; i++) {
+ pointer_array[i] = &ids[i];
+ }
+ pointer_array[i] = NULL;
+
state->ctx->status = idmap_xids_to_sids(service->idmap_ctx, mem_ctx,
- count, state->ids);
+ pointer_array);
if (!composite_is_ok(state->ctx)) return result;
composite_done(state->ctx);
@@ -64,7 +74,7 @@ struct composite_context *wb_xids2sids_send(TALLOC_CTX *mem_ctx,
}
NTSTATUS wb_xids2sids_recv(struct composite_context *ctx,
- struct id_mapping **ids)
+ struct id_map **ids)
{
NTSTATUS status = composite_wait(ctx);
struct xids2sids_state *state = talloc_get_type(ctx->private_data,
@@ -72,6 +82,9 @@ NTSTATUS wb_xids2sids_recv(struct composite_context *ctx,
DEBUG(5, ("wb_xids2sids_recv called.\n"));
+ /* We don't have to mess with pointer_array on the way out, as
+ * the results are filled into the pointers the caller
+ * supplied */
*ids = state->ids;
talloc_free(ctx);
diff --git a/source4/winbind/wscript_build b/source4/winbind/wscript_build
new file mode 100644
index 0000000000..09fee43809
--- /dev/null
+++ b/source4/winbind/wscript_build
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+
+
+bld.SAMBA_MODULE('service_winbind',
+ source='wb_server.c wb_irpc.c wb_samba3_protocol.c wb_samba3_cmd.c wb_init_domain.c wb_dom_info.c wb_dom_info_trusted.c wb_sid2domain.c wb_name2domain.c wb_sids2xids.c wb_xids2sids.c wb_gid2sid.c wb_sid2uid.c wb_sid2gid.c wb_uid2sid.c wb_connect_lsa.c wb_connect_sam.c wb_cmd_lookupname.c wb_cmd_lookupsid.c wb_cmd_getdcname.c wb_cmd_getgrnam.c wb_cmd_getgrgid.c wb_cmd_getpwnam.c wb_cmd_getpwuid.c wb_cmd_userdomgroups.c wb_cmd_usersids.c wb_cmd_list_groups.c wb_cmd_list_trustdom.c wb_cmd_list_users.c wb_cmd_setpwent.c wb_cmd_getpwent.c wb_cmd_getgrent.c wb_cmd_setgrent.c wb_cmd_getgroups.c wb_pam_auth.c wb_sam_logon.c wb_update_rodc_dns.c',
+ autoproto='wb_proto.h',
+ subsystem='service',
+ init_function='server_service_winbind_init',
+ deps='WB_HELPER IDMAP NDR_WINBIND process_model RPC_NDR_LSA dcerpc-samr PAM_ERRORS cli-ldap samba-net LIBSAMBA_TSOCKET',
+ internal_module=False,
+ )
+
+
+bld.SAMBA_SUBSYSTEM('WB_HELPER',
+ source='wb_async_helpers.c wb_utils.c',
+ autoproto='wb_helper.h',
+ public_deps='RPC_NDR_LSA dcerpc-samr'
+ )
+
+
+bld.SAMBA_SUBSYSTEM('IDMAP',
+ source='idmap.c',
+ autoproto='idmap_proto.h',
+ public_deps='samdb-common ldbsamba'
+ )
+
+bld.SAMBA_BINARY('wbinfo',
+ source='../../nsswitch/wbinfo.c',
+ deps='samba-util LIBCLI_AUTH popt POPT_SAMBA winbind-client wbclient tevent UTIL_TEVENT LIBASYNC_REQ security ndr NDR_SECURITY'
+ )