~zulcss/ubuntu/lucid/likewise-open/likewise-open-sru

« back to all changes in this revision

Viewing changes to samba/source/winbindd/likewise/gc_util.c

  • Committer: Bazaar Package Importer
  • Author(s): Rick Clark
  • Date: 2008-08-27 08:56:20 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080827085620-5q0f58b9qtog9myq
Tags: 4.1.0.2956-0ubuntu1
* missing-likewise-logo.diff: removed
* fixed copyright notice
* updated Standards-Version to 3.8.0
* removed path from command in prerm
* removed stop in S runlevel

Show diffs side-by-side

added added

removed removed

Lines of Context:
93
93
        return ret;
94
94
}
95
95
 
96
 
 
97
 
/**********************************************************************
98
 
 *********************************************************************/
99
 
 
100
 
static NTSTATUS gc_add_forest(const char *forest)
 
96
/**********************************************************************
 
97
 *********************************************************************/
 
98
 
 
99
 NTSTATUS gc_find_forest_root(struct gc_info *gc, const char *domain)
 
100
{
 
101
        ADS_STRUCT *ads = NULL;
 
102
        ADS_STATUS ads_status;
 
103
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
104
        struct cldap_netlogon_reply cldap_reply;
 
105
        
 
106
        if (!gc || !domain) {           
 
107
                return NT_STATUS_INVALID_PARAMETER;
 
108
        }
 
109
 
 
110
        ZERO_STRUCT(cldap_reply);
 
111
        
 
112
        ads = ads_init(domain, NULL, NULL);
 
113
        BAIL_ON_PTR_ERROR(ads, nt_status);
 
114
 
 
115
        ads->auth.flags = ADS_AUTH_NO_BIND;     
 
116
        ads_status = ads_connect(ads);
 
117
        if (!ADS_ERR_OK(ads_status)) {
 
118
                DEBUG(4, ("find_forest_root: ads_connect(%s) failed! (%s)\n",
 
119
                          domain, ads_errstr(ads_status)));
 
120
        }
 
121
        nt_status = ads_ntstatus(ads_status);
 
122
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
123
 
 
124
        if (!ads_cldap_netlogon(ads->config.ldap_server_name, 
 
125
                                ads->config.realm,
 
126
                                &cldap_reply))
 
127
        {
 
128
                DEBUG(4,("find_forest_root: Failed to get a CLDAP reply from %s!\n",
 
129
                         ads->server.ldap_server));
 
130
                nt_status = NT_STATUS_IO_TIMEOUT;
 
131
                BAIL_ON_NTSTATUS_ERROR(nt_status);              
 
132
        }
 
133
 
 
134
        gc->forest_name = talloc_strdup(gc, cldap_reply.forest);
 
135
        BAIL_ON_PTR_ERROR(gc->forest_name, nt_status);
 
136
 
 
137
done:
 
138
        if (ads) {
 
139
                ads_destroy(&ads);
 
140
        }
 
141
        
 
142
        return nt_status;
 
143
}
 
144
 
 
145
/**********************************************************************
 
146
 *********************************************************************/
 
147
 
 
148
static NTSTATUS gc_add_forest(const char *domain)
101
149
{
102
150
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
103
151
        struct gc_info *gc = NULL;
 
152
        struct gc_info *find_gc = NULL;
104
153
        char *dn;
105
154
        ADS_STRUCT *ads = NULL;
106
155
        struct likewise_cell *primary_cell = NULL;
111
160
                BAIL_ON_NTSTATUS_ERROR(nt_status);
112
161
        }
113
162
 
114
 
        /* Check for duplicates */
 
163
        /* Check for duplicates based on domain name first as this 
 
164
           requires no connection */
115
165
 
116
 
        gc = gc_list_head();
