lib/param: Move all enum declarations to lib/param
[samba.git] / source3 / utils / net_ads.c
index 5989fec3cebb2db25c69d427ccb0f065a76c8bca..a4f1588e515800550b39c3177fdf82cdeaa10c41 100644 (file)
 
 #include "includes.h"
 #include "utils/net.h"
+#include "rpc_client/cli_pipe.h"
 #include "librpc/gen_ndr/ndr_krb5pac.h"
-#include "../librpc/gen_ndr/cli_spoolss.h"
+#include "../librpc/gen_ndr/ndr_spoolss.h"
 #include "nsswitch/libwbclient/wbclient.h"
+#include "ads.h"
+#include "libads/cldap.h"
+#include "../lib/addns/dnsquery.h"
+#include "../libds/common/flags.h"
+#include "librpc/gen_ndr/libnet_join.h"
+#include "libnet/libnet_join.h"
+#include "smb_krb5.h"
+#include "secrets.h"
+#include "krb5_env.h"
+#include "../libcli/security/security.h"
+#include "libsmb/libsmb.h"
+#include "lib/param/loadparm.h"
 
 #ifdef HAVE_ADS
 
@@ -49,7 +62,8 @@ static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
        struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
 
        print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
-       if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) {
+
+       if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
                d_fprintf(stderr, _("CLDAP query failed!\n"));
                return -1;
        }
@@ -143,7 +157,7 @@ static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
        }
 
        if (!ads->config.realm) {
-               ads->config.realm = CONST_DISCARD(char *, c->opt_target_workgroup);
+               ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
                ads->ldap.port = 389;
        }
 
@@ -372,7 +386,6 @@ int net_ads_check(struct net_context *c)
 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
 {
        ADS_STRUCT *ads;
-       char addr[INET6_ADDRSTRLEN];
        struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
 
        if (c->display_usage) {
@@ -390,12 +403,11 @@ static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
        }
 
        if (!ads->config.realm) {
-               ads->config.realm = CONST_DISCARD(char *, c->opt_target_workgroup);
+               ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
                ads->ldap.port = 389;
        }
 
-       print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
-       if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) {
+       if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
                d_fprintf(stderr, _("CLDAP query failed!\n"));
                ads_destroy(&ads);
                return -1;
@@ -430,10 +442,10 @@ static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *d
        }
        if (!values) /* must be new field, indicate string field */
                return true;
-       if (StrCaseCmp(field, "sAMAccountName") == 0) {
+       if (strcasecmp_m(field, "sAMAccountName") == 0) {
                disp_fields[0] = SMB_STRDUP((char *) values[0]);
        }
-       if (StrCaseCmp(field, "description") == 0)
+       if (strcasecmp_m(field, "description") == 0)
                disp_fields[1] = SMB_STRDUP((char *) values[0]);
        return true;
 }
@@ -475,7 +487,7 @@ static int ads_user_add(struct net_context *c, int argc, const char **argv)
        if (c->opt_container) {
                ou_str = SMB_STRDUP(c->opt_container);
        } else {
-               ou_str = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
+               ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
        }
 
        status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
@@ -539,9 +551,9 @@ static int ads_user_info(struct net_context *c, int argc, const char **argv)
        char **grouplist;
        char *primary_group;
        char *escaped_user;
-       DOM_SID primary_group_sid;
+       struct dom_sid primary_group_sid;
        uint32_t group_rid;
-       enum SID_NAME_USE type;
+       enum wbcSidType type;
 
        if (argc < 1 || c->display_usage) {
                return net_ads_user_usage(c, argc, argv);
@@ -596,7 +608,7 @@ static int ads_user_info(struct net_context *c, int argc, const char **argv)
        wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
                                  NULL, /* don't look up domain */
                                  &primary_group,
-                                 (enum wbcSidType *) &type);
+                                 &type);
        if (!WBC_ERROR_IS_OK(wbc_status)) {
                d_fprintf(stderr, "wbcLookupSid: %s\n",
                          wbcErrorString(wbc_status));
@@ -769,7 +781,7 @@ static int ads_group_add(struct net_context *c, int argc, const char **argv)
        if (c->opt_container) {
                ou_str = SMB_STRDUP(c->opt_container);
        } else {
-               ou_str = ads_default_ou_string(ads, WELL_KNOWN_GUID_USERS);
+               ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
        }
 
        status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
@@ -904,7 +916,7 @@ static int net_ads_status(struct net_context *c, int argc, const char **argv)
                return -1;
        }
 
