~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/winbindd/idmap_adex/likewise_cell.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * idmap_adex: Support for AD Forests
 
3
 *
 
4
 * Copyright (C) Gerald (Jerry) Carter 2006-2008
 
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 2 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, write to the Free Software
 
18
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
 */
 
20
 
 
21
#include "includes.h"
 
22
#include "idmap_adex.h"
 
23
 
 
24
#undef DBGC_CLASS
 
25
#define DBGC_CLASS DBGC_IDMAP
 
26
 
 
27
static struct likewise_cell *_lw_cell_list = NULL;
 
28
 
 
29
/**********************************************************************
 
30
 Return the current HEAD of the list
 
31
 *********************************************************************/
 
32
 
 
33
 struct likewise_cell *cell_list_head(void)
 
34
{
 
35
        return _lw_cell_list;
 
36
}
 
37
 
 
38
 
 
39
/**********************************************************************
 
40
 *********************************************************************/
 
41
 
 
42
 void cell_destroy(struct likewise_cell *c)
 
43
{
 
44
        if (!c)
 
45
                return;
 
46
 
 
47
        if (c->conn)
 
48
                ads_destroy(&c->conn);
 
49
 
 
50
        talloc_destroy(c);
 
51
}
 
52
 
 
53
/**********************************************************************
 
54
 Free all cell entries and reset the list head to NULL
 
55
 *********************************************************************/
 
56
 
 
57
 void cell_list_destroy(void)
 
58
{
 
59
        struct likewise_cell *p = _lw_cell_list;
 
60
 
 
61
        while (p) {
 
62
                struct likewise_cell *q = p->next;
 
63
 
 
64
                cell_destroy(p);
 
65
 
 
66
                p = q;
 
67
        }
 
68
 
 
69
        _lw_cell_list = NULL;
 
70
 
 
71
        return;
 
72
}
 
73
 
 
74
/**********************************************************************
 
75
 Add a new cell structure to the list
 
76
 *********************************************************************/
 
77
 
 
78
 struct likewise_cell* cell_new(void)
 
79
{
 
80
        struct likewise_cell *c;
 
81
 
 
82
        /* Each cell struct is a TALLOC_CTX* */
 
83
 
 
84
        c = TALLOC_ZERO_P(NULL, struct likewise_cell);
 
85
        if (!c) {
 
86
                DEBUG(0,("cell_new: memory allocation failure!\n"));
 
87
                return NULL;
 
88
        }
 
89
 
 
90
        return c;
 
91
}
 
92
 
 
93
/**********************************************************************
 
94
 Add a new cell structure to the list
 
95
 *********************************************************************/
 
96
 
 
97
 bool cell_list_add(struct likewise_cell * cell)
 
98
{
 
99
        if (!cell) {
 
100
                return false;
 
101
        }
 
102
 
 
103
        /* Always add to the end */
 
104
 
 
105
        DLIST_ADD_END(_lw_cell_list, cell, struct likewise_cell *);
 
106
 
 
107
        return true;
 
108
}
 
109
 
 
110
/**********************************************************************
 
111
 Add a new cell structure to the list
 
112
 *********************************************************************/
 
113
 
 
114
 bool cell_list_remove(struct likewise_cell * cell)
 
115
{
 
116
        if (!cell) {
 
117
                return false;
 
118
        }
 
119
 
 
120
        /* Remove and drop the cell structure */
 
121
 
 
122
        DLIST_REMOVE(_lw_cell_list, cell);
 
123
        talloc_destroy(cell);
 
124
 
 
125
        return true;
 
126
}
 
127
 
 
128
/**********************************************************************
 
129
 Set the containing DNS domain for a cell
 
130
 *********************************************************************/
 
131
 
 
132
 void cell_set_dns_domain(struct likewise_cell *c, const char *dns_domain)
 
133
{
 
134
        c->dns_domain = talloc_strdup(c, dns_domain);
 
135
}
 
136
 
 
137
/**********************************************************************
 
138
 Set ADS connection for a cell
 
139
 *********************************************************************/
 
140
 
 
141
 void cell_set_connection(struct likewise_cell *c, ADS_STRUCT *ads)
 
142
{
 
143
        c->conn = ads;
 
144
}
 
145
 
 
146
/**********************************************************************
 
147
 *********************************************************************/
 
148
 
 
149
 void cell_set_flags(struct likewise_cell *c, uint32_t flags)
 
150
{
 
151
        c->flags |= flags;
 
152
}
 
153
 
 
154
/**********************************************************************
 
155
 *********************************************************************/
 
156
 
 
157
 void cell_clear_flags(struct likewise_cell *c, uint32_t flags)
 
158
{
 
159
        c->flags &= ~flags;
 
160
}
 
161
 
 
162
/**********************************************************************
 
163
 Set the Cell's DN
 
164
 *********************************************************************/
 
165
 
 
166
 void cell_set_dn(struct likewise_cell *c, const char *dn)
 
