root/source4/libnet/libnet_site.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. libnet_FindSite
  2. libnet_JoinSite

   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)
     /* [<][>][^][v][top][bottom][index][help] */
  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, 
     /* [<][>][^][v][top][bottom][index][help] */
 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 }

/* [<][>][^][v][top][bottom][index][help] */