Don't require "Modify property" perms to unjoin bug #6481)
[ira/wip.git] / source3 / utils / net_ads.c
index b03fefe14a1362e15c85d08441bc63e84fd8bec5..d82715eb45ec1199e324339b2b4155bce9dfd8f7 100644 (file)
@@ -123,6 +123,7 @@ static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
 static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
 {
        ADS_STRUCT *ads;
+       int ret;
 
        if (c->display_usage) {
                d_printf("Usage:\n"
@@ -133,6 +134,7 @@ static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
 
        if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
                d_fprintf(stderr, "Didn't find the cldap server!\n");
+               ads_destroy(&ads);
                return -1;
        }
 
@@ -141,7 +143,9 @@ static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
                ads->ldap.port = 389;
        }
 
-       return net_ads_cldap_netlogon(c, ads);
+       ret = net_ads_cldap_netlogon(c, ads);
+       ads_destroy(&ads);
+       return ret;
 }
 
 
@@ -166,6 +170,7 @@ static int net_ads_info(struct net_context *c, int argc, const char **argv)
 
        if (!ads || !ads->config.realm) {
                d_fprintf(stderr, "Didn't find the ldap server!\n");
+               ads_destroy(&ads);
                return -1;
        }
 
@@ -189,6 +194,7 @@ static int net_ads_info(struct net_context *c, int argc, const char **argv)
        d_printf("KDC server: %s\n", ads->auth.kdc_server );
        d_printf("Server time offset: %d\n", ads->auth.time_offset );
 
+       ads_destroy(&ads);
        return 0;
 }
 
@@ -225,32 +231,23 @@ retry_connect:
 
        ads = ads_init(realm, c->opt_target_workgroup, c->opt_host);
 
-       if (!c->opt_user_name) {
-               c->opt_user_name = "administrator";
-       }
-
-       if (c->opt_user_specified) {
-               need_password = true;
-       }
-
 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);
-                       return ADS_ERROR(LDAP_NO_MEMORY);
-               }
+       if (need_password) {
+               set_cmdline_auth_info_getpass(c->auth_info);
        }
 
-       if (c->opt_password) {
+       if (get_cmdline_auth_info_got_pass(c->auth_info) ||
+           !get_cmdline_auth_info_use_kerberos(c->auth_info)) {
                use_in_memory_ccache();
                SAFE_FREE(ads->auth.password);
-               ads->auth.password = smb_xstrdup(c->opt_password);
+               ads->auth.password = smb_xstrdup(
+                               get_cmdline_auth_info_password(c->auth_info));
        }
 
        ads->auth.flags |= auth_flags;
        SAFE_FREE(ads->auth.user_name);
-       ads->auth.user_name = smb_xstrdup(c->opt_user_name);
+       ads->auth.user_name = smb_xstrdup(
+                       get_cmdline_auth_info_username(c->auth_info));
 
        /*
         * If the username is of the form "name@realm",
@@ -293,7 +290,7 @@ retry:
 
                tried_closest_dc = true; /* avoid loop */
 
-               if (!ads->config.tried_closest_dc) {
+               if (!ads_closest_dc(ads)) {
 
                        namecache_delete(ads->server.realm, 0x1C);
                        namecache_delete(ads->server.workgroup, 0x1C);
@@ -383,6 +380,7 @@ static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
        print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
        if ( !ads_cldap_netlogon_5(talloc_tos(), addr, ads->server.realm, &reply ) ) {
                d_fprintf(stderr, "CLDAP query failed!\n");
+               ads_destroy(&ads);
                return -1;
        }
 
@@ -478,7 +476,9 @@ static int ads_user_add(struct net_context *c, int argc, const char **argv)
        }
 
        /* try setting the password */
-       asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
+       if (asprintf(&upn, "%s@%s", argv[0], ads->config.realm) == -1) {
+               goto done;
+       }
        status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
                                       ads->auth.time_offset);
        SAFE_FREE(upn);
@@ -494,9 +494,9 @@ static int ads_user_add(struct net_context *c, int argc, const char **argv)
        ads_msgfree(ads, res);
        status=ads_find_user_acct(ads, &res, argv[0]);
        if (ADS_ERR_OK(status)) {
-               userdn = ads_get_dn(ads, res);
+               userdn = ads_get_dn(ads, talloc_tos(), res);
                ads_del_dn(ads, userdn);
-               ads_memfree(ads, userdn);
+               TALLOC_FREE(userdn);
        }
 
  done:
@@ -533,7 +533,10 @@ static int ads_user_info(struct net_context *c, int argc, const char **argv)
                return -1;
        }
 