-       rc = ads_find_machine_acct(ads, &res, global_myname());
+       rc = ads_find_machine_acct(ads, &res, lp_netbios_name());
        if (!ADS_ERR_OK(rc)) {
                d_fprintf(stderr, _("ads_find_machine_acct: %s\n"), ads_errstr(rc));
                ads_destroy(&ads);
@@ -912,7 +924,7 @@ static int net_ads_status(struct net_context *c, int argc, const char **argv)
        }
 
        if (ads_count_replies(ads, res) == 0) {
-               d_fprintf(stderr, _("No machine account for '%s' found\n"), global_myname());
+               d_fprintf(stderr, _("No machine account for '%s' found\n"), lp_netbios_name());
                ads_destroy(&ads);
                return -1;
        }
@@ -958,6 +970,12 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv)
                use_in_memory_ccache();
        }
 
+       if (!c->msg_ctx) {
+               d_fprintf(stderr, _("Could not initialise message context. "
+                       "Try running as root\n"));
+               return -1;
+       }
+
        werr = libnet_init_UnjoinCtx(ctx, &r);
        if (!W_ERROR_IS_OK(werr)) {
                d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
@@ -977,6 +995,7 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv)
        r->in.unjoin_flags      = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
                                  WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
        r->in.delete_machine_account = true;
+       r->in.msg_ctx           = c->msg_ctx;
 
        werr = libnet_Unjoin(ctx, r);
        if (!W_ERROR_IS_OK(werr)) {
@@ -1000,7 +1019,7 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv)
                goto done;
        }
 
-       /* Based on what we requseted, we shouldn't get here, but if
+       /* Based on what we requested, we shouldn't get here, but if
           we did, it means the secrets were removed, and therefore
           we have left the domain */
        d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
@@ -1082,10 +1101,10 @@ static WERROR check_ads_config( void )
                return WERR_INVALID_DOMAIN_ROLE;
        }
 
-       if (strlen(global_myname()) > 15) {
+       if (strlen(lp_netbios_name()) > 15) {
                d_printf(_("Our netbios name can be at most 15 chars long, "
-                          "\"%s\" is %u chars long\n"), global_myname(),
-                        (unsigned int)strlen(global_myname()));
+                          "\"%s\" is %u chars long\n"), lp_netbios_name(),
+                        (unsigned int)strlen(lp_netbios_name()));
                return WERR_INVALID_COMPUTERNAME;
        }
 
@@ -1103,7 +1122,7 @@ static WERROR check_ads_config( void )
 *******************************************************************/
 
 #if defined(WITH_DNS_UPDATES)
-#include "dns.h"
+#include "../lib/addns/dns.h"
 DNS_ERROR DoDNSUpdate(char *pszServerName,
                      const char *pszDomainName, const char *pszHostName,
                      const struct sockaddr_storage *sslist,
@@ -1115,10 +1134,11 @@ static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
                                        int num_addrs)
 {
        struct dns_rr_ns *nameservers = NULL;
-       int ns_count = 0;
+       int ns_count = 0, i;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        DNS_ERROR dns_err;
        fstring dns_server;
+       const char *dns_hosts_file;
        const char *dnsdomain = NULL;
        char *root_domain = NULL;
 
@@ -1130,7 +1150,9 @@ static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
        }
        dnsdomain++;
 
-       status = ads_dns_lookup_ns( ctx, dnsdomain, &nameservers, &ns_count );
+       dns_hosts_file = lp_parm_const_string(-1, "resolv", "host file", NULL);
+       status = ads_dns_lookup_ns(ctx, dns_hosts_file,
+                                  dnsdomain, &nameservers, &ns_count);
        if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
                /* Child domains often do not have NS records.  Look
                   for the NS record for the forest root domain
@@ -1168,7 +1190,8 @@ static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
 
                /* try again for NS servers */
 
