~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/libnet/libnet_site.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
   Unix SMB/CIFS implementation.
 
3
 
 
4
   Copyright (C) Brad Henry     2005
 
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 3 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, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include "includes.h"
 
21
#include "libnet/libnet.h"
 
22
#include "libcli/cldap/cldap.h"
 
23
#include "lib/ldb/include/ldb.h"
 
24
#include "lib/ldb/include/ldb_errors.h"
 
25
#include "librpc/rpc/dcerpc.h"
 
26
#include "libcli/resolve/resolve.h"
 
27
#include "param/param.h"
 
28
 
 
29
/**
 
30
 * 1. Setup a CLDAP socket.
 
31
 * 2. Lookup the default Site-Name.
 
32
 */
 
33
NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_context *lctx, struct libnet_JoinSite *r)
 
34
{
 
35
        NTSTATUS status;
 
36
        TALLOC_CTX *tmp_ctx;
 
37
 
 
38
        char *site_name_str;
 
39
        char *config_dn_str;
 
40
        char *server_dn_str;
 
41
 
 
42
        struct cldap_socket *cldap = NULL;
 
43
        struct cldap_netlogon search;
 
44
 
 
45
        tmp_ctx = talloc_named(ctx, 0, "libnet_FindSite temp context");
 
46
        if (!tmp_ctx) {
 
47
                r->out.error_string = NULL;
 
48
                return NT_STATUS_NO_MEMORY;
 
49
        }
 
50
 
 
51
        /* Resolve the site name. */
 
52
        ZERO_STRUCT(search);
 
53
        search.in.dest_address = r->in.dest_address;
 
54
        search.in.dest_port = r->in.cldap_port;
 
55
        search.in.acct_control = -1;
 
56
        search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
 
57
        search.in.map_response = true;
 
58
 
 
59
        cldap = cldap_socket_init(tmp_ctx, lctx->event_ctx, lp_iconv_convenience(lctx->lp_ctx));
 
60
        status = cldap_netlogon(cldap, tmp_ctx, &search);
 
61
        if (!NT_STATUS_IS_OK(status)
 
62
            || !search.out.netlogon.data.nt5_ex.client_site) {
 
63
                /*
 
64
                  If cldap_netlogon() returns in error,
 
65
                  default to using Default-First-Site-Name.
 
66
                */
 
67
                site_name_str = talloc_asprintf(tmp_ctx, "%s",
 
68
                                                "Default-First-Site-Name");
 
69
                if (!site_name_str) {
 
70
                        r->out.error_string = NULL;
 
71
                        talloc_free(tmp_ctx);
 
72
                        return NT_STATUS_NO_MEMORY;
 
73
                }
 
74
        } else {
 
75
                site_name_str = talloc_asprintf(tmp_ctx, "%s",
 
76
                                        search.out.netlogon.data.nt5_ex.client_site);
 
77
                if (!site_name_str) {
 
78
                        r->out.error_string = NULL;
 
79
                        talloc_free(tmp_ctx);
 
80
                        return NT_STATUS_NO_MEMORY;
 
81
                }
 
82
        }
 
83
 
 
84
        /* Generate the CN=Configuration,... DN. */
 
85
/* TODO: look it up! */
 
86
        config_dn_str = talloc_asprintf(tmp_ctx, "CN=Configuration,%s", r->in.domain_dn_str);
 
87
        if (!config_dn_str) {
 
88
                r->out.error_string = NULL;
 
89
                talloc_free(tmp_ctx);
 
90
                return NT_STATUS_NO_MEMORY;
 
91
        }
 
92
 
 
93
        /* Generate the CN=Servers,... DN. */
 
94
        server_dn_str = talloc_asprintf(tmp_ctx, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s",
 
95
                                                 r->in.netbios_name, site_name_str, config_dn_str);
 
96
        if (!server_dn_str) {
 
97
                r->out.error_string = NULL;
 
98
                talloc_free(tmp_ctx);
 
99
                return NT_STATUS_NO_MEMORY;
 
100
        }
 
101
 
 
102
        r->out.site_name_str = site_name_str;
 
103
        talloc_steal(r, site_name_str);
 
104
 
 
105
        r->out.config_dn_str = config_dn_str;
 
106
        talloc_steal(r, config_dn_str);
 
107
 
 
108
        r->out.server_dn_str = server_dn_str;
 
109
        talloc_steal(r, server_dn_str);
 
110
 
 
111
        talloc_free(tmp_ctx);
 
112
        return NT_STATUS_OK;
 
113
}
 
