diff options
Diffstat (limited to 'source4/winbind')
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' + ) |