117
 
        while (gc) {
118
 
                if (strequal (gc->forest_name, forest))
 
166
        find_gc = gc_list_head();
 
167
        while (find_gc) {
 
168
                if (strequal (find_gc->forest_name, domain))
119
169
                        break;
120
 
                gc = gc->next;
 
170
                find_gc = find_gc->next;
121
171
        }
122
172
 
123
 
        if (gc) {
124
 
                DEBUG(10,("gc_add_forest: %s already in list\n", forest));
 
173
        if (find_gc) {
 
174
                DEBUG(10,("gc_add_forest: %s already in list\n", find_gc->forest_name));
125
175
                return NT_STATUS_OK;
126
176
        }
127
177
 
130
180
                BAIL_ON_NTSTATUS_ERROR(nt_status);
131
181
        }
132
182
 
133
 
        gc->forest_name = talloc_strdup(gc, forest);
134
 
        BAIL_ON_PTR_ERROR(gc->forest_name, nt_status);
 
183
        /* Query the rootDSE for the forest root naming conect first.
 
184
           Check that the a GC server for the forest has not already 
 
185
           been added */
 
186
 
 
187
        nt_status = gc_find_forest_root(gc, domain);    
 
188
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
189
 
 
190
        find_gc = gc_list_head();
 
191
        while (find_gc) {
 
192
                if (strequal (find_gc->forest_name, gc->forest_name))
 
193
                        break;
 
194
                find_gc = find_gc->next;
 
195
        }
 
196
 
 
197
        if (find_gc) {
 
198
                DEBUG(10,("gc_add_forest: Forest %s already in list\n", 
 
199
                          find_gc->forest_name));
 
200
                return NT_STATUS_OK;
 
201
        }
 
202
 
 
203
        /* Not found, so add it here.  Make sure we connect to 
 
204
           a DC in _this_ domain and not the forest root. */
135
205
 
136
206
        dn = ads_build_dn(gc->forest_name);
137
207
        BAIL_ON_PTR_ERROR(dn, nt_status);
138
208
 
139
209
        gc->search_base = talloc_strdup(gc, dn);
140
210
        SAFE_FREE(dn);
141
 
        BAIL_ON_PTR_ERROR(gc->search_base, nt_status);
142
 
 
143
 
        /* Connect to the cell to find the forest settings.  This must
144
 
           be done before we mark the cell as a GC cell connection to
145
 
           get the correct information. */
146
 
 
147
 
        nt_status = cell_connect_dn(&gc->forest_cell, gc->search_base);
 
211
        BAIL_ON_PTR_ERROR(gc->search_base, nt_status);  
 
212
 
 
213
#if 0
 
214
        /* Can't use cell_connect_dn() here as there is no way to 
 
215
           specifiy the LWCELL_FLAG_GC_CELL flag setting for cell_connect() */
 
216
 
 
217
        nt_status = cell_connect_dn(&gc->forest_cell, gc->search_base);
148
218
        BAIL_ON_NTSTATUS_ERROR(nt_status);
 
219
#else
 
220
 
 
221
        gc->forest_cell = cell_new();
 
222
        BAIL_ON_PTR_ERROR(gc->forest_cell, nt_status);
 
223
        
 
224
        /* Set the DNS domain, dn, etc ... and add it to the list */
 
225
 
 
226
        cell_set_dns_domain(gc->forest_cell, gc->forest_name);
 
227
        cell_set_dn(gc->forest_cell, gc->search_base);
 
228
        cell_set_flags(gc->forest_cell, LWCELL_FLAG_GC_CELL);
 
229
#endif
149
230
 
150
231
        /* It is possible to belong to a non-forest cell and a
151
232
           non-provisioned forest (at our domain levele). In that
153
234
           cell since the GC searches will match our own schema
154
235
           model. */
155
236
 
156
 
        if (is_subdomain(primary_cell->dns_domain, gc->forest_name)) {
 
237
        if (strequal(primary_cell->forest_name, gc->forest_name) 
 
238
            || is_subdomain(primary_cell->dns_domain, gc->forest_name)) 
 
239
        {
157
240
                cell_set_flags(gc->forest_cell, cell_flags(primary_cell));
158
241
        } else {
159
242
                /* outside of our domain */
 
243
 
 
244
                nt_status = cell_connect(gc->forest_cell);
 
245
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
246
 
160
247
                nt_status = cell_lookup_settings(gc->forest_cell);
161
248
                BAIL_ON_NTSTATUS_ERROR(nt_status);
 
249
 
 
250
                /* Drop the connection now that we have the settings */
 
251
 
 
252
                ads = cell_connection(gc->forest_cell);
 
253
                ads_destroy(&ads);
 
254
                cell_set_connection(gc->forest_cell, NULL);
162
255
        }
163
256
 
164
 
        /* Drop the connection now that we have the settings */
165
 
 
166
 
        ads = cell_connection(gc->forest_cell);
167
 
        ads_destroy(&ads);
168
 
        cell_set_connection(gc->forest_cell, NULL);
169
 
 
170
 
        /* Set a couple of necessary flags to mark this for
171
 
           cell_do_search() */
172
 
 
173
 
        cell_set_flags(gc->forest_cell, LWCELL_FLAG_GC_CELL);
174
 
 
175
257
        DLIST_ADD_END(_gc_server_list, gc, struct gc_info*);
176
258
 
 
259
        DEBUG(10,("gc_add_forest: Added %s to Global Catalog list of servers\n",
 
260
                  gc->forest_name));
 
261
        
177
262
        nt_status = NT_STATUS_OK;
178
263
 
179
264
done:
180
265
        if (!NT_STATUS_IS_OK(nt_status)) {
181
266
                talloc_destroy(gc);
182
 
                DEBUG(0,("LWI: Failed to add new GC connection for %s (%s)\n",
183
 
                         forest, nt_errstr(nt_status)));
 
267
                DEBUG(3,("LWI: Failed to add new GC connection for %s (%s)\n",
 
268
                         domain, nt_errstr(nt_status)));
184
269
        }
185
270
 
186
271
        return nt_status;
228
313
                BAIL_ON_NTSTATUS_ERROR(nt_status);
229
314
        }
230
315
 
231
 
        /* Find our forst first */
 
316
        /* Find our forest first.  Have to try all domains here starting 
 
317
           with our own.  gc_add_forest() filters duplicates */
232
318
 
 
319
        nt_status = gc_add_forest(lp_realm());
 
320
        WARN_ON_NTSTATUS_ERROR(nt_status);
 
321
        
233
322
        for (i=0; i<num_domains; i++) {
234
 
                uint32_t flags = (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
 
323
                uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST);
 
324
 
 
325
                /* I think we should be able to break out of loop once
 
326
                   we add a GC for our forest and not have to test every one.
 
327
                   In fact, this entire loop is probably irrelevant since
 
328
                   the GC location code should always find a GC given lp_realm().
 
329
                   Will have to spend time testing before making the change.
 
330
                   --jerry */
235
331
 
236
332
                if ((domains[i].trust_flags & flags) == flags) {
237
333
                        nt_status = gc_add_forest(domains[i].dns_name);
238
 
                        BAIL_ON_NTSTATUS_ERROR(nt_status);
239
 
 
240
 
                        break;
 
334
                        WARN_ON_NTSTATUS_ERROR(nt_status);
 
335
                        /* Don't BAIL here since not every domain may 
 
336
                           have a GC server */
241
337
                }
242
338
        }
243
339
 
244
340
        /* Now add trusted forests.  gc_add_forest() will filter out
245
 
           duplicates */
 
341
           duplicates. Check everything with an incoming trust path
 
342
           that is not in our own forest.  */
246
343
 
247
344
        for (i=0; i<num_domains; i++) {
248
345
                uint32_t flags = domains[i].trust_flags;
249
 
                uint32_t attribs = domains[i].trust_attribs;
 
346
                uint32_t attribs = domains[i].trust_attribs;           
 
347
 
 
348
                /* Skip non_AD domains */
 
349
 
 
350
                if (strlen(domains[i].dns_name) == 0) {
 
351
                        continue;
 
352
                }
 
353
 
 
354
                /* Only add a GC for a forest outside of our own.
 
355
                   Ignore QUARANTINED/EXTERNAL trusts */
250
356
 
251
357
                if ((flags & NETR_TRUST_FLAG_INBOUND)
 
358
                    && !(flags & NETR_TRUST_FLAG_IN_FOREST)
252
359
                    && (attribs & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
253
360
                {
254
361
                        nt_status = gc_add_forest(domains[i].dns_name);
315
422
                BAIL_ON_NTSTATUS_ERROR(nt_status);
316
423
        }
317
424
 
318
 
        ads_status = cell_do_search(gc->forest_cell, gc->search_base,
 
425
        /* When you have multiple domain trees in a forest, the
 
426
           GC will search all naming contexts when you send it 
 
427
           and empty ("") base search suffix.   Tested against 
 
428
           Windows 2003.  */
 
429
 
 
430
        ads_status = cell_do_search(gc->forest_cell, "",
319
431
                                   LDAP_SCOPE_SUBTREE, filter, attrs, &m);
320
432
        nt_status = ads_ntstatus(ads_status);
321
433
        BAIL_ON_NTSTATUS_ERROR(nt_status);
491
603
                        /* Ignore failures and continue the search */
492
604
 
493
605
                        if (!domain_rec) {
 
606
                                e = ads_next_entry(ads, e);                             
494
607
                                continue;
495
608
                        }
496
609