Revert "winbind: Remove "lookup_usergroups" winbind method"
[samba.git] / source3 / winbindd / winbindd_reconnect.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Wrapper around winbindd_rpc.c to centralize retry logic.
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 "winbindd.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_WINBIND
27
28 extern struct winbindd_methods msrpc_methods;
29
30 bool reconnect_need_retry(NTSTATUS status, struct winbindd_domain *domain)
31 {
32         if (NT_STATUS_IS_OK(status)) {
33                 return false;
34         }
35
36         if (!NT_STATUS_IS_ERR(status)) {
37                 return false;
38         }
39
40         if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
41                 return false;
42         }
43
44         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
45                 return false;
46         }
47
48         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_GROUP)) {
49                 return false;
50         }
51
52         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_ALIAS)) {
53                 return false;
54         }
55
56         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_MEMBER)) {
57                 return false;
58         }
59
60         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN)) {
61                 return false;
62         }
63
64         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_PRIVILEGE)) {
65                 return false;
66         }
67
68         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
69                 return false;
70         }
71
72         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR)) {
73                 /*
74                  * RPC call sent on expired session, needs
75                  * reauthentication.
76                  */
77                 invalidate_cm_connection(domain);
78         }
79
80         return true;
81 }
82
83 /* List all users */
84 static NTSTATUS query_user_list(struct winbindd_domain *domain,
85                                 TALLOC_CTX *mem_ctx,
86                                 uint32_t **rids)
87 {
88         NTSTATUS result;
89
90         result = msrpc_methods.query_user_list(domain, mem_ctx, rids);
91
92         if (reconnect_need_retry(result, domain))
93                 result = msrpc_methods.query_user_list(domain, mem_ctx, rids);
94
95         return result;
96 }
97
98 /* list all domain groups */
99 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
100                                 TALLOC_CTX *mem_ctx,
101                                 uint32_t *num_entries,
102                                 struct wb_acct_info **info)
103 {
104         NTSTATUS result;
105
106         result = msrpc_methods.enum_dom_groups(domain, mem_ctx,
107                                                num_entries, info);
108
109         if (reconnect_need_retry(result, domain))
110                 result = msrpc_methods.enum_dom_groups(domain, mem_ctx,
111                                                        num_entries, info);
112         return result;
113 }
114
115 /* List all domain groups */
116
117 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
118                                   TALLOC_CTX *mem_ctx,
119                                   uint32_t *num_entries,
120                                   struct wb_acct_info **info)
121 {
122         NTSTATUS result;
123
124         result = msrpc_methods.enum_local_groups(domain, mem_ctx,
125                                                  num_entries, info);
126
127         if (reconnect_need_retry(result, domain))
128                 result = msrpc_methods.enum_local_groups(domain, mem_ctx,
129                                                          num_entries, info);
130
131         return result;
132 }
133
134 /* convert a single name to a sid in a domain */
135 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
136                             TALLOC_CTX *mem_ctx,
137                             const char *domain_name,
138                             const char *name,
139                             uint32_t flags,
140                             struct dom_sid *sid,
141                             enum lsa_SidType *type)
142 {
143         NTSTATUS result;
144
145         result = msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
146                                            flags, sid, type);
147
148         if (reconnect_need_retry(result, domain))
149                 result = msrpc_methods.name_to_sid(domain, mem_ctx,
150                                                    domain_name, name, flags,
151                                                    sid, type);
152
153         return result;
154 }
155
156 /*
157   convert a domain SID to a user or group name
158 */
159 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
160                             TALLOC_CTX *mem_ctx,
161                             const struct dom_sid *sid,
162                             char **domain_name,
163                             char **name,
164                             enum lsa_SidType *type)
165 {
166         NTSTATUS result;
167
168         result = msrpc_methods.sid_to_name(domain, mem_ctx, sid,
169                                            domain_name, name, type);
170
171         if (reconnect_need_retry(result, domain))
172                 result = msrpc_methods.sid_to_name(domain, mem_ctx, sid,
173                                                    domain_name, name, type);
174
175         return result;
176 }
177
178 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
179                               TALLOC_CTX *mem_ctx,
180                               const struct dom_sid *sid,
181                               uint32_t *rids,
182                               size_t num_rids,
183                               char **domain_name,
184                               char ***names,
185                               enum lsa_SidType **types)
186 {
187         NTSTATUS result;
188
189         result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
190                                              rids, num_rids,
191                                              domain_name, names, types);
192         if (reconnect_need_retry(result, domain)) {
193                 result = msrpc_methods.rids_to_names(domain, mem_ctx, sid,
194                                                      rids, num_rids,
195                                                      domain_name, names,
196                                                      types);
197         }
198
199         return result;
200 }
201
202 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
203 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
204                                   TALLOC_CTX *mem_ctx,
205                                   const struct dom_sid *user_sid,
206                                   uint32_t *num_groups, struct dom_sid **user_gids)
207 {
208         NTSTATUS result;
209
210         result = msrpc_methods.lookup_usergroups(domain, mem_ctx,
211                                                  user_sid, num_groups,
212                                                  user_gids);
213
214         if (reconnect_need_retry(result, domain))
215                 result = msrpc_methods.lookup_usergroups(domain, mem_ctx,
216                                                          user_sid, num_groups,
217                                                          user_gids);
218
219         return result;
220 }
221
222 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
223                                    TALLOC_CTX *mem_ctx,
224                                    uint32_t num_sids, const struct dom_sid *sids,
225                                    uint32_t *num_aliases, uint32_t **alias_rids)
226 {
227         NTSTATUS result;
228
229         result = msrpc_methods.lookup_useraliases(domain, mem_ctx,
230                                                   num_sids, sids,
231                                                   num_aliases,
232                                                   alias_rids);
233
234         if (reconnect_need_retry(result, domain))
235                 result = msrpc_methods.lookup_useraliases(domain, mem_ctx,
236                                                           num_sids, sids,
237                                                           num_aliases,
238                                                           alias_rids);
239
240         return result;
241 }
242
243 /* Lookup group membership given a rid.   */
244 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
245                                 TALLOC_CTX *mem_ctx,
246                                 const struct dom_sid *group_sid,
247                                 enum lsa_SidType type,
248                                 uint32_t *num_names,
249                                 struct dom_sid **sid_mem, char ***names,
250                                 uint32_t **name_types)
251 {
252         NTSTATUS result;
253
254         result = msrpc_methods.lookup_groupmem(domain, mem_ctx,
255                                                group_sid, type, num_names,
256                                                sid_mem, names,
257                                                name_types);
258
259         if (reconnect_need_retry(result, domain))
260                 result = msrpc_methods.lookup_groupmem(domain, mem_ctx,
261                                                        group_sid, type,
262                                                        num_names,
263                                                        sid_mem, names,
264                                                        name_types);
265
266         return result;
267 }
268
269 /* find the sequence number for a domain */
270 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32_t *seq)
271 {
272         NTSTATUS result;
273
274         result = msrpc_methods.sequence_number(domain, seq);
275
276         if (reconnect_need_retry(result, domain))
277                 result = msrpc_methods.sequence_number(domain, seq);
278
279         return result;
280 }
281
282 /* find the lockout policy of a domain */
283 static NTSTATUS lockout_policy(struct winbindd_domain *domain, 
284                                TALLOC_CTX *mem_ctx,
285                                struct samr_DomInfo12 *policy)
286 {
287         NTSTATUS result;
288
289         result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
290
291         if (reconnect_need_retry(result, domain))
292                 result = msrpc_methods.lockout_policy(domain, mem_ctx, policy);
293
294         return result;
295 }
296
297 /* find the password policy of a domain */
298 static NTSTATUS password_policy(struct winbindd_domain *domain, 
299                                 TALLOC_CTX *mem_ctx,
300                                 struct samr_DomInfo1 *policy)
301 {
302         NTSTATUS result;
303  
304         result = msrpc_methods.password_policy(domain, mem_ctx, policy);
305
306         if (reconnect_need_retry(result, domain))
307                 result = msrpc_methods.password_policy(domain, mem_ctx, policy);
308         
309         return result;
310 }
311
312 /* get a list of trusted domains */
313 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
314                                 TALLOC_CTX *mem_ctx,
315                                 struct netr_DomainTrustList *trusts)
316 {
317         NTSTATUS result;
318
319         result = msrpc_methods.trusted_domains(domain, mem_ctx, trusts);
320
321         if (reconnect_need_retry(result, domain))
322                 result = msrpc_methods.trusted_domains(domain, mem_ctx,
323                                                        trusts);
324
325         return result;
326 }
327
328 /* the rpc backend methods are exposed via this structure */
329 struct winbindd_methods reconnect_methods = {
330         False,
331         query_user_list,
332         enum_dom_groups,
333         enum_local_groups,
334         name_to_sid,
335         sid_to_name,
336         rids_to_names,
337         lookup_usergroups,
338         lookup_useraliases,
339         lookup_groupmem,
340         sequence_number,
341         lockout_policy,
342         password_policy,
343         trusted_domains,
344 };