-       asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user);
+       if (asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user) == -1) {
+               SAFE_FREE(escaped_user);
+               return -1;
+       }
        rc = ads_search(ads, &res, searchstring, attrs);
        SAFE_FREE(searchstring);
 
@@ -586,10 +589,10 @@ static int ads_user_delete(struct net_context *c, int argc, const char **argv)
                ads_destroy(&ads);
                return -1;
        }
-       userdn = ads_get_dn(ads, res);
+       userdn = ads_get_dn(ads, talloc_tos(), res);
        ads_msgfree(ads, res);
        rc = ads_del_dn(ads, userdn);
-       ads_memfree(ads, userdn);
+       TALLOC_FREE(userdn);
        if (ADS_ERR_OK(rc)) {
                d_printf("User %s deleted\n", argv[0]);
                ads_destroy(&ads);
@@ -745,10 +748,10 @@ static int ads_group_delete(struct net_context *c, int argc, const char **argv)
                ads_destroy(&ads);
                return -1;
        }
-       groupdn = ads_get_dn(ads, res);
+       groupdn = ads_get_dn(ads, talloc_tos(), res);
        ads_msgfree(ads, res);
        rc = ads_del_dn(ads, groupdn);
-       ads_memfree(ads, groupdn);
+       TALLOC_FREE(groupdn);
        if (ADS_ERR_OK(rc)) {
                d_printf("Group %s deleted\n", argv[0]);
                ads_destroy(&ads);
@@ -863,6 +866,7 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv)
        TALLOC_CTX *ctx;
        struct libnet_UnjoinCtx *r = NULL;
        WERROR werr;
+       struct user_auth_info *ai = c->auth_info;
 
        if (c->display_usage) {
                d_printf("Usage:\n"
@@ -881,7 +885,7 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv)
                return -1;
        }
 
-       if (!c->opt_kerberos) {
+       if (!get_cmdline_auth_info_use_kerberos(ai)) {
                use_in_memory_ccache();
        }
 
@@ -891,15 +895,21 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv)
                return -1;
        }
 
+       set_cmdline_auth_info_getpass(ai);
+
        r->in.debug             = true;
-       r->in.use_kerberos      = c->opt_kerberos;
+       r->in.use_kerberos      = get_cmdline_auth_info_use_kerberos(ai);
        r->in.dc_name           = c->opt_host;
        r->in.domain_name       = lp_realm();
-       r->in.admin_account     = c->opt_user_name;
-       r->in.admin_password    = net_prompt_pass(c, c->opt_user_name);
+       r->in.admin_account     = get_cmdline_auth_info_username(ai);
+       r->in.admin_password    = get_cmdline_auth_info_password(ai);
        r->in.modify_config     = lp_config_backend_is_registry();
+
+       /* Try to delete it, but if that fails, disable it.  The 
+          WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
        r->in.unjoin_flags      = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
                                  WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
+       r->in.delete_machine_account = true;
 
        werr = libnet_Unjoin(ctx, r);
        if (!W_ERROR_IS_OK(werr)) {
@@ -909,7 +919,7 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv)
                goto done;
        }
 
-       if (W_ERROR_IS_OK(werr)) {
+       if (r->out.deleted_machine_account) {
                d_printf("Deleted account for '%s' in realm '%s'\n",
                        r->in.machine_name, r->out.dns_domain_name);
                goto done;
@@ -923,7 +933,10 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv)
                goto done;
        }
 
-       d_fprintf(stderr, "Failed to disable machine account for '%s' in realm '%s'\n",
+       /* Based on what we requseted, 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",
                  r->in.machine_name, r->out.dns_domain_name);
 
  done:
@@ -947,7 +960,8 @@ static NTSTATUS net_ads_join_ok(struct net_context *c)
                return NT_STATUS_ACCESS_DENIED;
        }
 
-       net_use_krb_machine_account(c);
+       set_cmdline_auth_info_use_machine_account(c->auth_info);
+       set_cmdline_auth_info_machine_account_creds(c->auth_info);
 
        status = ads_startup(c, true, &ads);
        if (!ADS_ERR_OK(status)) {
@@ -1178,6 +1192,7 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
        const char *os_name = NULL;
        const char *os_version = NULL;
        bool modify_config = lp_config_backend_is_registry();
+       struct user_auth_info *ai = c->auth_info;;
 
        if (c->display_usage)
                return net_ads_join_usage(c, argc, argv);
@@ -1197,7 +1212,7 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
                goto fail;
        }
 
-       if (!c->opt_kerberos) {
+       if (!get_cmdline_auth_info_use_kerberos(ai)) {
                use_in_memory_ccache();
        }
 
@@ -1247,6 +1262,8 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
 
        /* Do the domain join here */
 