-               status = ads_dns_lookup_ns( ctx, root_domain, &nameservers, &ns_count );
+               status = ads_dns_lookup_ns(ctx, dns_hosts_file, root_domain,
+                                          &nameservers, &ns_count);
 
                if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
                        DEBUG(3,("net_ads_join: Failed to find name server for the %s "
@@ -1180,14 +1203,33 @@ static NTSTATUS net_update_dns_internal(TALLOC_CTX *ctx, ADS_STRUCT *ads,
 
        }
 
-       /* Now perform the dns update - we'll try non-secure and if we fail,
-          we'll follow it up with a secure update */
+       for (i=0; i < ns_count; i++) {
+
+               status = NT_STATUS_UNSUCCESSFUL;
+
+               /* Now perform the dns update - we'll try non-secure and if we fail,
+                  we'll follow it up with a secure update */
+
+               fstrcpy( dns_server, nameservers[i].hostname );
+
+               dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs);
+               if (ERR_DNS_IS_OK(dns_err)) {
+                       status = NT_STATUS_OK;
+                       goto done;
+               }
 
-       fstrcpy( dns_server, nameservers[0].hostname );
+               if (ERR_DNS_EQUAL(dns_err, ERROR_DNS_INVALID_NAME_SERVER) ||
+                   ERR_DNS_EQUAL(dns_err, ERROR_DNS_CONNECTION_FAILED) ||
+                   ERR_DNS_EQUAL(dns_err, ERROR_DNS_SOCKET_ERROR)) {
+                       DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
+                               dns_errstr(dns_err)));
+                       continue;
+               }
 
-       dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs);
-       if (!ERR_DNS_IS_OK(dns_err)) {
+               d_printf(_("DNS Update for %s failed: %s\n"),
+                       machine_name, dns_errstr(dns_err));
                status = NT_STATUS_UNSUCCESSFUL;
+               goto done;
        }
 
 done:
@@ -1197,29 +1239,48 @@ done:
        return status;
 }
 