167
{
 
168
        if ( c->dn) {
 
169
                talloc_free(c->dn);
 
170
                c->dn = NULL;
 
171
        }
 
172
 
 
173
        c->dn = talloc_strdup(c, dn);
 
174
}
 
175
 
 
176
/**********************************************************************
 
177
 *********************************************************************/
 
178
 
 
179
 void cell_set_domain_sid(struct likewise_cell *c, DOM_SID *sid)
 
180
{
 
181
        sid_copy(&c->domain_sid, sid);
 
182
}
 
183
 
 
184
/*
 
185
 * Query Routines
 
186
 */
 
187
 
 
188
/**********************************************************************
 
189
 *********************************************************************/
 
190
 
 
191
 const char* cell_search_base(struct likewise_cell *c)
 
192
{
 
193
        if (!c)
 
194
                return NULL;
 
195
 
 
196
        return talloc_asprintf(c, "cn=%s,%s", ADEX_CELL_RDN, c->dn);
 
197
}
 
198
 
 
199
/**********************************************************************
 
200
 *********************************************************************/
 
201
 
 
202
 bool cell_search_forest(struct likewise_cell *c)
 
203
{
 
204
        uint32_t test_flags = LWCELL_FLAG_SEARCH_FOREST;
 
205
 
 
206
        return ((c->flags & test_flags) == test_flags);
 
207
}
 
208
 
 
209
/**********************************************************************
 
210
 *********************************************************************/
 
211
 
 
212
 uint32_t cell_flags(struct likewise_cell *c)
 
213
{
 
214
        if (!c)
 
215
                return 0;
 
216
 
 
217
        return c->flags;
 
218
}
 
219
 
 
220
/**********************************************************************
 
221
 *********************************************************************/
 
222
 
 
223
 const char *cell_dns_domain(struct likewise_cell *c)
 
224
{
 
225
        if (!c)
 
226
                return NULL;
 
227
 
 
228
        return c->dns_domain;
 
229
}
 
230
 
 
231
/**********************************************************************
 
232
 *********************************************************************/
 
233
 
 
234
 ADS_STRUCT *cell_connection(struct likewise_cell *c)
 
235
{
 
236
        if (!c)
 
237
                return NULL;
 
238
 
 
239
        return c->conn;
 
240
}
 
241
 
 
242
/*
 
243
 * Connection functions
 
244
 */
 
245
 
 
246
/********************************************************************
 
247
 *******************************************************************/
 
248
 
 
249
 NTSTATUS cell_connect(struct likewise_cell *c)
 
250
{
 
251
        ADS_STRUCT *ads = NULL;
 
252
        ADS_STATUS ads_status;
 
253
        fstring dc_name;
 
254
        struct sockaddr_storage dcip;
 
255
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
256
 
 
257
        /* have to at least have the AD domain name */
 
258
 
 
259
        if (!c->dns_domain) {
 
260
                nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 
261
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
262
        }
 
263
 
 
264
        /* clear out any old information */
 
265
 
 
266
        if (c->conn) {
 
267
                ads_destroy(&c->conn);
 
268
                c->conn = NULL;
 
269
        }
 
270
 
 
271
        /* now setup the new connection */
 
272
 
 
273
        ads = ads_init(c->dns_domain, NULL, NULL);
 
274
        BAIL_ON_PTR_ERROR(ads, nt_status);
 
275
 
 
276
        ads->auth.password =
 
277
            secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
 
278
        ads->auth.realm = SMB_STRDUP(lp_realm());
 
279
 
 
280
        /* Make the connection.  We should already have an initial
 
281
           TGT using the machine creds */
 
282
 
 
283
        if (cell_flags(c) & LWCELL_FLAG_GC_CELL) {
 
284
                ads_status = ads_connect_gc(ads);
 
285
        } else {
 
286
          /* Set up server affinity for normal cells and the client
 
287
             site name cache */
 
288
 
 
289
          if (!get_dc_name("", c->dns_domain, dc_name, &dcip)) {
 
290
            nt_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
 
291
            BAIL_ON_NTSTATUS_ERROR(nt_status);
 
292
          }
 
293
 
 
294
          ads_status = ads_connect(ads);
 
295
        }
 
296
 
 
297
 
 
298
        c->conn = ads;
 
299
 
 
300
        nt_status = ads_ntstatus(ads_status);
 
301
 
 
302
done:
 
303
        if (!NT_STATUS_IS_OK(nt_status)) {
 
304
                ads_destroy(&ads);
 
305
                c->conn = NULL;
 
306
        }
 
307
 
 
308
        return nt_status;
 
309
}
 
310
 
 
311
/********************************************************************
 
312
 *******************************************************************/
 
313
 
 
314
 NTSTATUS cell_connect_dn(struct likewise_cell **c, const char *dn)
 