+       set_cmdline_auth_info_getpass(ai);
+
        r->in.domain_name       = domain;
        r->in.create_upn        = createupn;
        r->in.upn               = machineupn;
@@ -1254,10 +1271,10 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
        r->in.os_name           = os_name;
        r->in.os_version        = os_version;
        r->in.dc_name           = c->opt_host;
-       r->in.admin_account     = c->opt_user_name;
-       r->in.admin_password    = net_prompt_pass(c, c->opt_user_name);
+       r->in.admin_account     = get_cmdline_auth_info_username(ai);
+       r->in.admin_password    = get_cmdline_auth_info_password(ai);
        r->in.debug             = true;
-       r->in.use_kerberos      = c->opt_kerberos;
+       r->in.use_kerberos      = get_cmdline_auth_info_use_kerberos(ai);
        r->in.modify_config     = modify_config;
        r->in.join_flags        = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
                                  WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
@@ -1297,7 +1314,9 @@ int net_ads_join(struct net_context *c, int argc, const char **argv)
                        /* kinit with the machine password */
 
                        use_in_memory_ccache();
-                       asprintf( &ads_dns->auth.user_name, "%s$", global_myname() );
+                       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 );
@@ -1566,6 +1585,7 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char *
        char *prt_dn, *srv_dn, **srv_cn;
        char *srv_cn_escaped = NULL, *printername_escaped = NULL;
        LDAPMessage *res = NULL;
+       struct user_auth_info *ai = c->auth_info;
 
        if (argc < 1 || c->display_usage) {
                d_printf("Usage:\n"
@@ -1597,8 +1617,9 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char *
        nt_status = cli_full_connection(&cli, global_myname(), servername,
                                        &server_ss, 0,
                                        "IPC$", "IPC",
-                                       c->opt_user_name, c->opt_workgroup,
-                                       c->opt_password ? c->opt_password : "",
+                                       get_cmdline_auth_info_username(ai),
+                                       c->opt_workgroup,
+                                       get_cmdline_auth_info_password(ai),
                                        CLI_FULL_CONNECTION_USE_KERBEROS,
                                        Undefined, NULL);
 
@@ -1636,12 +1657,19 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char *
                return -1;
        }
 
-       asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn);
+       if (asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn) == -1) {
+               SAFE_FREE(srv_cn_escaped);
+               SAFE_FREE(printername_escaped);
+               d_fprintf(stderr, "Internal error, out of memory!");
+               ads_destroy(&ads);
+               talloc_destroy(mem_ctx);
+               return -1;
+       }
 
        SAFE_FREE(srv_cn_escaped);
        SAFE_FREE(printername_escaped);
 
-       nt_status = cli_rpc_pipe_open_noauth(cli, &syntax_spoolss, &pipe_hnd);
+       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",
                         servername);
@@ -1719,10 +1747,10 @@ static int net_ads_printer_remove(struct net_context *c, int argc, const char **
                return -1;
        }
 
-       prt_dn = ads_get_dn(ads, res);
+       prt_dn = ads_get_dn(ads, talloc_tos(), res);
        ads_msgfree(ads, res);
        rc = ads_del_dn(ads, prt_dn);
-       ads_memfree(ads, prt_dn);
+       TALLOC_FREE(prt_dn);
 
        if (!ADS_ERR_OK(rc)) {
                d_fprintf(stderr, "ads_del_dn: %s\n", ads_errstr(rc));
@@ -1779,8 +1807,8 @@ static int net_ads_printer(struct net_context *c, int argc, const char **argv)
 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;
+       const char *auth_principal;
+       const char *auth_password;
        char *realm = NULL;
        char *new_password = NULL;
        char *chr, *prompt;
@@ -1795,10 +1823,9 @@ static int net_ads_password(struct net_context *c, int argc, const char **argv)
                return 0;
        }
 
