s3-param Remove special case for global_myname(), rename to lp_netbios_name()
[samba.git] / source3 / utils / net_rpc_join.c
index 87a90550fab9cba4cc86762d38f67c76ae2fe492..d228f928047e57e5fdd2b48995f4305d69987182 100644 (file)
 
 #include "includes.h"
 #include "utils/net.h"
+#include "rpc_client/cli_pipe.h"
+#include "../libcli/auth/libcli_auth.h"
+#include "../librpc/gen_ndr/ndr_lsa_c.h"
+#include "rpc_client/cli_lsarpc.h"
+#include "../librpc/gen_ndr/ndr_samr_c.h"
+#include "rpc_client/init_samr.h"
+#include "../librpc/gen_ndr/ndr_netlogon.h"
+#include "rpc_client/cli_netlogon.h"
+#include "secrets.h"
+#include "rpc_client/init_lsa.h"
+#include "libsmb/libsmb.h"
 
 /* Macro for checking RPC error codes to make things more readable */
 
 #define CHECK_RPC_ERR(rpc, msg) \
-        if (!NT_STATUS_IS_OK(result = rpc)) { \
-                DEBUG(0, (msg ": %s\n", nt_errstr(result))); \
+        if (!NT_STATUS_IS_OK(status = rpc)) { \
+                DEBUG(0, (msg ": %s\n", nt_errstr(status))); \
                 goto done; \
         }
 
+#define CHECK_DCERPC_ERR(rpc, msg) \
+       if (!NT_STATUS_IS_OK(status = rpc)) { \
+               DEBUG(0, (msg ": %s\n", nt_errstr(status))); \
+               goto done; \
+       } \
+       if (!NT_STATUS_IS_OK(result)) { \
+               status = result; \
+               DEBUG(0, (msg ": %s\n", nt_errstr(result))); \
+               goto done; \
+       }
+
+
 #define CHECK_RPC_ERR_DEBUG(rpc, debug_args) \
-        if (!NT_STATUS_IS_OK(result = rpc)) { \
+        if (!NT_STATUS_IS_OK(status = rpc)) { \
                 DEBUG(0, debug_args); \
                 goto done; \
         }
 
+#define CHECK_DCERPC_ERR_DEBUG(rpc, debug_args) \
+       if (!NT_STATUS_IS_OK(status = rpc)) { \
+               DEBUG(0, debug_args); \
+               goto done; \
+       } \
+       if (!NT_STATUS_IS_OK(result)) { \
+               status = result; \
+               DEBUG(0, debug_args); \
+               goto done; \
+       }
+
+
 /**
  * confirm that a domain join is still valid
  *
@@ -73,12 +108,13 @@ NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain,
        }
 
        /* Setup the creds as though we're going to do schannel... */
-        netlogon_pipe = get_schannel_session_key(cli, domain, &neg_flags, &ntret);
+       ntret = get_schannel_session_key(cli, domain, &neg_flags,
+                                        &netlogon_pipe);
 
        /* We return NT_STATUS_INVALID_NETWORK_RESPONSE if the server is refusing
           to negotiate schannel, but the creds were set up ok. That'll have to do. */
 
-        if (!netlogon_pipe) {
+        if (!NT_STATUS_IS_OK(ntret)) {
                if (NT_STATUS_EQUAL(ntret, NT_STATUS_INVALID_NETWORK_RESPONSE)) {
                        cli_shutdown(cli);
                        return NT_STATUS_OK;
@@ -98,11 +134,12 @@ NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain,
                return ntret;
        }
 
-       pipe_hnd = cli_rpc_pipe_open_schannel_with_key(cli, PI_NETLOGON,
-                               PIPE_AUTH_LEVEL_PRIVACY,
-                               domain, netlogon_pipe->dc, &ntret);
+       ntret = cli_rpc_pipe_open_schannel_with_key(
+               cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
+               DCERPC_AUTH_LEVEL_PRIVACY,
+               domain, &netlogon_pipe->dc, &pipe_hnd);
 
-       if (!pipe_hnd) {
+       if (!NT_STATUS_IS_OK(ntret)) {
                DEBUG(0,("net_rpc_join_ok: failed to open schannel session "
                                "on netlogon pipe to server %s for domain %s. Error was %s\n",
                        cli->desthost, domain, nt_errstr(ntret) ));
@@ -135,25 +172,26 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
        TALLOC_CTX *mem_ctx;
         uint32 acb_info = ACB_WSTRUST;
        uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
-       uint32 sec_channel_type;
+       enum netr_SchannelType sec_channel_type;
        struct rpc_pipe_client *pipe_hnd = NULL;
+       struct dcerpc_binding_handle *b = NULL;
 
        /* rpc variables */
 
-       POLICY_HND lsa_pol, sam_pol, domain_pol, user_pol;
-       DOM_SID *domain_sid;
+       struct policy_handle lsa_pol, sam_pol, domain_pol, user_pol;
+       struct dom_sid *domain_sid;
        uint32 user_rid;
 
        /* Password stuff */
 
        char *clear_trust_password = NULL;
-       uchar pwbuf[516];
+       struct samr_CryptPassword crypt_pwd;
        uchar md4_trust_password[16];
        union samr_UserInfo set_info;
 
        /* Misc */
 
-       NTSTATUS result;
+       NTSTATUS status, result;
        int retval = 1;
        const char *domain = NULL;
        char *acct_name;
@@ -164,6 +202,7 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
        struct samr_Ids user_rids;
        struct samr_Ids name_types;
 
+
        /* check what type of join */
        if (argc >= 0) {
                sec_channel_type = get_sec_channel_type(argv[0]);
@@ -183,12 +222,16 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
                acb_info = ACB_DOMTRUST;
                break;
 #endif
+       default:
+               DEBUG(0,("secure channel type %d not yet supported\n",
+                       sec_channel_type));
+               break;
        }
 
        /* Make authenticated connection to remote machine */
 
-       result = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
-       if (!NT_STATUS_IS_OK(result)) {
+       status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
+       if (!NT_STATUS_IS_OK(status)) {
                return 1;
        }
 
@@ -199,29 +242,32 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
 
        /* Fetch domain sid */
 
-       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
-       if (!pipe_hnd) {
+       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
+                                         &pipe_hnd);
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n",
-                       nt_errstr(result) ));
+                       nt_errstr(status) ));
                goto done;
        }
 
+       b = pipe_hnd->binding_handle;
 
-       CHECK_RPC_ERR(rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
-                                         SEC_RIGHTS_MAXIMUM_ALLOWED,
+       CHECK_RPC_ERR(rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
+                                         SEC_FLAG_MAXIMUM_ALLOWED,
                                          &lsa_pol),
                      "error opening lsa policy handle");
 
-       CHECK_RPC_ERR(rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
-                                                &lsa_pol,
-                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
-                                                &info),
+       CHECK_DCERPC_ERR(dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
+                                                   &lsa_pol,
+                                                   LSA_POLICY_INFO_ACCOUNT_DOMAIN,
+                                                   &info,
+                                                   &result),
                      "error querying info policy");
 
        domain = info->account_domain.name.string;
        domain_sid = info->account_domain.sid;
 
-       rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
+       dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
        TALLOC_FREE(pipe_hnd); /* Done with this pipe */
 
        /* Bail out if domain didn't get set. */
@@ -231,30 +277,38 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
        }
 
        /* Create domain user */