315
{
 
316
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
317
        struct likewise_cell *new_cell = NULL;
 
318
        char *dns_domain = NULL;
 
319
 
 
320
        if (*c || !dn) {
 
321
                nt_status = NT_STATUS_INVALID_PARAMETER;
 
322
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
323
        }
 
324
 
 
325
        if ((new_cell = cell_new()) == NULL) {
 
326
                nt_status = NT_STATUS_NO_MEMORY;
 
327
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
328
        }
 
329
 
 
330
        /* Set the DNS domain, dn, etc ... and add it to the list */
 
331
 
 
332
        dns_domain = cell_dn_to_dns(dn);
 
333
        cell_set_dns_domain(new_cell, dns_domain);
 
334
        SAFE_FREE(dns_domain);
 
335
 
 
336
        cell_set_dn(new_cell, dn);
 
337
 
 
338
        nt_status = cell_connect(new_cell);
 
339
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
340
 
 
341
        *c = new_cell;
 
342
 
 
343
done:
 
344
        if (!NT_STATUS_IS_OK(nt_status)) {
 
345
                DEBUG(1,("LWI: Failled to connect to cell \"%s\" (%s)\n",
 
346
                         dn ? dn : "NULL", nt_errstr(nt_status)));
 
347
                talloc_destroy(new_cell);
 
348
        }
 
349
 
 
350
        return nt_status;
 
351
}
 
352
 
 
353
 
 
354
/********************************************************************
 
355
 *******************************************************************/
 
356
 
 
357
#define MAX_SEARCH_COUNT    2
 
358
 
 
359
 ADS_STATUS cell_do_search(struct likewise_cell *c,
 
360
                          const char *search_base,
 
361
                          int scope,
 
362
                          const char *expr,
 
363
                          const char **attrs,
 
364
                          LDAPMessage ** msg)
 
365
{
 
366
        int search_count = 0;
 
367
        ADS_STATUS status;
 
368
        NTSTATUS nt_status;
 
369
 
 
370
        /* check for a NULL connection */
 
371
 
 
372
        if (!c->conn) {
 
373
                nt_status = cell_connect(c);
 
374
                if (!NT_STATUS_IS_OK(nt_status)) {
 
375
                        status = ADS_ERROR_NT(nt_status);
 
376
                        return status;
 
377
                }
 
378
        }
 
379
 
 
380
        DEBUG(10, ("cell_do_search: Base = %s,  Filter = %s, Scope = %d, GC = %s\n",
 
381
                   search_base, expr, scope,
 
382
                   c->conn->server.gc ? "yes" : "no"));
 
383
 
 
384
        /* we try multiple times in case the ADS_STRUCT is bad
 
385
           and we need to reconnect */
 
386
 
 
387
        while (search_count < MAX_SEARCH_COUNT) {
 
388
                *msg = NULL;
 
389
                status = ads_do_search(c->conn, search_base,
 
390
                                       scope, expr, attrs, msg);
 
391
                if (ADS_ERR_OK(status)) {
 
392
                        if (DEBUGLEVEL >= 10) {
 
393
                                LDAPMessage *e = NULL;
 
394
 
 
395
                                int n = ads_count_replies(c->conn, *msg);
 
396
 
 
397
                                DEBUG(10,("cell_do_search: Located %d entries\n", n));
 
398
 
 
399
                                for (e=ads_first_entry(c->conn, *msg);
 
400
                                     e!=NULL;
 
401
                                     e = ads_next_entry(c->conn, e))
 
402
                                {
 
403
                                        char *dn = ads_get_dn(c->conn, talloc_tos(), e);
 
404
 
 
405
                                        DEBUGADD(10,("   dn: %s\n", dn ? dn : "<NULL>"));
 
406
                                        TALLOC_FREE(dn);
 
407
                                }
 
408
                        }
 
409
 
 
410
                        return status;
 
411
                }
 
412
 
 
413
 
 
414
                DEBUG(5, ("cell_do_search: search[%d] failed (%s)\n",
 
415
                          search_count, ads_errstr(status)));
 
416
 
 
417
                search_count++;
 
418
 
 
419
                /* Houston, we have a problem */
 
420
 
 
421
                if (status.error_type == ENUM_ADS_ERROR_LDAP) {
 
422
                        switch (status.err.rc) {
 
423
                        case LDAP_TIMELIMIT_EXCEEDED:
 
424
                        case LDAP_TIMEOUT:
 
425
                        case -1:        /* we get this error if we cannot contact
 
426
                                           the LDAP server */
 
427
                                nt_status = cell_connect(c);
 
428
                                if (!NT_STATUS_IS_OK(nt_status)) {
 
429
                                        status = ADS_ERROR_NT(nt_status);
 
430
                                        return status;
 
431
                                }
 
432
                                break;
 
433
                        default:
 
434
                                /* we're all done here */
 
435
                                return status;
 
436
                        }
 
437
                }
 
438
        }
 
439
 
 
440
        DEBUG(5, ("cell_do_search: exceeded maximum search count!\n"));
 
441
 
 
442
        return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
 
443
}