114
 
 
115
/*
 
116
 * find out Site specific stuff:
 
117
 * 1. Lookup the Site name.
 
118
 * 2. Add entry CN=<netbios name>,CN=Servers,CN=<site name>,CN=Sites,CN=Configuration,<domain dn>.
 
119
 * TODO: 3.) use DsAddEntry() to create CN=NTDS Settings,CN=<netbios name>,CN=Servers,CN=<site name>,...
 
120
 */
 
121
NTSTATUS libnet_JoinSite(struct libnet_context *ctx, 
 
122
                         struct ldb_context *remote_ldb,
 
123
                         struct libnet_JoinDomain *libnet_r)
 
124
{
 
125
        NTSTATUS status;
 
126
        TALLOC_CTX *tmp_ctx;
 
127
 
 
128
        struct libnet_JoinSite *r;
 
129
 
 
130
        struct ldb_dn *server_dn;
 
131
        struct ldb_message *msg;
 
132
        int rtn;
 
133
 
 
134
        const char *server_dn_str;
 
135
        const char *config_dn_str;
 
136
        struct nbt_name name;
 
137
        const char *dest_addr = NULL;
 
138
 
 
139
        tmp_ctx = talloc_named(libnet_r, 0, "libnet_JoinSite temp context");
 
140
        if (!tmp_ctx) {
 
141
                libnet_r->out.error_string = NULL;
 
142
                return NT_STATUS_NO_MEMORY;
 
143
        }
 
144
 
 
145
        r = talloc(tmp_ctx, struct libnet_JoinSite);
 
146
        if (!r) {
 
147
                libnet_r->out.error_string = NULL;
 
148
                talloc_free(tmp_ctx);
 
149
                return NT_STATUS_NO_MEMORY;
 
150
        }
 
151
 
 
152
        make_nbt_name_client(&name, libnet_r->out.samr_binding->host);
 
153
        status = resolve_name(lp_resolve_context(ctx->lp_ctx), &name, r, &dest_addr, ctx->event_ctx);
 
154
        if (!NT_STATUS_IS_OK(status)) {
 
155
                libnet_r->out.error_string = NULL;
 
156
                talloc_free(tmp_ctx);
 
157
                return status;
 
158
        }
 
159
 
 
160
        /* Resolve the site name and AD DN's. */
 
161
        r->in.dest_address = dest_addr;
 
162
        r->in.netbios_name = libnet_r->in.netbios_name;
 
163
        r->in.domain_dn_str = libnet_r->out.domain_dn_str;
 
164
        r->in.cldap_port = lp_cldap_port(ctx->lp_ctx);
 
165
 
 
166
        status = libnet_FindSite(tmp_ctx, ctx, r);
 
167
        if (!NT_STATUS_IS_OK(status)) {
 
168
                libnet_r->out.error_string =
 
169
                        talloc_steal(libnet_r, r->out.error_string);
 
170
                talloc_free(tmp_ctx);
 
171
                return status;
 
172
        }
 
173
 
 
174
        config_dn_str = r->out.config_dn_str;
 
175
        server_dn_str = r->out.server_dn_str;
 
176
 
 
177
        /*
 
178
         Add entry CN=<netbios name>,CN=Servers,CN=<site name>,CN=Sites,CN=Configuration,<domain dn>.
 
179
        */
 
180
        msg = ldb_msg_new(tmp_ctx);
 
181
        if (!msg) {
 
182
                libnet_r->out.error_string = NULL;
 
183
                talloc_free(tmp_ctx);
 
184
                return NT_STATUS_NO_MEMORY;
 
185
        }
 
186
 
 
187
        rtn = ldb_msg_add_string(msg, "objectClass", "server");
 
188
        if (rtn != 0) {
 
189
                libnet_r->out.error_string = NULL;
 
190
                talloc_free(tmp_ctx);
 
191
                return NT_STATUS_NO_MEMORY;
 
192
        }
 
193
        rtn = ldb_msg_add_string(msg, "systemFlags", "50000000");
 
194
        if (rtn != 0) {
 
195
                libnet_r->out.error_string = NULL;
 
196
                talloc_free(tmp_ctx);
 
197
                return NT_STATUS_NO_MEMORY;
 
198
        }
 
199
        rtn = ldb_msg_add_string(msg, "serverReference", libnet_r->out.account_dn_str);
 
200
        if (rtn != 0) {
 
201
                libnet_r->out.error_string = NULL;
 
202
                talloc_free(tmp_ctx);
 
203
                return NT_STATUS_NO_MEMORY;
 
204
        }
 
205
 
 
206
        server_dn = ldb_dn_new(tmp_ctx, remote_ldb, server_dn_str);
 
207
        if ( ! ldb_dn_validate(server_dn)) {
 
208
                libnet_r->out.error_string = talloc_asprintf(libnet_r,
 
209
                                        "Invalid server dn: %s",
 
210
                                        server_dn_str);
 
211
                talloc_free(tmp_ctx);
 
212
                return NT_STATUS_UNSUCCESSFUL;
 
213
        }
 
214
 
 
215
        msg->dn = server_dn;
 
216
 
 
217
        rtn = ldb_add(remote_ldb, msg);
 
218
        if (rtn == LDB_ERR_ENTRY_ALREADY_EXISTS) {
 
219
                int i;
 
220
 
 
221
                /* make a 'modify' msg, and only for serverReference */
 
222
                msg = ldb_msg_new(tmp_ctx);
 
223
                if (!msg) {
 
224
                        libnet_r->out.error_string = NULL;
 
225
                        talloc_free(tmp_ctx);
 
226
                        return NT_STATUS_NO_MEMORY;
 
227
                }
 
228
                msg->dn = server_dn;
 
229
 
 
230
                rtn = ldb_msg_add_string(msg, "serverReference",libnet_r->out.account_dn_str);
 
231
                if (rtn != 0) {
 
232
                        libnet_r->out.error_string = NULL;
 
233
                        talloc_free(tmp_ctx);
 
234
                        return NT_STATUS_NO_MEMORY;
 
235
                }
 
236
 
 
237
                /* mark all the message elements (should be just one)
 
238
                   as LDB_FLAG_MOD_REPLACE */
 
239
                for (i=0;i<msg->num_elements;i++) {
 
240
                        msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
 
241
                }
 
242
 
 
243
                rtn = ldb_modify(remote_ldb, msg);
 
244
                if (rtn != 0) {
 
245
                        libnet_r->out.error_string
 
246
                                = talloc_asprintf(libnet_r,
 
247
                                                  "Failed to modify server entry %s: %s: %d",
 
248
                                                  server_dn_str,
 
249
                                                  ldb_errstring(remote_ldb), rtn);
 
250
                        talloc_free(tmp_ctx);
 
251
                        return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
252
                }
 
253
        } else if (rtn != 0) {
 
254
                libnet_r->out.error_string
 
255
                        = talloc_asprintf(libnet_r,
 
256
                                "Failed to add server entry %s: %s: %d",
 
257
                                server_dn_str, ldb_errstring(remote_ldb),
 
258
                                rtn);
 
259
                talloc_free(tmp_ctx);
 
260
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
 
261
        }
 
262
        DEBUG(0, ("We still need to perform a DsAddEntry() so that we can create the CN=NTDS Settings container.\n"));
 
263
 
 
264
        /* Store the server DN in libnet_r */
 
265
        libnet_r->out.server_dn_str = server_dn_str;
 
266
        talloc_steal(libnet_r, server_dn_str);
 
267
 
 
268
        talloc_free(tmp_ctx);
 
269
        return NT_STATUS_OK;
 
270
}