-       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);
-       if (!pipe_hnd) {
+       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
+                                         &pipe_hnd);
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
-                       nt_errstr(result) ));
+                       nt_errstr(status) ));
                goto done;
        }
 
-       CHECK_RPC_ERR(rpccli_samr_Connect2(pipe_hnd, mem_ctx,
-                                          pipe_hnd->desthost,
-                                          SEC_RIGHTS_MAXIMUM_ALLOWED,
-                                          &sam_pol),
+       b = pipe_hnd->binding_handle;
+
+       CHECK_DCERPC_ERR(dcerpc_samr_Connect2(b, mem_ctx,
+                                             pipe_hnd->desthost,
+                                             SAMR_ACCESS_ENUM_DOMAINS
+                                             | SAMR_ACCESS_LOOKUP_DOMAIN,
+                                             &sam_pol,
+                                             &result),
                      "could not connect to SAM database");
 
 
-       CHECK_RPC_ERR(rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
-                                            &sam_pol,
-                                            SEC_RIGHTS_MAXIMUM_ALLOWED,
-                                            domain_sid,
-                                            &domain_pol),
+       CHECK_DCERPC_ERR(dcerpc_samr_OpenDomain(b, mem_ctx,
+                                               &sam_pol,
+                                               SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1
+                                               | SAMR_DOMAIN_ACCESS_CREATE_USER
+                                               | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
+                                               domain_sid,
+                                               &domain_pol,
+                                               &result),
                      "could not open domain");
 
        /* Create domain user */
-       if ((acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname())) == NULL) {
-               result = NT_STATUS_NO_MEMORY;
+       if ((acct_name = talloc_asprintf(mem_ctx, "%s$", lp_netbios_name())) == NULL) {
+               status = NT_STATUS_NO_MEMORY;
                goto done;
        }
        strlower_m(acct_name);
@@ -269,25 +323,30 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
 
        DEBUG(10, ("Creating account with flags: %d\n",acct_flags));
 
-       result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_CreateUser2(b, mem_ctx,
                                         &domain_pol,
                                         &lsa_acct_name,
                                         acb_info,
                                         acct_flags,
                                         &user_pol,
                                         &access_granted,
-                                        &user_rid);
-
-       if (!NT_STATUS_IS_OK(result) && 
+                                        &user_rid,
+                                        &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+       if (!NT_STATUS_IS_OK(result) &&
            !NT_STATUS_EQUAL(result, NT_STATUS_USER_EXISTS)) {
-               d_fprintf(stderr, "Creation of workstation account failed\n");
+               status = result;
+               d_fprintf(stderr,_("Creation of workstation account failed\n"));
 
                /* If NT_STATUS_ACCESS_DENIED then we have a valid
                   username/password combo but the user does not have
                   administrator access. */
 
                if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED))
-                       d_fprintf(stderr, "User specified does not have administrator privileges\n");
+                       d_fprintf(stderr, _("User specified does not have "
+                                           "administrator privileges\n"));
 
                goto done;
        }
