s4/libnet: Add "dNSHostName" attribute when joining the Site
[kamenim/samba.git] / source4 / libnet / libnet_site.c
index 444a9ba485851354ad53d545a268b48fd03f3e3d..24311df5a2791c7b8d3f1603ddf689cb61970917 100644 (file)
@@ -5,7 +5,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -14,8 +14,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "libcli/cldap/cldap.h"
 #include "lib/ldb/include/ldb.h"
 #include "lib/ldb/include/ldb_errors.h"
-#include "librpc/rpc/dcerpc.h"
+#include "libcli/resolve/resolve.h"
+#include "param/param.h"
+#include "lib/tsocket/tsocket.h"
 
-/*
+/**
  * 1. Setup a CLDAP socket.
  * 2. Lookup the default Site-Name.
  */
-NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_JoinSite *r)
+NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_context *lctx, struct libnet_JoinSite *r)
 {
        NTSTATUS status;
        TALLOC_CTX *tmp_ctx;
@@ -40,6 +41,8 @@ NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_JoinSite *r)
 
        struct cldap_socket *cldap = NULL;
        struct cldap_netlogon search;
+       int ret;
+       struct tsocket_address *dest_address;
 
        tmp_ctx = talloc_named(ctx, 0, "libnet_FindSite temp context");
        if (!tmp_ctx) {
@@ -49,13 +52,32 @@ NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_JoinSite *r)
 
        /* Resolve the site name. */
        ZERO_STRUCT(search);
-       search.in.dest_address = r->in.dest_address;
+       search.in.dest_address = NULL;
+       search.in.dest_port = 0;
        search.in.acct_control = -1;
-       search.in.version = 6;
+       search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
+       search.in.map_response = true;
+
+       ret = tsocket_address_inet_from_strings(tmp_ctx, "ip",
+                                               r->in.dest_address,
+                                               r->in.cldap_port,
+                                               &dest_address);
+       if (ret != 0) {
+               r->out.error_string = NULL;
+               status = map_nt_error_from_unix(errno);
+               return status;
+       }
 
-       cldap = cldap_socket_init(tmp_ctx, NULL);
-       status = cldap_netlogon(cldap, tmp_ctx, &search);
+       /* we want to use non async calls, so we're not passing an event context */
+       status = cldap_socket_init(tmp_ctx, NULL, NULL, dest_address, &cldap);
        if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(tmp_ctx);
+               r->out.error_string = NULL;
+               return status;
+       }
+       status = cldap_netlogon(cldap, lp_iconv_convenience(lctx->lp_ctx), tmp_ctx, &search);
+       if (!NT_STATUS_IS_OK(status)
+           || !search.out.netlogon.data.nt5_ex.client_site) {
                /*
                  If cldap_netlogon() returns in error,
                  default to using Default-First-Site-Name.
@@ -69,7 +91,7 @@ NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_JoinSite *r)
                }
        } else {
                site_name_str = talloc_asprintf(tmp_ctx, "%s",
-                                       search.out.netlogon.logon5.site_name);
+                                       search.out.netlogon.data.nt5_ex.client_site);
                if (!site_name_str) {
                        r->out.error_string = NULL;
                        talloc_free(tmp_ctx);
@@ -78,6 +100,7 @@ NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_JoinSite *r)
        }
 
        /* Generate the CN=Configuration,... DN. */
+/* TODO: look it up! */
        config_dn_str = talloc_asprintf(tmp_ctx, "CN=Configuration,%s", r->in.domain_dn_str);
        if (!config_dn_str) {
                r->out.error_string = NULL;
@@ -113,7 +136,8 @@ NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_JoinSite *r)
  * 2. Add entry CN=<netbios name>,CN=Servers,CN=<site name>,CN=Sites,CN=Configuration,<domain dn>.
  * TODO: 3.) use DsAddEntry() to create CN=NTDS Settings,CN=<netbios name>,CN=Servers,CN=<site name>,...
  */
-NTSTATUS libnet_JoinSite(struct ldb_context *remote_ldb,
+NTSTATUS libnet_JoinSite(struct libnet_context *ctx, 
+                        struct ldb_context *remote_ldb,
                         struct libnet_JoinDomain *libnet_r)
 {
        NTSTATUS status;
@@ -127,6 +151,9 @@ NTSTATUS libnet_JoinSite(struct ldb_context *remote_ldb,
 
        const char *server_dn_str;
        const char *config_dn_str;
+       struct nbt_name name;
+       const char *dest_addr = NULL;
+       char *dns_host_name;
 
        tmp_ctx = talloc_named(libnet_r, 0, "libnet_JoinSite temp context");
        if (!tmp_ctx) {
@@ -141,17 +168,26 @@ NTSTATUS libnet_JoinSite(struct ldb_context *remote_ldb,
                return NT_STATUS_NO_MEMORY;
        }
 
+       make_nbt_name_client(&name, libnet_r->out.samr_binding->host);
+       status = resolve_name(lp_resolve_context(ctx->lp_ctx), &name, r, &dest_addr, ctx->event_ctx);
+       if (!NT_STATUS_IS_OK(status)) {
+               libnet_r->out.error_string = NULL;
+               talloc_free(tmp_ctx);
+               return status;
+       }
+
        /* Resolve the site name and AD DN's. */
-       r->in.dest_address = libnet_r->out.samr_binding->host;
+       r->in.dest_address = dest_addr;
        r->in.netbios_name = libnet_r->in.netbios_name;
        r->in.domain_dn_str = libnet_r->out.domain_dn_str;
+       r->in.cldap_port = lp_cldap_port(ctx->lp_ctx);
 
-       status = libnet_FindSite(tmp_ctx, r);
+       status = libnet_FindSite(tmp_ctx, ctx, r);
        if (!NT_STATUS_IS_OK(status)) {
                libnet_r->out.error_string =
                        talloc_steal(libnet_r, r->out.error_string);
                talloc_free(tmp_ctx);
-               return NT_STATUS_NO_MEMORY;
+               return status;
        }
 
        config_dn_str = r->out.config_dn_str;
@@ -185,9 +221,18 @@ NTSTATUS libnet_JoinSite(struct ldb_context *remote_ldb,
                talloc_free(tmp_ctx);
                return NT_STATUS_NO_MEMORY;
        }
+       dns_host_name = talloc_asprintf(tmp_ctx, "%s.%s",
+                                       libnet_r->in.netbios_name, libnet_r->out.realm);
+       if (!dns_host_name) {
+               r->out.error_string = NULL;
+               talloc_free(tmp_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
+       strlower_m(dns_host_name);
+       rtn = ldb_msg_add_string(msg, "dNSHostName", dns_host_name);
 
-       server_dn = ldb_dn_explode(tmp_ctx, server_dn_str);
-       if (server_dn == NULL) {
+       server_dn = ldb_dn_new(tmp_ctx, remote_ldb, server_dn_str);
+       if ( ! ldb_dn_validate(server_dn)) {
                libnet_r->out.error_string = talloc_asprintf(libnet_r,
                                        "Invalid server dn: %s",
                                        server_dn_str);
@@ -199,7 +244,7 @@ NTSTATUS libnet_JoinSite(struct ldb_context *remote_ldb,
 
        rtn = ldb_add(remote_ldb, msg);
        if (rtn == LDB_ERR_ENTRY_ALREADY_EXISTS) {
-               int i;
+               unsigned int i;
 
                /* make a 'modify' msg, and only for serverReference */
                msg = ldb_msg_new(tmp_ctx);