-static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads)
+static NTSTATUS net_update_dns_ext(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
+                                  const char *hostname,
+                                  struct sockaddr_storage *iplist,
+                                  int num_addrs)
 {
-       int num_addrs;
-       struct sockaddr_storage *iplist = NULL;
+       struct sockaddr_storage *iplist_alloc = NULL;
        fstring machine_name;
        NTSTATUS status;
 
-       name_to_fqdn( machine_name, global_myname() );
+       if (hostname) {
+               fstrcpy(machine_name, hostname);
+       } else {
+               name_to_fqdn( machine_name, lp_netbios_name() );
+       }
        strlower_m( machine_name );
 
-       /* Get our ip address (not the 127.0.0.x address but a real ip
-        * address) */
-
-       num_addrs = get_my_ip_address( &iplist );
-       if ( num_addrs <= 0 ) {
-               DEBUG(4,("net_update_dns: Failed to find my non-loopback IP "
-                        "addresses!\n"));
-               return NT_STATUS_INVALID_PARAMETER;
+       if (num_addrs == 0 || iplist == NULL) {
+               /*
+                * Get our ip address
+                * (not the 127.0.0.x address but a real ip address)
+                */
+               num_addrs = get_my_ip_address(&iplist_alloc);
+               if ( num_addrs <= 0 ) {
+                       DEBUG(4, ("net_update_dns_ext: Failed to find my "
+                                 "non-loopback IP addresses!\n"));
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+               iplist = iplist_alloc;
        }
 
        status = net_update_dns_internal(mem_ctx, ads, machine_name,
                                         iplist, num_addrs);
-       SAFE_FREE( iplist );
+
+       SAFE_FREE(iplist_alloc);
+       return status;
+}
+
+static NTSTATUS net_update_dns(TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
+{
+       NTSTATUS status;
+
+       status = net_update_dns_ext(mem_ctx, ads, hostname, NULL, 0);
        return status;
 }
 #endif
@@ -1248,8 +1309,91 @@ static int net_ads_join_usage(struct net_context *c, int argc, const char **argv
        return -1;
 }
 
-/*******************************************************************
- ********************************************************************/
+
+static void _net_ads_join_dns_updates(TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
+{
+#if defined(WITH_DNS_UPDATES)
+       ADS_STRUCT *ads_dns = NULL;
+       int ret;
+       NTSTATUS status;
+
+       /*
+        * In a clustered environment, don't do dynamic dns updates:
+        * Registering the set of ip addresses that are assigned to
+        * the interfaces of the node that performs the join does usually
+        * not have the desired effect, since the local interfaces do not
+        * carry the complete set of the cluster's public IP addresses.
+        * And it can also contain internal addresses that should not
+        * be visible to the outside at all.
+        * In order to do dns updates in a clustererd setup, use
+        * net ads dns register.
+        */
+       if (lp_clustering()) {
+               d_fprintf(stderr, _("Not doing automatic DNS update in a "
+                                   "clustered setup.\n"));
+               return;
+       }
+
+       if (!r->out.domain_is_ad) {
+               return;
+       }
+
+       /*
+        * We enter this block with user creds.
+        * kinit with the machine password to do dns update.
+        */
+
+       ads_dns = ads_init(lp_realm(), NULL, r->in.dc_name);
+
+       if (ads_dns == NULL) {
+               d_fprintf(stderr, _("DNS update failed: out of memory!\n"));
+               goto done;
+       }
+
+       use_in_memory_ccache();
+
+       ret = asprintf(&ads_dns->auth.user_name, "%s$", lp_netbios_name());
+       if (ret == -1) {
+               d_fprintf(stderr, _("DNS update failed: out of memory\n"));
+               goto done;
+       }
+
+       ads_dns->auth.password = secrets_fetch_machine_password(
+               r->out.netbios_domain_name, NULL, NULL);
+       if (ads_dns->auth.password == NULL) {
+               d_fprintf(stderr, _("DNS update failed: out of memory\n"));
+               goto done;
+       }
+
+       ads_dns->auth.realm = SMB_STRDUP(r->out.dns_domain_name);
+       if (ads_dns->auth.realm == NULL) {
+               d_fprintf(stderr, _("DNS update failed: out of memory\n"));
+               goto done;
+       }
+
+       strupper_m(ads_dns->auth.realm);
+
+       ret = ads_kinit_password(ads_dns);
+       if (ret != 0) {
+               d_fprintf(stderr,
+                         _("DNS update failed: kinit failed: %s\n"),
+                         error_message(ret));
+               goto done;
+       }
+
+       status = net_update_dns(ctx, ads_dns, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf( stderr, _("DNS update failed: %s\n"),
+                         nt_errstr(status));
+       }
+
+done:
+       ads_destroy(&ads_dns);
+#endif
+
+       return;
+}
+
 
 int net_ads_join(struct net_context *c, int argc, const char **argv)
 {
@@ -1295,25 +1439,25 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
        /* process additional command line args */
 
        for ( i=0; i<argc; i++ ) {
-               if ( !StrnCaseCmp(argv[i], "createupn", strlen("createupn")) ) {
+               if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
                        createupn = true;
                        machineupn = get_string_param(argv[i]);
                }
-               else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
+               else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
                        if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
                                d_fprintf(stderr, _("Please supply a valid OU path.\n"));
                                werr = WERR_INVALID_PARAM;
                                goto fail;
                        }
                }
-               else if ( !StrnCaseCmp(argv[i], "osName", strlen("osName")) ) {
+               else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
                        if ( (os_name = get_string_param(argv[i])) == NULL ) {
                                d_fprintf(stderr, _("Please supply a operating system name.\n"));
                                werr = WERR_INVALID_PARAM;
                                goto fail;
                        }
                }
-               else if ( !StrnCaseCmp(argv[i], "osVer", strlen("osVer")) ) {
+               else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
                        if ( (os_version = get_string_param(argv[i])) == NULL ) {
                                d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
                                werr = WERR_INVALID_PARAM;
@@ -1331,6 +1475,13 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
                goto fail;
        }
 
+       if (!c->msg_ctx) {
+               d_fprintf(stderr, _("Could not initialise message context. "
+                       "Try running as root\n"));
+               werr = WERR_ACCESS_DENIED;
+               goto fail;
+       }
+
        /* Do the domain join here */
 
        r->in.domain_name       = domain;
@@ -1348,8 +1499,14 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
        r->in.join_flags        = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
                                  WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
                                  WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
+       r->in.msg_ctx           = c->msg_ctx;
 
        werr = libnet_Join(ctx, r);
+       if (W_ERROR_EQUAL(werr, WERR_DCNOTFOUND) &&
+           strequal(domain, lp_realm())) {
+               r->in.domain_name = lp_workgroup();
+               werr = libnet_Join(ctx, r);
+       }
        if (!W_ERROR_IS_OK(werr)) {
                goto fail;
        }
@@ -1375,33 +1532,13 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
                        r->out.netbios_domain_name);
        }
 
-#if defined(WITH_DNS_UPDATES)
-       if (r->out.domain_is_ad) {
-               /* We enter this block with user creds */
-               ADS_STRUCT *ads_dns = NULL;
-
-               if ( (ads_dns = ads_init( lp_realm(), NULL, NULL )) != NULL ) {
-                       /* kinit with the machine password */
-
-                       use_in_memory_ccache();
-                       if (asprintf( &ads_dns->auth.user_name, "%s$", global_myname()) == -1) {
-                               goto fail;
-                       }
-                       ads_dns->auth.password = secrets_fetch_machine_password(
-                               r->out.netbios_domain_name, NULL, NULL );
-                       ads_dns->auth.realm = SMB_STRDUP( r->out.dns_domain_name );
-                       strupper_m(ads_dns->auth.realm );
-                       ads_kinit_password( ads_dns );
-               }
-
-               if ( !ads_dns || !NT_STATUS_IS_OK(net_update_dns( ctx, ads_dns )) ) {
-                       d_fprintf( stderr, _("DNS update failed!\n") );
-               }
+       /*
+        * We try doing the dns update (if it was compiled in).
+        * If the dns update fails, we still consider the join
+        * operation as succeeded if we came this far.
+        */
+       _net_ads_join_dns_updates(ctx, r);
 
-               /* exit from this block using machine creds */
-               ads_destroy(&ads_dns);
-       }
-#endif
        TALLOC_FREE(r);
        TALLOC_FREE( ctx );
 
@@ -1425,15 +1562,28 @@ static int net_ads_dns_register(struct net_context *c, int argc, const char **ar
 #if defined(WITH_DNS_UPDATES)
        ADS_STRUCT *ads;
        ADS_STATUS status;
+       NTSTATUS ntstatus;
        TALLOC_CTX *ctx;
+       const char *hostname = NULL;
+       const char **addrs_list = NULL;
+       struct sockaddr_storage *addrs = NULL;
+       int num_addrs = 0;
+       int count;
 
 #ifdef DEVELOPER
        talloc_enable_leak_report();
 #endif
 
-       if (argc > 0 || c->display_usage) {
+       if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
+               d_fprintf(stderr, _("Refusing DNS updates with automatic "
+                                   "detection of addresses in a clustered "
+                                   "setup.\n"));
+               c->display_usage = true;
+       }
+
+       if (c->display_usage) {
                d_printf(  "%s\n"
-                          "net ads dns register\n"
+                          "net ads dns register [hostname [IP [IP...]]]\n"
                           "    %s\n",
                         _("Usage:"),
                         _("Register hostname with DNS\n"));
@@ -1445,6 +1595,37 @@ static int net_ads_dns_register(struct net_context *c, int argc, const char **ar
                return -1;
        }
 
+       if (argc >= 1) {
+               hostname = argv[0];
+       }
+
+       if (argc > 1) {
+               num_addrs = argc - 1;
+               addrs_list = &argv[1];
+       } else if (lp_clustering()) {
+               addrs_list = lp_cluster_addresses();
+               num_addrs = str_list_length(addrs_list);
+       }
+
+       if (num_addrs > 0) {
+               addrs = talloc_zero_array(ctx, struct sockaddr_storage, num_addrs);
+               if (addrs == NULL) {
+                       d_fprintf(stderr, _("Error allocating memory!\n"));
+                       talloc_free(ctx);
+                       return -1;
+               }
+       }
+
+       for (count = 0; count < num_addrs; count++) {
+               if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
+                       d_fprintf(stderr, "%s '%s'.\n",
+                                         _("Cannot interpret address"),
+                                         addrs_list[count]);
+                       talloc_free(ctx);
+                       return -1;
+               }
+       }
+
        status = ads_startup(c, true, &ads);
        if ( !ADS_ERR_OK(status) ) {
                DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
@@ -1452,7 +1633,8 @@ static int net_ads_dns_register(struct net_context *c, int argc, const char **ar
                return -1;
        }
 
-       if ( !NT_STATUS_IS_OK(net_update_dns(ctx, ads)) ) {
+       ntstatus = net_update_dns_ext(ctx, ads, hostname, addrs, num_addrs);
+       if (!NT_STATUS_IS_OK(ntstatus)) {
                d_fprintf( stderr, _("DNS update failed!\n") );
                ads_destroy( &ads );
                TALLOC_FREE( ctx );
@@ -1499,7 +1681,8 @@ static int net_ads_dns_gethostbyname(struct net_context *c, int argc, const char
 
        err = do_gethostbyname(argv[0], argv[1]);
 
-       d_printf(_("do_gethostbyname returned %d\n"), ERROR_DNS_V(err));
+       d_printf(_("do_gethostbyname returned %s (%d)\n"),
+               dns_errstr(err), ERROR_DNS_V(err));
 #endif
        return 0;
 }
@@ -1623,7 +1806,7 @@ static int net_ads_printer_info(struct net_context *c, int argc, const char **ar
        if (argc > 1) {
                servername =  argv[1];
        } else {
-               servername = global_myname();
+               servername = lp_netbios_name();
        }
 
        rc = ads_find_printer_on_server(ads, &res, printername, servername);
@@ -1686,23 +1869,23 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char *
        if (argc == 2) {
                servername = argv[1];
        } else {
-               servername = global_myname();
+               servername = lp_netbios_name();
        }
 
        /* Get printer data from SPOOLSS */
 
        resolve_name(servername, &server_ss, 0x20, false);
 
-       nt_status = cli_full_connection(&cli, global_myname(), servername,
+       nt_status = cli_full_connection(&cli, lp_netbios_name(), servername,
                                        &server_ss, 0,
                                        "IPC$", "IPC",
                                        c->opt_user_name, c->opt_workgroup,
                                        c->opt_password ? c->opt_password : "",
                                        CLI_FULL_CONNECTION_USE_KERBEROS,
-                                       Undefined, NULL);
+                                       SMB_SIGNING_DEFAULT);
 
        if (NT_STATUS_IS_ERR(nt_status)) {
-               d_fprintf(stderr, _("Unable to open a connnection to %s to "
+               d_fprintf(stderr, _("Unable to open a connection to %s to "
                                    "obtain data for %s\n"),
                          servername, printername);
                ads_destroy(&ads);
@@ -1751,7 +1934,7 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char *
 
        nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss.syntax_id, &pipe_hnd);
        if (!NT_STATUS_IS_OK(nt_status)) {
-               d_fprintf(stderr, _("Unable to open a connnection to the spoolss pipe on %s\n"),
+               d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
                         servername);
                SAFE_FREE(prt_dn);
                ads_destroy(&ads);
@@ -1809,7 +1992,7 @@ static int net_ads_printer_remove(struct net_context *c, int argc, const char **
        if (argc > 1) {
                servername = argv[1];
        } else {
-               servername = global_myname();
+               servername = lp_netbios_name();
        }
 
        rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
@@ -1890,8 +2073,8 @@ static int net_ads_password(struct net_context *c, int argc, const char **argv)
        ADS_STRUCT *ads;
        const char *auth_principal = c->opt_user_name;
        const char *auth_password = c->opt_password;
-       char *realm = NULL;
-       char *new_password = NULL;
+       const char *realm = NULL;
+       const char *new_password = NULL;
        char *chr, *prompt;
        const char *user;
        ADS_STATUS ret;
@@ -1950,7 +2133,7 @@ static int net_ads_password(struct net_context *c, int argc, const char **argv)
        }
 
        if (argv[1]) {
-               new_password = (char *)argv[1];
+               new_password = (const char *)argv[1];
        } else {
                if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) {
                        return -1;
@@ -2002,7 +2185,7 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
                return -1;
        }
 
-       fstrcpy(my_name, global_myname());
+       fstrcpy(my_name, lp_netbios_name());
        strlower_m(my_name);
        if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
                ads_destroy(&ads);
@@ -2073,7 +2256,7 @@ static int net_ads_search(struct net_context *c, int argc, const char **argv)
        ldap_exp = argv[0];
        attrs = (argv + 1);
 
-       rc = ads_do_search_all(ads, ads->config.bind_path,
+       rc = ads_do_search_retry(ads, ads->config.bind_path,
                               LDAP_SCOPE_SUBTREE,
                               ldap_exp, attrs, &res);
        if (!ADS_ERR_OK(rc)) {
@@ -2181,7 +2364,7 @@ static int net_ads_sid(struct net_context *c, int argc, const char **argv)
        const char *sid_string;
        const char **attrs;
        LDAPMessage *res = NULL;
-       DOM_SID sid;
+       struct dom_sid sid;
 
        if (argc < 1 || c->display_usage) {
                return net_ads_sid_usage(c, argc, argv);
@@ -2708,6 +2891,11 @@ int net_ads_group(struct net_context *c, int argc, const char **argv)
        return net_ads_noads();
 }
 
+int net_ads_gpo(struct net_context *c, int argc, const char **argv)
+{
+       return net_ads_noads();
+}
+
 /* this one shouldn't display a message */
 int net_ads_check(struct net_context *c)
 {
@@ -2724,4 +2912,4 @@ int net_ads(struct net_context *c, int argc, const char **argv)
        return net_ads_noads();
 }
 
-#endif /* WITH_ADS */
+#endif /* HAVE_ADS */