@@ -295,17 +354,18 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
        /* We *must* do this.... don't ask... */
 
        if (NT_STATUS_IS_OK(result)) {
-               rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
+               dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
        }
 
-       CHECK_RPC_ERR_DEBUG(rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
-                                                   &domain_pol,
-                                                   1,
-                                                   &lsa_acct_name,
-                                                   &user_rids,
-                                                   &name_types),
-                           ("error looking up rid for user %s: %s\n",
-                            acct_name, nt_errstr(result)));
+       CHECK_DCERPC_ERR_DEBUG(dcerpc_samr_LookupNames(b, mem_ctx,
+                                                      &domain_pol,
+                                                      1,
+                                                      &lsa_acct_name,
+                                                      &user_rids,
+                                                      &name_types,
+                                                      &result),
+                           ("error looking up rid for user %s: %s/%s\n",
+                            acct_name, nt_errstr(status), nt_errstr(result)));
 
        if (name_types.ids[0] != SID_NAME_USER) {
                DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types.ids[0]));
@@ -316,37 +376,35 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
 
        /* Open handle on user */
 
-       CHECK_RPC_ERR_DEBUG(
-               rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
+       CHECK_DCERPC_ERR_DEBUG(
+               dcerpc_samr_OpenUser(b, mem_ctx,
                                     &domain_pol,
-                                    SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                    SEC_FLAG_MAXIMUM_ALLOWED,
                                     user_rid,
-                                    &user_pol),
-               ("could not re-open existing user %s: %s\n",
-                acct_name, nt_errstr(result)));
+                                    &user_pol,
+                                    &result),
+               ("could not re-open existing user %s: %s/%s\n",
+                acct_name, nt_errstr(status), nt_errstr(result)));
        
        /* Create a random machine account password */
 
