1/* 2 Unix SMB/CIFS implementation. 3 4 Command backend for wbinfo --user-sids 5 6 Copyright (C) Volker Lendecke 2005 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "libcli/composite/composite.h" 24#include "winbind/wb_server.h" 25#include "smbd/service_task.h" 26#include "librpc/gen_ndr/ndr_samr_c.h" 27#include "libcli/security/security.h" 28 29/* Calculate the token in two steps: Go the user's originating domain, ask for 30 * the user's domain groups. Then with the resulting list of sids go to our 31 * own domain to expand the aliases aka domain local groups. */ 32 33struct cmd_usersids_state { 34 struct composite_context *ctx; 35 struct wbsrv_service *service; 36 struct dom_sid *user_sid; 37 int num_domgroups; 38 struct dom_sid **domgroups; 39 40 struct lsa_SidArray lsa_sids; 41 struct samr_Ids rids; 42 struct samr_GetAliasMembership r; 43 44 int num_sids; 45 struct dom_sid **sids; 46}; 47 48static void usersids_recv_domgroups(struct composite_context *ctx); 49static void usersids_recv_domain(struct composite_context *ctx); 50static void usersids_recv_aliases(struct rpc_request *req); 51 52struct composite_context *wb_cmd_usersids_send(TALLOC_CTX *mem_ctx, 53 struct wbsrv_service *service, 54 const struct dom_sid *sid) 55{ 56 struct composite_context *result, *ctx; 57 struct cmd_usersids_state *state; 58 59 60 result = composite_create(mem_ctx, service->task->event_ctx); 61 if (result == NULL) goto failed; 62 63 state = talloc(result, struct cmd_usersids_state); 64 if (state == NULL) goto failed; 65 state->ctx = result; 66 result->private_data = state; 67 68 state->service = service; 69 state->user_sid = dom_sid_dup(state, sid); 70 if (state->user_sid == NULL) goto failed; 71 72 ctx = wb_cmd_userdomgroups_send(state, service, sid); 73 if (ctx == NULL) goto failed; 74 75 ctx->async.fn = usersids_recv_domgroups; 76 ctx->async.private_data = state; 77 return result; 78 79 failed: 80 talloc_free(result); 81 return NULL; 82} 83 84static void usersids_recv_domgroups(struct composite_context *ctx) 85{ 86 struct cmd_usersids_state *state = 87 talloc_get_type(ctx->async.private_data, 88 struct cmd_usersids_state); 89 90 state->ctx->status = wb_cmd_userdomgroups_recv(ctx, state, 91 &state->num_domgroups, 92 &state->domgroups); 93 if (!composite_is_ok(state->ctx)) return; 94 95 ctx = wb_sid2domain_send(state, state->service, 96 state->service->primary_sid); 97 composite_continue(state->ctx, ctx, usersids_recv_domain, state); 98} 99 100static void usersids_recv_domain(struct composite_context *ctx) 101{ 102 struct cmd_usersids_state *state = 103 talloc_get_type(ctx->async.private_data, 104 struct cmd_usersids_state); 105 struct rpc_request *req; 106 struct wbsrv_domain *domain; 107 int i; 108 109 state->ctx->status = wb_sid2domain_recv(ctx, &domain); 110 if (!composite_is_ok(state->ctx)) return; 111 112 state->lsa_sids.num_sids = state->num_domgroups+1; 113 state->lsa_sids.sids = talloc_array(state, struct lsa_SidPtr, 114 state->lsa_sids.num_sids); 115 if (composite_nomem(state->lsa_sids.sids, state->ctx)) return; 116 117 state->lsa_sids.sids[0].sid = state->user_sid; 118 for (i=0; i<state->num_domgroups; i++) { 119 state->lsa_sids.sids[i+1].sid = state->domgroups[i]; 120 } 121 122 state->rids.count = 0; 123 state->rids.ids = NULL; 124 125 state->r.in.domain_handle = &domain->libnet_ctx->samr.handle; 126 state->r.in.sids = &state->lsa_sids; 127 state->r.out.rids = &state->rids; 128 129 req = dcerpc_samr_GetAliasMembership_send(domain->libnet_ctx->samr.pipe, state, 130 &state->r); 131 composite_continue_rpc(state->ctx, req, usersids_recv_aliases, state); 132} 133 134static void usersids_recv_aliases(struct rpc_request *req) 135{ 136 struct cmd_usersids_state *state = 137 talloc_get_type(req->async.private_data, 138 struct cmd_usersids_state); 139 int i; 140 141 state->ctx->status = dcerpc_ndr_request_recv(req); 142 if (!composite_is_ok(state->ctx)) return; 143 state->ctx->status = state->r.out.result; 144 if (!composite_is_ok(state->ctx)) return; 145 146 state->num_sids = 1 + state->num_domgroups + state->r.out.rids->count; 147 state->sids = talloc_array(state, struct dom_sid *, state->num_sids); 148 if (composite_nomem(state->sids, state->ctx)) return; 149 150 state->sids[0] = talloc_steal(state->sids, state->user_sid); 151 152 for (i=0; i<state->num_domgroups; i++) { 153 state->sids[1+i] = 154 talloc_steal(state->sids, state->domgroups[i]); 155 } 156 157 for (i=0; i<state->r.out.rids->count; i++) { 158 state->sids[1+state->num_domgroups+i] = dom_sid_add_rid( 159 state->sids, state->service->primary_sid, 160 state->r.out.rids->ids[i]); 161 162 if (composite_nomem(state->sids[1+state->num_domgroups+i], 163 state->ctx)) return; 164 } 165 166 composite_done(state->ctx); 167} 168 169NTSTATUS wb_cmd_usersids_recv(struct composite_context *ctx, 170 TALLOC_CTX *mem_ctx, 171 int *num_sids, struct dom_sid ***sids) 172{ 173 NTSTATUS status = composite_wait(ctx); 174 if (NT_STATUS_IS_OK(status)) { 175 struct cmd_usersids_state *state = 176 talloc_get_type(ctx->private_data, 177 struct cmd_usersids_state); 178 *num_sids = state->num_sids; 179 *sids = talloc_steal(mem_ctx, state->sids); 180 } 181 talloc_free(ctx); 182 return status; 183} 184 185NTSTATUS wb_cmd_usersids(TALLOC_CTX *mem_ctx, struct wbsrv_service *service, 186 const struct dom_sid *sid, 187 int *num_sids, struct dom_sid ***sids) 188{ 189 struct composite_context *c = 190 wb_cmd_usersids_send(mem_ctx, service, sid); 191 return wb_cmd_usersids_recv(c, mem_ctx, num_sids, sids); 192} 193 194