winbindd: Add retry also for ADS method calls
[obnox/samba/samba-obnox.git] / source3 / winbindd / winbindd_reconnect_ads.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Wrapper around winbindd_ads.c to centralize retry logic.
5    Copyright (C) Christof Schmitt 2016
6
7    Based on winbindd_reconnect.c
8    Copyright (C) Volker Lendecke 2005
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "winbindd.h"
26
27 #ifdef HAVE_ADS
28
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_WINBIND
31
32 extern struct winbindd_methods ads_methods;
33
34 /* List all users */
35 static NTSTATUS query_user_list(struct winbindd_domain *domain,
36                                 TALLOC_CTX *mem_ctx,
37                                 uint32_t *num_entries,
38                                 struct wbint_userinfo **info)
39 {
40         NTSTATUS result;
41
42         result = ads_methods.query_user_list(domain, mem_ctx,
43                                              num_entries, info);
44
45         if (reconnect_need_retry(result, domain)) {
46                 result = ads_methods.query_user_list(domain, mem_ctx,
47                                                      num_entries, info);
48         }
49
50         return result;
51 }
52
53 /* list all domain groups */
54 static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
55                                 TALLOC_CTX *mem_ctx,
56                                 uint32_t *num_entries,
57                                 struct wb_acct_info **info)
58 {
59         NTSTATUS result;
60
61         result = ads_methods.enum_dom_groups(domain, mem_ctx,
62                                              num_entries, info);
63
64         if (reconnect_need_retry(result, domain)) {
65                 result = ads_methods.enum_dom_groups(domain, mem_ctx,
66                                                      num_entries, info);
67         }
68
69         return result;
70 }
71
72 /* List all domain groups */
73 static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
74                                   TALLOC_CTX *mem_ctx,
75                                   uint32_t *num_entries,
76                                   struct wb_acct_info **info)
77 {
78         NTSTATUS result;
79
80         result = ads_methods.enum_local_groups(domain, mem_ctx,
81                                                num_entries, info);
82
83         if (reconnect_need_retry(result, domain)) {
84                 result = ads_methods.enum_local_groups(domain, mem_ctx,
85                                                        num_entries, info);
86         }
87
88         return result;
89 }
90
91 /* convert a single name to a sid in a domain */
92 static NTSTATUS name_to_sid(struct winbindd_domain *domain,
93                             TALLOC_CTX *mem_ctx,
94                             const char *domain_name,
95                             const char *name,
96                             uint32_t flags,
97                             struct dom_sid *sid,
98                             enum lsa_SidType *type)
99 {
100         NTSTATUS result;
101
102         result = ads_methods.name_to_sid(domain, mem_ctx, domain_name, name,
103                                          flags, sid, type);
104
105         if (reconnect_need_retry(result, domain)) {
106                 result = ads_methods.name_to_sid(domain, mem_ctx,
107                                                  domain_name, name, flags,
108                                                  sid, type);
109         }
110
111         return result;
112 }
113
114 /*
115   convert a domain SID to a user or group name
116 */
117 static NTSTATUS sid_to_name(struct winbindd_domain *domain,
118                             TALLOC_CTX *mem_ctx,
119                             const struct dom_sid *sid,
120                             char **domain_name,
121                             char **name,
122                             enum lsa_SidType *type)
123 {
124         NTSTATUS result;
125
126         result = ads_methods.sid_to_name(domain, mem_ctx, sid,
127                                          domain_name, name, type);
128
129         if (reconnect_need_retry(result, domain))
130                 result = ads_methods.sid_to_name(domain, mem_ctx, sid,
131                                                  domain_name, name, type);
132
133         return result;
134 }
135
136 static NTSTATUS rids_to_names(struct winbindd_domain *domain,
137                               TALLOC_CTX *mem_ctx,
138                               const struct dom_sid *sid,
139                               uint32_t *rids,
140                               size_t num_rids,
141                               char **domain_name,
142                               char ***names,
143                               enum lsa_SidType **types)
144 {
145         NTSTATUS result;
146
147         result = ads_methods.rids_to_names(domain, mem_ctx, sid,
148                                            rids, num_rids,
149                                            domain_name, names, types);
150         if (reconnect_need_retry(result, domain)) {
151                 result = ads_methods.rids_to_names(domain, mem_ctx, sid,
152                                                    rids, num_rids, domain_name,
153                                                    names, types);
154         }
155
156         return result;
157 }
158
159 /* Lookup user information from a rid or username. */
160 static NTSTATUS query_user(struct winbindd_domain *domain,
161                            TALLOC_CTX *mem_ctx,
162                            const struct dom_sid *user_sid,
163                            struct wbint_userinfo *user_info)
164 {
165         NTSTATUS result;
166
167         result = ads_methods.query_user(domain, mem_ctx, user_sid, user_info);
168
169         if (reconnect_need_retry(result, domain)) {
170                 result = ads_methods.query_user(domain, mem_ctx, user_sid,
171                                                 user_info);
172         }
173
174         return result;
175 }
176
177 /* Lookup groups a user is a member of.  I wish Unix had a call like this! */
178 static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
179                                   TALLOC_CTX *mem_ctx,
180                                   const struct dom_sid *user_sid,
181                                   uint32_t *num_groups,
182                                   struct dom_sid **user_gids)
183 {
184         NTSTATUS result;
185
186         result = ads_methods.lookup_usergroups(domain, mem_ctx, user_sid,
187                                                num_groups, user_gids);
188
189         if (reconnect_need_retry(result, domain)) {
190                 result = ads_methods.lookup_usergroups(domain, mem_ctx,
191                                                        user_sid, num_groups,
192                                                        user_gids);
193         }
194
195         return result;
196 }
197
198 static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
199                                    TALLOC_CTX *mem_ctx,
200                                    uint32_t num_sids,
201                                    const struct dom_sid *sids,
202                                    uint32_t *num_aliases, uint32_t **alias_rids)
203 {
204         NTSTATUS result;
205
206         result = ads_methods.lookup_useraliases(domain, mem_ctx, num_sids, sids,
207                                                 num_aliases, alias_rids);
208
209         if (reconnect_need_retry(result, domain)) {
210                 result = ads_methods.lookup_useraliases(domain, mem_ctx,
211                                                         num_sids, sids,
212                                                         num_aliases,
213                                                         alias_rids);
214         }
215
216         return result;
217 }
218
219 /* Lookup group membership given a rid.   */
220 static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
221                                 TALLOC_CTX *mem_ctx,
222                                 const struct dom_sid *group_sid,
223                                 enum lsa_SidType type,
224                                 uint32_t *num_names,
225                                 struct dom_sid **sid_mem, char ***names,
226                                 uint32_t **name_types)
227 {
228         NTSTATUS result;
229
230         result = ads_methods.lookup_groupmem(domain, mem_ctx, group_sid, type,
231                                              num_names, sid_mem, names,
232                                              name_types);
233
234         if (reconnect_need_retry(result, domain)) {
235                 result = ads_methods.lookup_groupmem(domain, mem_ctx, group_sid,
236                                                      type, num_names, sid_mem,
237                                                      names, name_types);
238         }
239
240         return result;
241 }
242
243 /* find the sequence number for a domain */
244 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32_t *seq)
245 {
246         NTSTATUS result;
247
248         result = ads_methods.sequence_number(domain, seq);
249
250         if (reconnect_need_retry(result, domain)) {
251                 result = ads_methods.sequence_number(domain, seq);
252         }
253
254         return result;
255 }
256
257 /* find the lockout policy of a domain */
258 static NTSTATUS lockout_policy(struct winbindd_domain *domain,
259                                TALLOC_CTX *mem_ctx,
260                                struct samr_DomInfo12 *policy)
261 {
262         NTSTATUS result;
263
264         result = ads_methods.lockout_policy(domain, mem_ctx, policy);
265
266         if (reconnect_need_retry(result, domain)) {
267                 result = ads_methods.lockout_policy(domain, mem_ctx, policy);
268         }
269
270         return result;
271 }
272
273 /* find the password policy of a domain */
274 static NTSTATUS password_policy(struct winbindd_domain *domain,
275                                 TALLOC_CTX *mem_ctx,
276                                 struct samr_DomInfo1 *policy)
277 {
278         NTSTATUS result;
279
280         result = ads_methods.password_policy(domain, mem_ctx, policy);
281
282         if (reconnect_need_retry(result, domain)) {
283                 result = ads_methods.password_policy(domain, mem_ctx, policy);
284         }
285
286         return result;
287 }
288
289 /* get a list of trusted domains */
290 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
291                                 TALLOC_CTX *mem_ctx,
292                                 struct netr_DomainTrustList *trusts)
293 {
294         NTSTATUS result;
295
296         result = ads_methods.trusted_domains(domain, mem_ctx, trusts);
297
298         if (reconnect_need_retry(result, domain)) {
299                 result = ads_methods.trusted_domains(domain, mem_ctx, trusts);
300         }
301
302         return result;
303 }
304
305 /* the rpc backend methods are exposed via this structure */
306 struct winbindd_methods reconnect_ads_methods = {
307         true,
308         query_user_list,
309         enum_dom_groups,
310         enum_local_groups,
311         name_to_sid,
312         sid_to_name,
313         rids_to_names,
314         query_user,
315         lookup_usergroups,
316         lookup_useraliases,
317         lookup_groupmem,
318         sequence_number,
319         lockout_policy,
320         password_policy,
321         trusted_domains,
322 };
323
324 #endif