-       { 
-               char *str;
-               str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
-               clear_trust_password = SMB_STRDUP(str);
-               E_md4hash(clear_trust_password, md4_trust_password);
-       }
-
-       encode_pw_buffer(pwbuf, clear_trust_password, STR_UNICODE);
+       clear_trust_password = generate_random_str(talloc_tos(), DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
+       E_md4hash(clear_trust_password, md4_trust_password);
 
        /* Set password on machine account */
 
-       init_samr_user_info24(&set_info.info24, pwbuf, 24);
+       init_samr_CryptPassword(clear_trust_password,
+                               &cli->user_session_key,
+                               &crypt_pwd);
 
-       SamOEMhashBlob(set_info.info24.password.data, 516,
-                      &cli->user_session_key);
+       set_info.info24.password = crypt_pwd;
+       set_info.info24.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;
 
-       CHECK_RPC_ERR(rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
-                                              &user_pol,
-                                              24,
-                                              &set_info),
+       CHECK_DCERPC_ERR(dcerpc_samr_SetUserInfo2(b, mem_ctx,
+                                                 &user_pol,
+                                                 24,
+                                                 &set_info,
+                                                 &result),
                      "error setting trust account password");
 
        /* Why do we have to try to (re-)set the ACB to be the same as what
@@ -363,41 +421,44 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
        /* Ignoring the return value is necessary for joining a domain
           as a normal user with "Add workstation to domain" privilege. */
 
-       result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
+       status = dcerpc_samr_SetUserInfo(b, mem_ctx,
                                         &user_pol,
                                         16,
-                                        &set_info);
+                                        &set_info,
+                                        &result);
 
-       rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
+       dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
        TALLOC_FREE(pipe_hnd); /* Done with this pipe */
 
        /* Now check the whole process from top-to-bottom */
 
-       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result);
-       if (!pipe_hnd) {
+       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
+                                         &pipe_hnd);
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n",
-                       nt_errstr(result) ));
+                       nt_errstr(status) ));
                goto done;
        }
 
-       result = rpccli_netlogon_setup_creds(pipe_hnd,
+       status = rpccli_netlogon_setup_creds(pipe_hnd,
                                        cli->desthost, /* server name */
                                        domain,        /* domain */
-                                       global_myname(), /* client name */
-                                       global_myname(), /* machine account name */
+                                       lp_netbios_name(), /* client name */
+                                       lp_netbios_name(), /* machine account name */
                                         md4_trust_password,
                                         sec_channel_type,
                                         &neg_flags);
 
-       if (!NT_STATUS_IS_OK(result)) {
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("Error in domain join verification (credential setup failed): %s\n\n",
-                         nt_errstr(result)));
+                         nt_errstr(status)));
 
-               if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) &&
+               if ( NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
                     (sec_channel_type == SEC_CHAN_BDC) ) {
-                       d_fprintf(stderr, "Please make sure that no computer account\n"
-                                "named like this machine (%s) exists in the domain\n",
-                                global_myname());
+                       d_fprintf(stderr, _("Please make sure that no computer "
+                                           "account\nnamed like this machine "
+                                           "(%s) exists in the domain\n"),
+                                lp_netbios_name());
                }
 
                goto done;
