s3:utils: Fix code spelling
[samba.git] / source3 / utils / net_ads.c
index 863bccb2cf1cada7177c47fe9dec932acfb090da..4f3d754a095c54fb1e00cde15305f4c98a3c8d90 100644 (file)
@@ -232,6 +232,36 @@ static int net_ads_cldap_netlogon_json
                goto failure;
        }
 
+       ret = json_add_bool(&flagsobj, "Runs on Windows 2012R2 or later",
+                           reply->server_type & NBT_SERVER_DS_9);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_bool(&flagsobj, "Runs on Windows 2016 or later",
+                           reply->server_type & NBT_SERVER_DS_10);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_bool(&flagsobj, "Has a DNS name",
+                           reply->server_type & NBT_SERVER_HAS_DNS_NAME);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_bool(&flagsobj, "Is a default NC",
+                           reply->server_type & NBT_SERVER_IS_DEFAULT_NC);
+       if (ret != 0) {
+               goto failure;
+       }
+
+       ret = json_add_bool(&flagsobj, "Is the forest root",
+                           reply->server_type & NBT_SERVER_FOREST_ROOT);
+       if (ret != 0) {
+               goto failure;
+       }
+
        ret = json_add_string(&jsobj, "Forest", reply->forest);
        if (ret != 0) {
                goto failure;
@@ -372,7 +402,12 @@ static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
                   "\tIs NT6 DC that has some secrets:            %s\n"
                   "\tIs NT6 DC that has all secrets:             %s\n"
                   "\tRuns Active Directory Web Services:         %s\n"
-                  "\tRuns on Windows 2012 or later:              %s\n"),
+                  "\tRuns on Windows 2012 or later:              %s\n"
+                  "\tRuns on Windows 2012R2 or later:            %s\n"
+                  "\tRuns on Windows 2016 or later:              %s\n"
+                  "\tHas a DNS name:                             %s\n"
+                  "\tIs a default NC:                            %s\n"
+                  "\tIs the forest root:                         %s\n"),
                   (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
                   (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
                   (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
@@ -386,7 +421,12 @@ static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
                   (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
                   (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"),
                   (reply.server_type & NBT_SERVER_ADS_WEB_SERVICE) ? _("yes") : _("no"),
-                  (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"));
+                  (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"),
+                  (reply.server_type & NBT_SERVER_DS_9) ? _("yes") : _("no"),
+                  (reply.server_type & NBT_SERVER_DS_10) ? _("yes") : _("no"),
+                  (reply.server_type & NBT_SERVER_HAS_DNS_NAME) ? _("yes") : _("no"),
+                  (reply.server_type & NBT_SERVER_IS_DEFAULT_NC) ? _("yes") : _("no"),
+                  (reply.server_type & NBT_SERVER_FOREST_ROOT) ? _("yes") : _("no"));
 
 
        printf(_("Forest: %s\n"), reply.forest);
@@ -426,7 +466,7 @@ static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
                         _("Usage:"),
                         _("Find the ADS DC using CLDAP lookup.\n"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
        status = ads_startup_nobind(c, false, tmp_ctx, &ads);
@@ -436,13 +476,16 @@ static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
        }
 
        if (!ads->config.realm) {
-               ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
+               ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
+               if (ads->config.realm == NULL) {
+                       d_fprintf(stderr, _("Out of memory\n"));
+                       goto out;
+               }
                ads->ldap.port = 389;
        }
 
        ret = net_ads_cldap_netlogon(c, ads);
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -552,7 +595,7 @@ static int net_ads_info(struct net_context *c, int argc, const char **argv)
                         _("Display information about an Active Directory "
                           "server.\n"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
        status = ads_startup_nobind(c, false, tmp_ctx, &ads);
@@ -598,13 +641,15 @@ static int net_ads_info(struct net_context *c, int argc, const char **argv)
 
        ret = 0;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
 
-static ADS_STATUS ads_startup_int(struct net_context *c, bool only_own_domain,
-                                 uint32_t auth_flags, ADS_STRUCT **ads_ret)
+static ADS_STATUS ads_startup_int(struct net_context *c,
+                                 bool only_own_domain,
+                                 uint32_t auth_flags,
+                                 TALLOC_CTX *mem_ctx,
+                                 ADS_STRUCT **ads_ret)
 {
        ADS_STRUCT *ads = NULL;
        ADS_STATUS status;
@@ -630,10 +675,14 @@ retry_connect:
                realm = assume_own_realm(c);
        }
 
-       ads = ads_init(realm,
-                       c->opt_target_workgroup,
-                       c->opt_host,
-                       ADS_SASL_PLAIN);
+       ads = ads_init(mem_ctx,
+                      realm,
+                      c->opt_target_workgroup,
+                      c->opt_host,
+                      ADS_SASL_PLAIN);
+       if (ads == NULL) {
+               return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+       }
 
        if (!c->opt_user_name) {
                c->opt_user_name = "administrator";
@@ -647,19 +696,27 @@ retry:
        if (!c->opt_password && need_password && !c->opt_machine_pass) {
                c->opt_password = net_prompt_pass(c, c->opt_user_name);
                if (!c->opt_password) {
-                       ads_destroy(&ads);
+                       TALLOC_FREE(ads);
                        return ADS_ERROR(LDAP_NO_MEMORY);
                }
        }
 
        if (c->opt_password) {
                use_in_memory_ccache();
-               SAFE_FREE(ads->auth.password);
-               ads->auth.password = smb_xstrdup(c->opt_password);
+               ADS_TALLOC_CONST_FREE(ads->auth.password);
+               ads->auth.password = talloc_strdup(ads, c->opt_password);
+               if (ads->auth.password == NULL) {
+                       TALLOC_FREE(ads);
+                       return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+               }
        }
 
-       SAFE_FREE(ads->auth.user_name);
-       ads->auth.user_name = smb_xstrdup(c->opt_user_name);
+       ADS_TALLOC_CONST_FREE(ads->auth.user_name);
+       ads->auth.user_name = talloc_strdup(ads, c->opt_user_name);
+       if (ads->auth.user_name == NULL) {
+               TALLOC_FREE(ads);
+               return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+       }
 
        ads->auth.flags |= auth_flags;
 
@@ -687,13 +744,23 @@ retry:
         */
        if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
                *cp++ = '\0';
-               SAFE_FREE(ads->auth.realm);
-               ads->auth.realm = smb_xstrdup(cp);
-               if (!strupper_m(ads->auth.realm)) {
-                       ads_destroy(&ads);
+               ADS_TALLOC_CONST_FREE(ads->auth.realm);
+               ads->auth.realm = talloc_asprintf_strupper_m(ads, "%s", cp);
+               if (ads->auth.realm == NULL) {
+                       TALLOC_FREE(ads);
                        return ADS_ERROR(LDAP_NO_MEMORY);
                }
-       }
+       } else if (ads->auth.realm == NULL) {
+               const char *c_realm = cli_credentials_get_realm(c->creds);
+
+               if (c_realm != NULL) {
+                       ads->auth.realm = talloc_strdup(ads, c_realm);
+                       if (ads->auth.realm == NULL) {
+                               TALLOC_FREE(ads);
+                               return ADS_ERROR(LDAP_NO_MEMORY);
+                       }
+               }
+       }
 
        status = ads_connect(ads);
 
@@ -702,7 +769,7 @@ retry:
                if (NT_STATUS_EQUAL(ads_ntstatus(status),
                                    NT_STATUS_NO_LOGON_SERVERS)) {
                        DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
-                       ads_destroy(&ads);
+                       TALLOC_FREE(ads);
                        return status;
                }
 
@@ -711,7 +778,7 @@ retry:
                        second_time = true;
                        goto retry;
                } else {
-                       ads_destroy(&ads);
+                       TALLOC_FREE(ads);
                        return status;
                }
        }
@@ -729,20 +796,22 @@ retry:
                        namecache_delete(ads->server.realm, 0x1C);
                        namecache_delete(ads->server.workgroup, 0x1C);
 
-                       ads_destroy(&ads);
-                       ads = NULL;
+                       TALLOC_FREE(ads);
 
                        goto retry_connect;
                }
        }
 
-       *ads_ret = ads;
+       *ads_ret = talloc_move(mem_ctx, &ads);
        return status;
 }
 
-ADS_STATUS ads_startup(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
+ADS_STATUS ads_startup(struct net_context *c,
+                      bool only_own_domain,
+                      TALLOC_CTX *mem_ctx,
+                      ADS_STRUCT **ads)
 {
-       return ads_startup_int(c, only_own_domain, 0, ads);
+       return ads_startup_int(c, only_own_domain, 0, mem_ctx, ads);
 }
 
 ADS_STATUS ads_startup_nobind(struct net_context *c,
@@ -750,7 +819,11 @@ ADS_STATUS ads_startup_nobind(struct net_context *c,
                              TALLOC_CTX *mem_ctx,
                              ADS_STRUCT **ads)
 {
-       return ads_startup_int(c, only_own_domain, ADS_AUTH_NO_BIND, ads);
+       return ads_startup_int(c,
+                              only_own_domain,
+                              ADS_AUTH_NO_BIND,
+                              mem_ctx,
+                              ads);
 }
 
 /*
@@ -758,35 +831,42 @@ ADS_STATUS ads_startup_nobind(struct net_context *c,
   ads_startup() stores the password in opt_password if it needs to so
   that rpc or rap can use it without re-prompting.
 */
-static int net_ads_check_int(const char *realm, const char *workgroup, const char *host)
+static int net_ads_check_int(struct net_context *c,
+                            const char *realm,
+                            const char *workgroup,
+                            const char *host)
 {
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
        ADS_STRUCT *ads;
        ADS_STATUS status;
+       int ret = -1;
 
-       ads = ads_init(realm, workgroup, host, ADS_SASL_PLAIN);
-       if (ads == NULL ) {
-               return -1;
+       ads = ads_init(tmp_ctx, realm, workgroup, host, ADS_SASL_PLAIN);
+       if (ads == NULL) {
+               goto out;
        }
 
        ads->auth.flags |= ADS_AUTH_NO_BIND;
 
         status = ads_connect(ads);
         if ( !ADS_ERR_OK(status) ) {
-                return -1;
+                goto out;
         }
 
-       ads_destroy(&ads);
-       return 0;
+       ret = 0;
+out:
+       TALLOC_FREE(tmp_ctx);
+       return ret;
 }
 
 int net_ads_check_our_domain(struct net_context *c)
 {
-       return net_ads_check_int(lp_realm(), lp_workgroup(), NULL);
+       return net_ads_check_int(c, lp_realm(), lp_workgroup(), NULL);
 }
 
 int net_ads_check(struct net_context *c)
 {
-       return net_ads_check_int(NULL, c->opt_workgroup, c->opt_host);
+       return net_ads_check_int(c, NULL, c->opt_workgroup, c->opt_host);
 }
 
 /*
@@ -808,7 +888,7 @@ static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
                         _("Usage:"),
                         _("Print the workgroup name"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
        status = ads_startup_nobind(c, false, tmp_ctx, &ads);
@@ -818,7 +898,11 @@ static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
        }
 
        if (!ads->config.realm) {
-               ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
+               ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
+               if (ads->config.realm == NULL) {
+                       d_fprintf(stderr, _("Out of memory\n"));
+                       goto out;
+               }
                ads->ldap.port = 389;
        }
 
@@ -833,7 +917,6 @@ static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
 
        ret = 0;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
 
        return ret;
@@ -889,7 +972,7 @@ static int ads_user_add(struct net_context *c, int argc, const char **argv)
                return net_ads_user_usage(c, argc, argv);
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto done;
        }
@@ -961,7 +1044,6 @@ static int ads_user_add(struct net_context *c, int argc, const char **argv)
 
  done:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        SAFE_FREE(ou_str);
        TALLOC_FREE(tmp_ctx);
        return rc;
@@ -997,7 +1079,7 @@ static int ads_user_info(struct net_context *c, int argc, const char **argv)
                goto out;
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -1059,7 +1141,6 @@ static int ads_user_info(struct net_context *c, int argc, const char **argv)
        ret = 0;
 out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -1078,7 +1159,7 @@ static int ads_user_delete(struct net_context *c, int argc, const char **argv)
                return net_ads_user_usage(c, argc, argv);
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -1106,7 +1187,6 @@ static int ads_user_delete(struct net_context *c, int argc, const char **argv)
        ret = 0;
 out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -1161,10 +1241,10 @@ int net_ads_user(struct net_context *c, int argc, const char **argv)
                         _("List AD users"));
                net_display_usage_from_functable(func);
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -1187,7 +1267,6 @@ int net_ads_user(struct net_context *c, int argc, const char **argv)
 
        ret = 0;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -1211,7 +1290,7 @@ static int ads_group_add(struct net_context *c, int argc, const char **argv)
                return net_ads_group_usage(c, argc, argv);
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -1245,7 +1324,6 @@ static int ads_group_add(struct net_context *c, int argc, const char **argv)
        ret = 0;
  out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        SAFE_FREE(ou_str);
        TALLOC_FREE(tmp_ctx);
        return ret;
@@ -1265,7 +1343,7 @@ static int ads_group_delete(struct net_context *c, int argc, const char **argv)
                return net_ads_group_usage(c, argc, argv);
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -1292,7 +1370,6 @@ static int ads_group_delete(struct net_context *c, int argc, const char **argv)
        ret = 0;
 out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -1339,10 +1416,10 @@ int net_ads_group(struct net_context *c, int argc, const char **argv)
                         _("List AD groups"));
                net_display_usage_from_functable(func);
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -1365,7 +1442,6 @@ int net_ads_group(struct net_context *c, int argc, const char **argv)
 
        ret = 0;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -1385,10 +1461,12 @@ static int net_ads_status(struct net_context *c, int argc, const char **argv)
                         _("Usage:"),
                         _("Display machine account details"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
-       status = ads_startup(c, true, &ads);
+       net_warn_member_options();
+
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -1411,7 +1489,6 @@ static int net_ads_status(struct net_context *c, int argc, const char **argv)
        ret = 0;
 out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -1437,7 +1514,7 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv)
                         _("Usage:"),
                         _("Leave an AD domain"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
        if (!*lp_realm()) {
@@ -1531,18 +1608,19 @@ static ADS_STATUS net_ads_join_ok(struct net_context *c)
                return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
        }
 
+       net_warn_member_options();
+
        net_use_krb_machine_account(c);
 
        get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
 
        status = ADS_ERROR_NT(NT_STATUS_OK);
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return  status;
 }
@@ -1561,9 +1639,11 @@ int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
                           "    %s\n",
                         _("Usage:"),
                         _("Test if the existing join is ok"));
-               return 0;
+               return -1;
        }
 
+       net_warn_member_options();
+
        /* Display success or failure */
        status = net_ads_join_ok(c);
        if (!ADS_ERR_OK(status)) {
@@ -1661,6 +1741,8 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
                return net_ads_join_usage(c, argc, argv);
        }
 
+       net_warn_member_options();
+
        if (!modify_config) {
                werr = check_ads_config();
                if (!W_ERROR_IS_OK(werr)) {
@@ -1860,7 +1942,8 @@ static int net_ads_dns_register(struct net_context *c, int argc, const char **ar
 
        if (c->display_usage) {
                d_printf(  "%s\n"
-                          "net ads dns register [hostname [IP [IP...]]]\n"
+                          "net ads dns register [hostname [IP [IP...]]] "
+                          "[--force] [--dns-ttl TTL]\n"
                           "    %s\n",
                         _("Usage:"),
                         _("Register hostname with DNS\n"));
@@ -1899,7 +1982,7 @@ static int net_ads_dns_register(struct net_context *c, int argc, const char **ar
                }
        }
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if ( !ADS_ERR_OK(status) ) {
                DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
                goto out;
@@ -1921,7 +2004,6 @@ static int net_ads_dns_register(struct net_context *c, int argc, const char **ar
 
        ret = 0;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
 
        return ret;
@@ -1957,7 +2039,7 @@ static int net_ads_dns_unregister(struct net_context *c,
                           "net ads dns unregister [hostname]\n"
                           "    %s\n",
                         _("Usage:"),
-                        _("Remove all IP Address entires for a given\n"
+                        _("Remove all IP Address entries for a given\n"
                            "    hostname from the Active Directory server.\n"));
                TALLOC_FREE(tmp_ctx);
                return -1;
@@ -1966,7 +2048,7 @@ static int net_ads_dns_unregister(struct net_context *c,
        /* Get the hostname for un-registering */
        hostname = argv[0];
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if ( !ADS_ERR_OK(status) ) {
                DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
                goto out;
@@ -1988,7 +2070,6 @@ static int net_ads_dns_unregister(struct net_context *c,
 
        ret = 0;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
 
        return ret;
@@ -2147,10 +2228,10 @@ static int net_ads_printer_search(struct net_context *c,
                         _("Usage:"),
                         _("List printers in the AD"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -2172,7 +2253,6 @@ static int net_ads_printer_search(struct net_context *c,
        ret = 0;
 out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -2197,10 +2277,10 @@ static int net_ads_printer_info(struct net_context *c,
                           "    printername\tPrinter name or wildcard\n"
                           "    servername\tName of the print server\n"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -2234,7 +2314,6 @@ static int net_ads_printer_info(struct net_context *c,
        ret = 0;
 out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -2279,7 +2358,7 @@ static int net_ads_printer_publish(struct net_context *c,
                goto out;
        }
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -2381,7 +2460,6 @@ static int net_ads_printer_publish(struct net_context *c,
 
        ret = 0;
 out:
-       ads_destroy(&ads);
        talloc_destroy(tmp_ctx);
 
        return ret;
@@ -2410,7 +2488,7 @@ static int net_ads_printer_remove(struct net_context *c,
                return -1;
        }
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -2448,7 +2526,6 @@ static int net_ads_printer_remove(struct net_context *c,
        ret = 0;
 out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -2517,7 +2594,7 @@ static int net_ads_password(struct net_context *c, int argc, const char **argv)
                           "  Change password for user\n"
                           "    username\tName of user to change password for\n"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
        if (auth_principal == NULL || auth_password == NULL) {
@@ -2554,13 +2631,17 @@ static int net_ads_password(struct net_context *c, int argc, const char **argv)
 
        /* use the realm so we can eventually change passwords for users
        in realms other than default */
-       ads = ads_init(realm, c->opt_workgroup, c->opt_host, ADS_SASL_PLAIN);
+       ads = ads_init(tmp_ctx,
+                      realm,
+                      c->opt_workgroup,
+                      c->opt_host,
+                      ADS_SASL_PLAIN);
        if (ads == NULL) {
                goto out;
        }
 
        /* we don't actually need a full connect, but it's the easy way to
-               fill in the KDC's addresss */
+               fill in the KDC's address */
        ads_connect(ads);
 
        if (!ads->config.realm) {
@@ -2609,7 +2690,6 @@ static int net_ads_password(struct net_context *c, int argc, const char **argv)
 
        ret = 0;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -2630,7 +2710,7 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
                         _("Usage:"),
                         _("Change the machine account's trust password"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
        if (!secrets_init()) {
@@ -2638,11 +2718,13 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
                goto out;
        }
 
+       net_warn_member_options();
+
        net_use_krb_machine_account(c);
 
        use_in_memory_ccache();
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -2678,7 +2760,6 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
 
        ret = 0;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
 
        return ret;
@@ -2719,7 +2800,7 @@ static int net_ads_search(struct net_context *c, int argc, const char **argv)
                return net_ads_search_usage(c, argc, argv);
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -2746,7 +2827,6 @@ static int net_ads_search(struct net_context *c, int argc, const char **argv)
        ret = 0;
 out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -2788,7 +2868,7 @@ static int net_ads_dn(struct net_context *c, int argc, const char **argv)
                return net_ads_dn_usage(c, argc, argv);
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -2815,7 +2895,6 @@ static int net_ads_dn(struct net_context *c, int argc, const char **argv)
        ret = 0;
 out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -2856,7 +2935,7 @@ static int net_ads_sid(struct net_context *c, int argc, const char **argv)
                return net_ads_sid_usage(c, argc, argv);
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -2883,7 +2962,6 @@ static int net_ads_sid(struct net_context *c, int argc, const char **argv)
        ret = 0;
 out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -2904,21 +2982,20 @@ static int net_ads_keytab_flush(struct net_context *c,
                         _("Usage:"),
                         _("Delete the whole keytab"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
        if (!c->opt_user_specified && c->opt_password == NULL) {
                net_use_krb_machine_account(c);
        }
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
 
        ret = ads_keytab_flush(ads);
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -2942,16 +3019,18 @@ static int net_ads_keytab_add(struct net_context *c,
                           "    principal\tKerberos principal to add to "
                           "keytab\n"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
+       net_warn_member_options();
+
        d_printf(_("Processing principals to add...\n"));
 
        if (!c->opt_user_specified && c->opt_password == NULL) {
                net_use_krb_machine_account(c);
        }
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -2960,7 +3039,6 @@ static int net_ads_keytab_add(struct net_context *c,
                ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
        }
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -2979,6 +3057,48 @@ static int net_ads_keytab_add_update_ads(struct net_context *c,
        return net_ads_keytab_add(c, argc, argv, true);
 }
 
+static int net_ads_keytab_delete(struct net_context *c,
+                                int argc,
+                                const char **argv)
+{
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
+       ADS_STRUCT *ads = NULL;
+       ADS_STATUS status;
+       int i;
+       int ret = -1;
+
+       if (c->display_usage) {
+               d_printf("%s\n%s",
+                        _("Usage:"),
+                        _("net ads keytab delete <principal> [principal ...]\n"
+                          "  Remove entries for service principal, "
+                          "  from the keytab file only."
+                          "  Remove principals from local keytab\n"
+                          "    principal\tKerberos principal to remove from "
+                          "keytab\n"));
+               TALLOC_FREE(tmp_ctx);
+               return -1;
+       }
+
+       d_printf(_("Processing principals to delete...\n"));
+
+       if (!c->opt_user_specified && c->opt_password == NULL) {
+               net_use_krb_machine_account(c);
+       }
+
+       status = ads_startup(c, true, tmp_ctx, &ads);
+       if (!ADS_ERR_OK(status)) {
+               goto out;
+       }
+
+       for (ret = 0, i = 0; i < argc; i++) {
+               ret |= ads_keytab_delete_entry(ads, argv[i]);
+       }
+out:
+       TALLOC_FREE(tmp_ctx);
+       return ret;
+}
+
 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
 {
        TALLOC_CTX *tmp_ctx = talloc_stackframe();
@@ -2993,21 +3113,22 @@ static int net_ads_keytab_create(struct net_context *c, int argc, const char **a
                         _("Usage:"),
                         _("Create new default keytab"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
+       net_warn_member_options();
+
        if (!c->opt_user_specified && c->opt_password == NULL) {
                net_use_krb_machine_account(c);
        }
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
 
        ret = ads_keytab_create_default(ads);
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -3022,7 +3143,7 @@ static int net_ads_keytab_list(struct net_context *c, int argc, const char **arg
                         _("net ads keytab list [keytab]\n"
                           "  List a local keytab\n"
                           "    keytab\tKeytab to list\n"));
-               return 0;
+               return -1;
        }
 
        if (argc >= 1) {
@@ -3044,6 +3165,14 @@ int net_ads_keytab(struct net_context *c, int argc, const char **argv)
                        N_("net ads keytab add\n"
                           "    Add a service principal, updates keytab file only.")
                },
+               {
+                       "delete",
+                       net_ads_keytab_delete,
+                       NET_TRANSPORT_ADS,
+                       N_("Delete a service principal"),
+                       N_("net ads keytab delete\n"
+                          "    Remove entries for service principal, from the keytab file only.")
+               },
                {
                        "add_update_ads",
                        net_ads_keytab_add_update_ads,
@@ -3097,7 +3226,7 @@ static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **
                           "    %s\n",
                         _("Usage:"),
                         _("Renew TGT from existing credential cache"));
-               return 0;
+               return -1;
        }
 
        ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
@@ -3303,7 +3432,6 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar
 
 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
 {
-       TALLOC_CTX *mem_ctx = NULL;
        int ret = -1;
        NTSTATUS status;
 
@@ -3313,12 +3441,7 @@ static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **
                           "    %s\n",
                         _("Usage:"),
                         _("Get Ticket Granting Ticket (TGT) for the user"));
-               return 0;
-       }
-
-       mem_ctx = talloc_init("net_ads_kerberos_kinit");
-       if (!mem_ctx) {
-               goto out;
+               return -1;
        }
 
        c->opt_password = net_prompt_pass(c, c->opt_user_name);
@@ -3340,7 +3463,6 @@ static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **
                d_printf(_("failed to kinit password: %s\n"),
                        nt_errstr(status));
        }
- out:
        return ret;
 }
 
@@ -3393,10 +3515,10 @@ static int net_ads_setspn_list(struct net_context *c,
                         _("Usage:"),
                         _("net ads setspn list <machinename>\n"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -3409,7 +3531,6 @@ static int net_ads_setspn_list(struct net_context *c,
 
        ret = ok ? 0 : -1;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -3427,10 +3548,10 @@ static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv
                         _("Usage:"),
                         _("net ads setspn add <machinename> SPN\n"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -3443,7 +3564,6 @@ static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv
 
        ret = ok ? 0 : -1;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -3461,10 +3581,10 @@ static int net_ads_setspn_delete(struct net_context *c, int argc, const char **a
                         _("Usage:"),
                         _("net ads setspn delete <machinename> SPN\n"));
                TALLOC_FREE(tmp_ctx);
-               return 0;
+               return -1;
        }
 
-       status = ads_startup(c, true, &ads);
+       status = ads_startup(c, true, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
                goto out;
        }
@@ -3477,7 +3597,6 @@ static int net_ads_setspn_delete(struct net_context *c, int argc, const char **a
 
        ret = ok ? 0 : -1;
 out:
-       ads_destroy(&ads);
        TALLOC_FREE(tmp_ctx);
        return ret;
 }
@@ -3591,15 +3710,22 @@ static void net_ads_enctype_dump_enctypes(const char *username,
        printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
                enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
                ENC_HMAC_SHA1_96_AES256);
+       printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
+               enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
+               ENC_HMAC_SHA1_96_AES256_SK);
+       printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
+               enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
+               KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
 }
 
 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
 {
-       int ret = -1;
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
        ADS_STATUS status;
        ADS_STRUCT *ads = NULL;
        LDAPMessage *res = NULL;
        const char *str = NULL;
+       int ret = -1;
 
        if (c->display_usage || (argc < 1)) {
                d_printf(  "%s\n"
@@ -3607,41 +3733,41 @@ static int net_ads_enctypes_list(struct net_context *c, int argc, const char **a
                           "    %s\n",
                         _("Usage:"),
                         _("List supported enctypes"));
-               return 0;
+               TALLOC_FREE(tmp_ctx);
+               return -1;
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
-               printf("startup failed\n");
-               return ret;
+               goto out;
        }
 
        ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
        if (ret) {
-               goto done;
+               goto out;
        }
 
        net_ads_enctype_dump_enctypes(argv[0], str);
 
        ret = 0;
done:
out:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
-
+       TALLOC_FREE(tmp_ctx);
        return ret;
 }
 
 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
 {
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
        int ret = -1;
        ADS_STATUS status;
-       ADS_STRUCT *ads;
+       ADS_STRUCT *ads = NULL;
        LDAPMessage *res = NULL;
-       const char *etype_list_str;
-       const char *dn;
-       ADS_MODLIST mods;
+       const char *etype_list_str = NULL;
+       const char *dn = NULL;
+       ADS_MODLIST mods = NULL;
        uint32_t etype_list;
-       const char *str;
+       const char *str = NULL;
 
        if (c->display_usage || argc < 1) {
                d_printf(  "%s\n"
@@ -3649,13 +3775,13 @@ static int net_ads_enctypes_set(struct net_context *c, int argc, const char **ar
                           "    %s\n",
                         _("Usage:"),
                         _("Set supported enctypes"));
-               return 0;
+               TALLOC_FREE(tmp_ctx);
+               return -1;
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
-               printf("startup failed\n");
-               return ret;
+               goto done;
        }
 
        ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
@@ -3663,34 +3789,31 @@ static int net_ads_enctypes_set(struct net_context *c, int argc, const char **ar
                goto done;
        }
 
-       dn = ads_get_dn(ads, c, res);
+       dn = ads_get_dn(ads, tmp_ctx, res);
        if (dn == NULL) {
                goto done;
        }
 
-       etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5;
-#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
+       etype_list = 0;
+       etype_list |= ENC_RC4_HMAC_MD5;
        etype_list |= ENC_HMAC_SHA1_96_AES128;
-#endif
-#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
        etype_list |= ENC_HMAC_SHA1_96_AES256;
-#endif
 
        if (argv[1] != NULL) {
                sscanf(argv[1], "%i", &etype_list);
        }
 
-       etype_list_str = talloc_asprintf(c, "%d", etype_list);
+       etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
        if (!etype_list_str) {
                goto done;
        }
 
-       mods = ads_init_mods(c);
+       mods = ads_init_mods(tmp_ctx);
        if (!mods) {
                goto done;
        }
 
-       status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes",
+       status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
                             etype_list_str);
        if (!ADS_ERR_OK(status)) {
                goto done;
@@ -3704,6 +3827,7 @@ static int net_ads_enctypes_set(struct net_context *c, int argc, const char **ar
        }
 
        ads_msgfree(ads, res);
+       res = NULL;
 
        ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
        if (ret) {
@@ -3715,19 +3839,19 @@ static int net_ads_enctypes_set(struct net_context *c, int argc, const char **ar
        ret = 0;
  done:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
-
+       TALLOC_FREE(tmp_ctx);
        return ret;
 }
 
 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
 {
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
        int ret = -1;
        ADS_STATUS status;
-       ADS_STRUCT *ads;
+       ADS_STRUCT *ads = NULL;
        LDAPMessage *res = NULL;
-       const char *dn;
-       ADS_MODLIST mods;
+       const char *dn = NULL;
+       ADS_MODLIST mods = NULL;
 
        if (c->display_usage || argc < 1) {
                d_printf(  "%s\n"
@@ -3735,13 +3859,13 @@ static int net_ads_enctypes_delete(struct net_context *c, int argc, const char *
                           "    %s\n",
                         _("Usage:"),
                         _("Delete supported enctypes"));
-               return 0;
+               TALLOC_FREE(tmp_ctx);
+               return -1;
        }
 
-       status = ads_startup(c, false, &ads);
+       status = ads_startup(c, false, tmp_ctx, &ads);
        if (!ADS_ERR_OK(status)) {
-               printf("startup failed\n");
-               return ret;
+               goto done;
        }
 
        ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
@@ -3749,17 +3873,17 @@ static int net_ads_enctypes_delete(struct net_context *c, int argc, const char *
                goto done;
        }
 
-       dn = ads_get_dn(ads, c, res);
+       dn = ads_get_dn(ads, tmp_ctx, res);
        if (dn == NULL) {
                goto done;
        }
 
-       mods = ads_init_mods(c);
+       mods = ads_init_mods(tmp_ctx);
        if (!mods) {
                goto done;
        }
 
-       status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", NULL);
+       status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
        if (!ADS_ERR_OK(status)) {
                goto done;
        }
@@ -3775,7 +3899,7 @@ static int net_ads_enctypes_delete(struct net_context *c, int argc, const char *
 
  done:
        ads_msgfree(ads, res);
-       ads_destroy(&ads);
+       TALLOC_FREE(tmp_ctx);
        return ret;
 }