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