-       if (c->opt_user_name == NULL || c->opt_password == NULL) {
-               d_fprintf(stderr, "You must supply an administrator username/password\n");
-               return -1;
-       }
+       auth_principal = get_cmdline_auth_info_username(c->auth_info);
+       set_cmdline_auth_info_getpass(c->auth_info);
+       auth_password = get_cmdline_auth_info_password(c->auth_info);
 
        if (argc < 1) {
                d_fprintf(stderr, "ERROR: You must say which username to change password for\n");
@@ -1807,7 +1834,9 @@ static int net_ads_password(struct net_context *c, int argc, const char **argv)
 
        user = argv[0];
        if (!strchr_m(user, '@')) {
-               asprintf(&chr, "%s@%s", argv[0], lp_realm());
+               if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) {
+                       return -1;
+               }
                user = chr;
        }
 
@@ -1831,13 +1860,16 @@ static int net_ads_password(struct net_context *c, int argc, const char **argv)
 
        if (!ads->config.realm) {
                d_fprintf(stderr, "Didn't find the kerberos server!\n");
+               ads_destroy(&ads);
                return -1;
        }
 
        if (argv[1]) {
                new_password = (char *)argv[1];
        } else {
-               asprintf(&prompt, "Enter new password for %s:", user);
+               if (asprintf(&prompt, "Enter new password for %s:", user) == -1) {
+                       return -1;
+               }
                new_password = getpass(prompt);
                free(prompt);
        }
@@ -1875,7 +1907,7 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
                return -1;
        }
 
-       net_use_krb_machine_account(c);
+       set_cmdline_auth_info_use_machine_account(c->auth_info);
 
        use_in_memory_ccache();
 
@@ -1885,7 +1917,10 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
 
        fstrcpy(my_name, global_myname());
        strlower_m(my_name);
-       asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm);
+       if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
+               ads_destroy(&ads);
+               return -1;
+       }
        d_printf("Changing password for principal: %s\n", host_principal);
 
        ret = ads_change_trust_account_password(ads, host_principal);
@@ -1899,7 +1934,7 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
 
        d_printf("Password change for principal %s succeeded.\n", host_principal);
 
-       if (lp_use_kerberos_keytab()) {
+       if (USE_SYSTEM_KEYTAB) {
                d_printf("Attempting to update system keytab with new password.\n");
                if (ads_keytab_create_default(ads)) {
                        d_printf("Failed to update system keytab.\n");
@@ -2220,9 +2255,9 @@ int net_ads_keytab(struct net_context *c, int argc, const char **argv)
                {NULL, NULL, 0, NULL, NULL}
        };
 
-       if (!lp_use_kerberos_keytab()) {
-               d_printf("\nWarning: \"use kerberos keytab\" must be set to \"true\" in order to \
-use keytab functions.\n");
+       if (!USE_KERBEROS_KEYTAB) {
+               d_printf("\nWarning: \"kerberos method\" must be set to a "
+                   "keytab method to use keytab functions.\n");
        }
 
        return net_run_function(c, argc, argv, "net ads keytab", func);
@@ -2254,6 +2289,7 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar
        TALLOC_CTX *mem_ctx = NULL;
        NTSTATUS status;
        int ret = -1;
+       struct user_auth_info *ai = c->auth_info;
 
        if (c->display_usage) {
                d_printf("Usage:\n"
@@ -2267,11 +2303,11 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar
                goto out;
        }
 
-       c->opt_password = net_prompt_pass(c, c->opt_user_name);
+       set_cmdline_auth_info_getpass(ai);
 
        status = kerberos_return_pac(mem_ctx,
-                                    c->opt_user_name,
-                                    c->opt_password,
+                                    get_cmdline_auth_info_username(ai),
+                                    get_cmdline_auth_info_password(ai),
                                     0,
                                     NULL,
                                     NULL,
@@ -2304,6 +2340,7 @@ static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **
        TALLOC_CTX *mem_ctx = NULL;
        int ret = -1;
        NTSTATUS status;
+       struct user_auth_info *ai = c->auth_info;
 
        if (c->display_usage) {
                d_printf("Usage:\n"
@@ -2317,10 +2354,10 @@ static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **
                goto out;
        }
 
-       c->opt_password = net_prompt_pass(c, c->opt_user_name);
+       set_cmdline_auth_info_getpass(ai);
 
-       ret = kerberos_kinit_password_ext(c->opt_user_name,
-                                         c->opt_password,
+       ret = kerberos_kinit_password_ext(get_cmdline_auth_info_username(ai),
+                                         get_cmdline_auth_info_password(ai),
                                          0,
                                          NULL,
                                          NULL,