drs: Send DRSUAPI_DRS_GET_ALL_GROUP_MEMBERSHIP by default
[samba.git] / source3 / winbindd / wb_getpwsid.c
1 /*
2    Unix SMB/CIFS implementation.
3    async getpwsid
4    Copyright (C) Volker Lendecke 2009
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "winbindd.h"
22 #include "librpc/gen_ndr/ndr_winbind_c.h"
23 #include "../libcli/security/security.h"
24
25 struct wb_getpwsid_state {
26         struct tevent_context *ev;
27         struct dom_sid sid;
28         struct wbint_userinfo *userinfo;
29         struct winbindd_pw *pw;
30 };
31
32 static void wb_getpwsid_queryuser_done(struct tevent_req *subreq);
33 static void wb_getpwsid_lookupsid_done(struct tevent_req *subreq);
34 static void wb_getpwsid_done(struct tevent_req *subreq);
35
36 struct tevent_req *wb_getpwsid_send(TALLOC_CTX *mem_ctx,
37                                     struct tevent_context *ev,
38                                     const struct dom_sid *user_sid,
39                                     struct winbindd_pw *pw)
40 {
41         struct tevent_req *req, *subreq;
42         struct wb_getpwsid_state *state;
43
44         req = tevent_req_create(mem_ctx, &state, struct wb_getpwsid_state);
45         if (req == NULL) {
46                 return NULL;
47         }
48         sid_copy(&state->sid, user_sid);
49         state->ev = ev;
50         state->pw = pw;
51
52         subreq = wb_queryuser_send(state, ev, &state->sid);
53         if (tevent_req_nomem(subreq, req)) {
54                 return tevent_req_post(req, ev);
55         }
56         tevent_req_set_callback(subreq, wb_getpwsid_queryuser_done, req);
57         return req;
58 }
59
60 static void wb_getpwsid_queryuser_done(struct tevent_req *subreq)
61 {
62         struct tevent_req *req = tevent_req_callback_data(
63                 subreq, struct tevent_req);
64         struct wb_getpwsid_state *state = tevent_req_data(
65                 req, struct wb_getpwsid_state);
66         NTSTATUS status;
67
68         status = wb_queryuser_recv(subreq, state, &state->userinfo);
69         TALLOC_FREE(subreq);
70         if (NT_STATUS_IS_OK(status)
71             && (state->userinfo->acct_name != NULL)
72             && (state->userinfo->acct_name[0] != '\0'))
73         {
74                 /*
75                  * QueryUser got us a name, let's go directly to the
76                  * fill_pwent step
77                  */
78                 subreq = wb_fill_pwent_send(state, state->ev, state->userinfo,
79                                             state->pw);
80                 if (tevent_req_nomem(subreq, req)) {
81                         return;
82                 }
83                 tevent_req_set_callback(subreq, wb_getpwsid_done, req);
84                 return;
85         }
86
87         /*
88          * Either query_user did not succeed, or it
89          * succeeded but did not return an acct_name.
90          * (TODO: Can this happen at all???)
91          * ==> Try lsa_lookupsids.
92          */
93         if (state->userinfo == NULL) {
94                 state->userinfo = talloc_zero(state, struct wbint_userinfo);
95                 if (tevent_req_nomem(state->userinfo, req)) {
96                         return;
97                 }
98
99                 /* a successful query_user call would have filled these */
100                 sid_copy(&state->userinfo->user_sid, &state->sid);
101                 state->userinfo->homedir = NULL;
102                 state->userinfo->shell = NULL;
103                 state->userinfo->primary_gid = (gid_t)-1;
104         }
105
106         subreq = wb_lookupsid_send(state, state->ev, &state->sid);
107         if (tevent_req_nomem(subreq, req)) {
108                 return;
109         }
110         tevent_req_set_callback(subreq, wb_getpwsid_lookupsid_done, req);
111 }
112
113 static void wb_getpwsid_lookupsid_done(struct tevent_req *subreq)
114 {
115         struct tevent_req *req = tevent_req_callback_data(
116                 subreq, struct tevent_req);
117         struct wb_getpwsid_state *state = tevent_req_data(
118                 req, struct wb_getpwsid_state);
119         NTSTATUS status;
120         enum lsa_SidType type;
121         const char *domain;
122
123         status = wb_lookupsid_recv(subreq, state->userinfo, &type, &domain,
124                                    &state->userinfo->acct_name);
125         TALLOC_FREE(subreq);
126         if (tevent_req_nterror(req, status)) {
127                 return;
128         }
129
130         switch (type) {
131         case SID_NAME_USER:
132         case SID_NAME_COMPUTER:
133                 /*
134                  * user case: we only need the account name from lookup_sids
135                  */
136                 break;
137         case SID_NAME_DOM_GRP:
138         case SID_NAME_ALIAS:
139         case SID_NAME_WKN_GRP:
140                 /*
141                  * also treat group-type SIDs (they might map to ID_TYPE_BOTH)
142                  */
143                 sid_copy(&state->userinfo->group_sid, &state->sid);
144                 break;
145         default:
146                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
147                 return;
148         }
149
150         subreq = wb_fill_pwent_send(state, state->ev, state->userinfo,
151                                     state->pw);
152         if (tevent_req_nomem(subreq, req)) {
153                 return;
154         }
155         tevent_req_set_callback(subreq, wb_getpwsid_done, req);
156 }
157
158 static void wb_getpwsid_done(struct tevent_req *subreq)
159 {
160         struct tevent_req *req = tevent_req_callback_data(
161                 subreq, struct tevent_req);
162         NTSTATUS status;
163
164         status = wb_fill_pwent_recv(subreq);
165         if (tevent_req_nterror(req, status)) {
166                 return;
167         }
168         tevent_req_done(req);
169 }
170
171 NTSTATUS wb_getpwsid_recv(struct tevent_req *req)
172 {
173         return tevent_req_simple_recv_ntstatus(req);
174 }