@@ -409,23 +470,24 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
           do the same again (setup creds) in net_rpc_join_ok(). JRA. */
 
        if (lp_client_schannel() && (neg_flags & NETLOGON_NEG_SCHANNEL)) {
-               struct rpc_pipe_client *netlogon_schannel_pipe = 
-                                               cli_rpc_pipe_open_schannel_with_key(cli,
-                                                       PI_NETLOGON,
-                                                       PIPE_AUTH_LEVEL_PRIVACY,
-                                                       domain,
-                                                       pipe_hnd->dc,
-                                                       &result);
-
-               if (!NT_STATUS_IS_OK(result)) {
+               struct rpc_pipe_client *netlogon_schannel_pipe;
+
+               status = cli_rpc_pipe_open_schannel_with_key(
+                       cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
+                       DCERPC_AUTH_LEVEL_PRIVACY, domain, &pipe_hnd->dc,
+                       &netlogon_schannel_pipe);
+
+               if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(0, ("Error in domain join verification (schannel setup failed): %s\n\n",
-                                 nt_errstr(result)));
+                                 nt_errstr(status)));
 
-                       if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) &&
+                       if ( NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
                             (sec_channel_type == SEC_CHAN_BDC) ) {
-                               d_fprintf(stderr, "Please make sure that no computer account\n"
-                                        "named like this machine (%s) exists in the domain\n",
-                                        global_myname());
+                               d_fprintf(stderr, _("Please make sure that no "
+                                                   "computer account\nnamed "
+                                                   "like this machine (%s) "
+                                                   "exists in the domain\n"),
+                                        lp_netbios_name());
                        }
 
                        goto done;
@@ -437,7 +499,7 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
 
        /* Now store the secret in the secrets database */
 
-       strupper_m(CONST_DISCARD(char *, domain));
+       strupper_m(discard_const_p(char, domain));
 
        if (!secrets_store_domain_sid(domain, domain_sid)) {
                DEBUG(0, ("error storing domain sid for %s\n", domain));
@@ -449,8 +511,8 @@ int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
        }
 
        /* double-check, connection from scratch */
-       result = net_rpc_join_ok(c, domain, cli->desthost, &cli->dest_ss);
-       retval = NT_STATUS_IS_OK(result) ? 0 : -1;
+       status = net_rpc_join_ok(c, domain, cli->desthost, &cli->dest_ss);
+       retval = NT_STATUS_IS_OK(status) ? 0 : -1;
 
 done:
 
@@ -458,15 +520,15 @@ done:
 
        if (domain) {
                if (retval != 0) {
-                       fprintf(stderr,"Unable to join domain %s.\n",domain);
+                       fprintf(stderr,_("Unable to join domain %s.\n"),domain);
                } else {
-                       printf("Joined domain %s.\n",domain);
+                       printf(_("Joined domain %s.\n"),domain);
                }
        }
 
        cli_shutdown(cli);
 
-       SAFE_FREE(clear_trust_password);
+       TALLOC_FREE(clear_trust_password);
 
        return retval;
 }
@@ -479,19 +541,23 @@ done:
  **/
 int net_rpc_testjoin(struct net_context *c, int argc, const char **argv)
 {
-       char *domain = smb_xstrdup(c->opt_target_workgroup);
        NTSTATUS nt_status;
 
+       if (c->display_usage) {
+               d_printf(_("Usage\n"
+                          "net rpc testjoin\n"
+                          "    Test if a join is OK\n"));
+               return 0;
+       }
+
        /* Display success or failure */
-       nt_status = net_rpc_join_ok(c, domain, NULL, NULL);
+       nt_status = net_rpc_join_ok(c, c->opt_target_workgroup, NULL, NULL);
        if (!NT_STATUS_IS_OK(nt_status)) {
-               fprintf(stderr,"Join to domain '%s' is not valid: %s\n",
-                       domain, nt_errstr(nt_status));
-               free(domain);
+               fprintf(stderr, _("Join to domain '%s' is not valid: %s\n"),
+                       c->opt_target_workgroup, nt_errstr(nt_status));
                return -1;
        }
 
-       printf("Join to '%s' is OK\n",domain);
-       free(domain);
+       printf(_("Join to '%s' is OK\n"), c->opt_target_workgroup);
        return 0;
 }