LCOV - code coverage report
Current view: top level - source3/lib/netapi - joindomain.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 122 424 28.8 %
Date: 2021-09-23 10:06:22 Functions: 5 16 31.2 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  NetApi Join Support
       4             :  *  Copyright (C) Guenther Deschner 2007-2008
       5             :  *
       6             :  *  This program is free software; you can redistribute it and/or modify
       7             :  *  it under the terms of the GNU General Public License as published by
       8             :  *  the Free Software Foundation; either version 3 of the License, or
       9             :  *  (at your option) any later version.
      10             :  *
      11             :  *  This program is distributed in the hope that it will be useful,
      12             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  *  GNU General Public License for more details.
      15             :  *
      16             :  *  You should have received a copy of the GNU General Public License
      17             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include "includes.h"
      21             : #include "ads.h"
      22             : #include "librpc/gen_ndr/libnetapi.h"
      23             : #include "libcli/auth/libcli_auth.h"
      24             : #include "lib/netapi/netapi.h"
      25             : #include "lib/netapi/netapi_private.h"
      26             : #include "lib/netapi/libnetapi.h"
      27             : #include "librpc/gen_ndr/libnet_join.h"
      28             : #include "libnet/libnet_join.h"
      29             : #include "../librpc/gen_ndr/ndr_wkssvc_c.h"
      30             : #include "rpc_client/cli_pipe.h"
      31             : #include "secrets.h"
      32             : #include "libsmb/dsgetdcname.h"
      33             : #include "../librpc/gen_ndr/ndr_ODJ.h"
      34             : #include "lib/util/base64.h"
      35             : #include "libnet/libnet_join_offline.h"
      36             : 
      37             : /****************************************************************
      38             : ****************************************************************/
      39             : 
      40           2 : WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
      41             :                        struct NetJoinDomain *r)
      42             : {
      43           2 :         struct libnet_JoinCtx *j = NULL;
      44             :         struct libnetapi_private_ctx *priv;
      45             :         WERROR werr;
      46             : 
      47           2 :         priv = talloc_get_type_abort(mem_ctx->private_data,
      48             :                 struct libnetapi_private_ctx);
      49             : 
      50           2 :         if (!r->in.domain) {
      51           0 :                 return WERR_INVALID_PARAMETER;
      52             :         }
      53             : 
      54           2 :         werr = libnet_init_JoinCtx(mem_ctx, &j);
      55           2 :         W_ERROR_NOT_OK_RETURN(werr);
      56             : 
      57           2 :         j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
      58           2 :         W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
      59             : 
      60           2 :         if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
      61             :                 NTSTATUS status;
      62           2 :                 struct netr_DsRGetDCNameInfo *info = NULL;
      63           2 :                 const char *dc = NULL;
      64           2 :                 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
      65             :                                  DS_WRITABLE_REQUIRED |
      66             :                                  DS_RETURN_DNS_NAME;
      67           2 :                 status = dsgetdcname(mem_ctx, priv->msg_ctx, r->in.domain,
      68             :                                      NULL, NULL, flags, &info);
      69           2 :                 if (!NT_STATUS_IS_OK(status)) {
      70           2 :                         libnetapi_set_error_string(mem_ctx,
      71             :                                 "%s", get_friendly_nt_error_msg(status));
      72           4 :                         return ntstatus_to_werror(status);
      73             :                 }
      74             : 
      75           0 :                 dc = strip_hostname(info->dc_unc);
      76           0 :                 j->in.dc_name = talloc_strdup(mem_ctx, dc);
      77           0 :                 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
      78             :         }
      79             : 
      80           0 :         if (r->in.account_ou) {
      81           0 :                 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
      82           0 :                 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
      83             :         }
      84             : 
      85           0 :         if (r->in.account) {
      86           0 :                 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
      87           0 :                 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
      88             :         }
      89             : 
      90           0 :         if (r->in.password) {
      91           0 :                 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
      92           0 :                 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
      93             :         }
      94             : 
      95           0 :         j->in.join_flags = r->in.join_flags;
      96           0 :         j->in.modify_config = true;
      97           0 :         j->in.debug = true;
      98             : 
      99           0 :         werr = libnet_Join(mem_ctx, j);
     100           0 :         if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
     101           0 :                 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
     102             :         }
     103           0 :         TALLOC_FREE(j);
     104             : 
     105           0 :         return werr;
     106             : }
     107             : 
     108             : /****************************************************************
     109             : ****************************************************************/
     110             : 
     111           0 : WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
     112             :                        struct NetJoinDomain *r)
     113             : {
     114           0 :         struct rpc_pipe_client *pipe_cli = NULL;
     115           0 :         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
     116             :         NTSTATUS status;
     117             :         WERROR werr;
     118           0 :         unsigned int old_timeout = 0;
     119             :         struct dcerpc_binding_handle *b;
     120             :         DATA_BLOB session_key;
     121             : 
     122           0 :         if (IS_DC) {
     123           0 :                 return WERR_NERR_SETUPDOMAINCONTROLLER;
     124             :         }
     125             : 
     126           0 :         werr = libnetapi_open_pipe(ctx, r->in.server,
     127             :                                    &ndr_table_wkssvc,
     128             :                                    &pipe_cli);
     129           0 :         if (!W_ERROR_IS_OK(werr)) {
     130           0 :                 goto done;
     131             :         }
     132             : 
     133           0 :         b = pipe_cli->binding_handle;
     134             : 
     135           0 :         if (r->in.password) {
     136             : 
     137           0 :                 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
     138           0 :                 if (!NT_STATUS_IS_OK(status)) {
     139           0 :                         werr = ntstatus_to_werror(status);
     140           0 :                         goto done;
     141             :                 }
     142             : 
     143           0 :                 werr = encode_wkssvc_join_password_buffer(ctx,
     144             :                                                           r->in.password,
     145             :                                                           &session_key,
     146             :                                                           &encrypted_password);
     147           0 :                 if (!W_ERROR_IS_OK(werr)) {
     148           0 :                         goto done;
     149             :                 }
     150             :         }
     151             : 
     152           0 :         old_timeout = rpccli_set_timeout(pipe_cli, 600000);
     153             : 
     154           0 :         status = dcerpc_wkssvc_NetrJoinDomain2(b, talloc_tos(),
     155             :                                                r->in.server,
     156             :                                                r->in.domain,
     157             :                                                r->in.account_ou,
     158             :                                                r->in.account,
     159             :                                                encrypted_password,
     160             :                                                r->in.join_flags,
     161             :                                                &werr);
     162           0 :         if (!NT_STATUS_IS_OK(status)) {
     163           0 :                 werr = ntstatus_to_werror(status);
     164           0 :                 goto done;
     165             :         }
     166             : 
     167           0 :  done:
     168           0 :         if (pipe_cli && old_timeout) {
     169           0 :                 rpccli_set_timeout(pipe_cli, old_timeout);
     170             :         }
     171             : 
     172           0 :         return werr;
     173             : }
     174             : /****************************************************************
     175             : ****************************************************************/
     176             : 
     177           0 : WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
     178             :                          struct NetUnjoinDomain *r)
     179             : {
     180           0 :         struct libnet_UnjoinCtx *u = NULL;
     181             :         struct dom_sid domain_sid;
     182           0 :         const char *domain = NULL;
     183             :         WERROR werr;
     184             :         struct libnetapi_private_ctx *priv;
     185           0 :         const char *realm = lp_realm();
     186             : 
     187           0 :         priv = talloc_get_type_abort(mem_ctx->private_data,
     188             :                 struct libnetapi_private_ctx);
     189             : 
     190           0 :         if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
     191           0 :                 return WERR_NERR_SETUPNOTJOINED;
     192             :         }
     193             : 
     194           0 :         werr = libnet_init_UnjoinCtx(mem_ctx, &u);
     195           0 :         W_ERROR_NOT_OK_RETURN(werr);
     196             : 
     197           0 :         if (realm[0] != '\0') {
     198           0 :                 domain = realm;
     199             :         } else {
     200           0 :                 domain = lp_workgroup();
     201             :         }
     202             : 
     203           0 :         if (r->in.server_name) {
     204           0 :                 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
     205           0 :                 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
     206             :         } else {
     207             :                 NTSTATUS status;
     208           0 :                 struct netr_DsRGetDCNameInfo *info = NULL;
     209           0 :                 const char *dc = NULL;
     210           0 :                 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
     211             :                                  DS_WRITABLE_REQUIRED |
     212             :                                  DS_RETURN_DNS_NAME;
     213           0 :                 status = dsgetdcname(mem_ctx, priv->msg_ctx, domain,
     214             :                                      NULL, NULL, flags, &info);
     215           0 :                 if (!NT_STATUS_IS_OK(status)) {
     216           0 :                         libnetapi_set_error_string(mem_ctx,
     217             :                                 "failed to find DC for domain %s: %s",
     218             :                                 domain,
     219             :                                 get_friendly_nt_error_msg(status));
     220           0 :                         return ntstatus_to_werror(status);
     221             :                 }
     222             : 
     223           0 :                 dc = strip_hostname(info->dc_unc);
     224           0 :                 u->in.dc_name = talloc_strdup(mem_ctx, dc);
     225           0 :                 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
     226             : 
     227           0 :                 u->in.domain_name = domain;
     228             :         }
     229             : 
     230           0 :         if (r->in.account) {
     231           0 :                 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
     232           0 :                 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
     233             :         }
     234             : 
     235           0 :         if (r->in.password) {
     236           0 :                 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
     237           0 :                 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
     238             :         }
     239             : 
     240           0 :         u->in.domain_name = domain;
     241           0 :         u->in.unjoin_flags = r->in.unjoin_flags;
     242           0 :         u->in.delete_machine_account = false;
     243           0 :         u->in.modify_config = true;
     244           0 :         u->in.debug = true;
     245             : 
     246           0 :         u->in.domain_sid = &domain_sid;
     247             : 
     248           0 :         werr = libnet_Unjoin(mem_ctx, u);
     249           0 :         if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
     250           0 :                 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
     251             :         }
     252           0 :         TALLOC_FREE(u);
     253             : 
     254           0 :         return werr;
     255             : }
     256             : 
     257             : /****************************************************************
     258             : ****************************************************************/
     259             : 
     260           0 : WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
     261             :                          struct NetUnjoinDomain *r)
     262             : {
     263           0 :         struct rpc_pipe_client *pipe_cli = NULL;
     264           0 :         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
     265             :         NTSTATUS status;
     266             :         WERROR werr;
     267           0 :         unsigned int old_timeout = 0;
     268             :         struct dcerpc_binding_handle *b;
     269             :         DATA_BLOB session_key;
     270             : 
     271           0 :         werr = libnetapi_open_pipe(ctx, r->in.server_name,
     272             :                                    &ndr_table_wkssvc,
     273             :                                    &pipe_cli);
     274           0 :         if (!W_ERROR_IS_OK(werr)) {
     275           0 :                 goto done;
     276             :         }
     277             : 
     278           0 :         b = pipe_cli->binding_handle;
     279             : 
     280           0 :         if (r->in.password) {
     281             : 
     282           0 :                 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
     283           0 :                 if (!NT_STATUS_IS_OK(status)) {
     284           0 :                         werr = ntstatus_to_werror(status);
     285           0 :                         goto done;
     286             :                 }
     287             : 
     288           0 :                 werr = encode_wkssvc_join_password_buffer(ctx,
     289             :                                                           r->in.password,
     290             :                                                           &session_key,
     291             :                                                           &encrypted_password);
     292           0 :                 if (!W_ERROR_IS_OK(werr)) {
     293           0 :                         goto done;
     294             :                 }
     295             :         }
     296             : 
     297           0 :         old_timeout = rpccli_set_timeout(pipe_cli, 60000);
     298             : 
     299           0 :         status = dcerpc_wkssvc_NetrUnjoinDomain2(b, talloc_tos(),
     300             :                                                  r->in.server_name,
     301             :                                                  r->in.account,
     302             :                                                  encrypted_password,
     303             :                                                  r->in.unjoin_flags,
     304             :                                                  &werr);
     305           0 :         if (!NT_STATUS_IS_OK(status)) {
     306           0 :                 werr = ntstatus_to_werror(status);
     307           0 :                 goto done;
     308             :         }
     309             : 
     310           0 :  done:
     311           0 :         if (pipe_cli && old_timeout) {
     312           0 :                 rpccli_set_timeout(pipe_cli, old_timeout);
     313             :         }
     314             : 
     315           0 :         return werr;
     316             : }
     317             : 
     318             : /****************************************************************
     319             : ****************************************************************/
     320             : 
     321           0 : WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
     322             :                                struct NetGetJoinInformation *r)
     323             : {
     324           0 :         struct rpc_pipe_client *pipe_cli = NULL;
     325             :         NTSTATUS status;
     326             :         WERROR werr;
     327           0 :         const char *buffer = NULL;
     328             :         struct dcerpc_binding_handle *b;
     329             : 
     330           0 :         werr = libnetapi_open_pipe(ctx, r->in.server_name,
     331             :                                    &ndr_table_wkssvc,
     332             :                                    &pipe_cli);
     333           0 :         if (!W_ERROR_IS_OK(werr)) {
     334           0 :                 goto done;
     335             :         }
     336             : 
     337           0 :         b = pipe_cli->binding_handle;
     338             : 
     339           0 :         status = dcerpc_wkssvc_NetrGetJoinInformation(b, talloc_tos(),
     340             :                                                       r->in.server_name,
     341             :                                                       &buffer,
     342           0 :                                                       (enum wkssvc_NetJoinStatus *)r->out.name_type,
     343             :                                                       &werr);
     344           0 :         if (!NT_STATUS_IS_OK(status)) {
     345           0 :                 werr = ntstatus_to_werror(status);
     346           0 :                 goto done;
     347             :         }
     348             : 
     349           0 :         if (!W_ERROR_IS_OK(werr)) {
     350           0 :                 goto done;
     351             :         }
     352             : 
     353           0 :         *r->out.name_buffer = talloc_strdup(ctx, buffer);
     354           0 :         W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
     355             : 
     356           0 :  done:
     357           0 :         return werr;
     358             : }
     359             : 
     360             : /****************************************************************
     361             : ****************************************************************/
     362             : 
     363           0 : WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
     364             :                                struct NetGetJoinInformation *r)
     365             : {
     366           0 :         const char *realm = lp_realm();
     367             : 
     368           0 :         if ((lp_security() == SEC_ADS) && realm[0] != '\0') {
     369           0 :                 *r->out.name_buffer = talloc_strdup(ctx, realm);
     370             :         } else {
     371           0 :                 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
     372             :         }
     373           0 :         if (!*r->out.name_buffer) {
     374           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     375             :         }
     376             : 
     377           0 :         switch (lp_server_role()) {
     378           0 :                 case ROLE_DOMAIN_MEMBER:
     379             :                 case ROLE_DOMAIN_PDC:
     380             :                 case ROLE_DOMAIN_BDC:
     381           0 :                         *r->out.name_type = NetSetupDomainName;
     382           0 :                         break;
     383           0 :                 case ROLE_STANDALONE:
     384             :                 default:
     385           0 :                         *r->out.name_type = NetSetupWorkgroupName;
     386           0 :                         break;
     387             :         }
     388             : 
     389           0 :         return WERR_OK;
     390             : }
     391             : 
     392             : /****************************************************************
     393             : ****************************************************************/
     394             : 
     395           0 : WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
     396             :                            struct NetGetJoinableOUs *r)
     397             : {
     398             : #ifdef HAVE_ADS
     399             :         NTSTATUS status;
     400             :         ADS_STATUS ads_status;
     401           0 :         ADS_STRUCT *ads = NULL;
     402           0 :         struct netr_DsRGetDCNameInfo *info = NULL;
     403           0 :         const char *dc = NULL;
     404           0 :         uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
     405             :                          DS_RETURN_DNS_NAME;
     406             :         struct libnetapi_private_ctx *priv;
     407             :         char **p;
     408             :         size_t s;
     409             : 
     410           0 :         priv = talloc_get_type_abort(ctx->private_data,
     411             :                 struct libnetapi_private_ctx);
     412             : 
     413           0 :         status = dsgetdcname(ctx, priv->msg_ctx, r->in.domain,
     414             :                              NULL, NULL, flags, &info);
     415           0 :         if (!NT_STATUS_IS_OK(status)) {
     416           0 :                 libnetapi_set_error_string(ctx, "%s",
     417             :                         get_friendly_nt_error_msg(status));
     418           0 :                 return ntstatus_to_werror(status);
     419             :         }
     420             : 
     421           0 :         dc = strip_hostname(info->dc_unc);
     422             : 
     423           0 :         ads = ads_init(info->domain_name,
     424           0 :                        info->domain_name,
     425             :                        dc,
     426             :                        ADS_SASL_PLAIN);
     427           0 :         if (!ads) {
     428           0 :                 return WERR_GEN_FAILURE;
     429             :         }
     430             : 
     431           0 :         SAFE_FREE(ads->auth.user_name);
     432           0 :         if (r->in.account) {
     433           0 :                 ads->auth.user_name = SMB_STRDUP(r->in.account);
     434             :         } else {
     435           0 :                 const char *username = NULL;
     436             : 
     437           0 :                 libnetapi_get_username(ctx, &username);
     438           0 :                 if (username != NULL) {
     439           0 :                         ads->auth.user_name = SMB_STRDUP(username);
     440             :                 }
     441             :         }
     442             : 
     443           0 :         SAFE_FREE(ads->auth.password);
     444           0 :         if (r->in.password) {
     445           0 :                 ads->auth.password = SMB_STRDUP(r->in.password);
     446             :         } else {
     447           0 :                 const char *password = NULL;
     448             : 
     449           0 :                 libnetapi_get_password(ctx, &password);
     450           0 :                 if (password != NULL) {
     451           0 :                         ads->auth.password = SMB_STRDUP(password);
     452             :                 }
     453             :         }
     454             : 
     455           0 :         ads_status = ads_connect_user_creds(ads);
     456           0 :         if (!ADS_ERR_OK(ads_status)) {
     457           0 :                 ads_destroy(&ads);
     458           0 :                 return WERR_NERR_DEFAULTJOINREQUIRED;
     459             :         }
     460             : 
     461           0 :         ads_status = ads_get_joinable_ous(ads, ctx, &p, &s);
     462           0 :         if (!ADS_ERR_OK(ads_status)) {
     463           0 :                 ads_destroy(&ads);
     464           0 :                 return WERR_NERR_DEFAULTJOINREQUIRED;
     465             :         }
     466           0 :         *r->out.ous = discard_const_p(const char *, p);
     467           0 :         *r->out.ou_count = s;
     468             : 
     469           0 :         ads_destroy(&ads);
     470           0 :         return WERR_OK;
     471             : #else
     472           0 :         return WERR_NOT_SUPPORTED;
     473             : #endif
     474             : }
     475             : 
     476             : /****************************************************************
     477             : ****************************************************************/
     478             : 
     479           0 : WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
     480             :                            struct NetGetJoinableOUs *r)
     481             : {
     482           0 :         struct rpc_pipe_client *pipe_cli = NULL;
     483           0 :         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
     484             :         NTSTATUS status;
     485             :         WERROR werr;
     486             :         struct dcerpc_binding_handle *b;
     487             :         DATA_BLOB session_key;
     488             : 
     489           0 :         werr = libnetapi_open_pipe(ctx, r->in.server_name,
     490             :                                    &ndr_table_wkssvc,
     491             :                                    &pipe_cli);
     492           0 :         if (!W_ERROR_IS_OK(werr)) {
     493           0 :                 goto done;
     494             :         }
     495             : 
     496           0 :         b = pipe_cli->binding_handle;
     497             : 
     498           0 :         if (r->in.password) {
     499             : 
     500           0 :                 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
     501           0 :                 if (!NT_STATUS_IS_OK(status)) {
     502           0 :                         werr = ntstatus_to_werror(status);
     503           0 :                         goto done;
     504             :                 }
     505             : 
     506           0 :                 werr = encode_wkssvc_join_password_buffer(ctx,
     507             :                                                           r->in.password,
     508             :                                                           &session_key,
     509             :                                                           &encrypted_password);
     510           0 :                 if (!W_ERROR_IS_OK(werr)) {
     511           0 :                         goto done;
     512             :                 }
     513             :         }
     514             : 
     515           0 :         status = dcerpc_wkssvc_NetrGetJoinableOus2(b, talloc_tos(),
     516             :                                                    r->in.server_name,
     517             :                                                    r->in.domain,
     518             :                                                    r->in.account,
     519             :                                                    encrypted_password,
     520             :                                                    r->out.ou_count,
     521             :                                                    r->out.ous,
     522             :                                                    &werr);
     523           0 :         if (!NT_STATUS_IS_OK(status)) {
     524           0 :                 werr = ntstatus_to_werror(status);
     525           0 :                 goto done;
     526             :         }
     527             : 
     528           0 :  done:
     529           0 :         return werr;
     530             : }
     531             : 
     532             : /****************************************************************
     533             : ****************************************************************/
     534             : 
     535           0 : WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
     536             :                                   struct NetRenameMachineInDomain *r)
     537             : {
     538           0 :         struct rpc_pipe_client *pipe_cli = NULL;
     539           0 :         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
     540             :         NTSTATUS status;
     541             :         WERROR werr;
     542             :         struct dcerpc_binding_handle *b;
     543             :         DATA_BLOB session_key;
     544             : 
     545           0 :         werr = libnetapi_open_pipe(ctx, r->in.server_name,
     546             :                                    &ndr_table_wkssvc,
     547             :                                    &pipe_cli);
     548           0 :         if (!W_ERROR_IS_OK(werr)) {
     549           0 :                 goto done;
     550             :         }
     551             : 
     552           0 :         b = pipe_cli->binding_handle;
     553             : 
     554           0 :         if (r->in.password) {
     555             : 
     556           0 :                 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
     557           0 :                 if (!NT_STATUS_IS_OK(status)) {
     558           0 :                         werr = ntstatus_to_werror(status);
     559           0 :                         goto done;
     560             :                 }
     561             : 
     562           0 :                 werr = encode_wkssvc_join_password_buffer(ctx,
     563             :                                                           r->in.password,
     564             :                                                           &session_key,
     565             :                                                           &encrypted_password);
     566           0 :                 if (!W_ERROR_IS_OK(werr)) {
     567           0 :                         goto done;
     568             :                 }
     569             :         }
     570             : 
     571           0 :         status = dcerpc_wkssvc_NetrRenameMachineInDomain2(b, talloc_tos(),
     572             :                                                           r->in.server_name,
     573             :                                                           r->in.new_machine_name,
     574             :                                                           r->in.account,
     575             :                                                           encrypted_password,
     576             :                                                           r->in.rename_options,
     577             :                                                           &werr);
     578           0 :         if (!NT_STATUS_IS_OK(status)) {
     579           0 :                 werr = ntstatus_to_werror(status);
     580           0 :                 goto done;
     581             :         }
     582             : 
     583           0 :  done:
     584           0 :         return werr;
     585             : }
     586             : 
     587             : /****************************************************************
     588             : ****************************************************************/
     589             : 
     590           0 : WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
     591             :                                   struct NetRenameMachineInDomain *r)
     592             : {
     593           0 :         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);
     594             : }
     595             : 
     596             : /****************************************************************
     597             : ****************************************************************/
     598             : 
     599           0 : WERROR NetProvisionComputerAccount_r(struct libnetapi_ctx *ctx,
     600             :                                      struct NetProvisionComputerAccount *r)
     601             : {
     602           0 :         return NetProvisionComputerAccount_l(ctx, r);
     603             : }
     604             : 
     605             : /****************************************************************
     606             : ****************************************************************/
     607             : 
     608           6 : static WERROR NetProvisionComputerAccount_backend(struct libnetapi_ctx *ctx,
     609             :                                                   struct NetProvisionComputerAccount *r,
     610             :                                                   TALLOC_CTX *mem_ctx,
     611             :                                                   struct ODJ_PROVISION_DATA **p)
     612             : {
     613             :         WERROR werr;
     614           6 :         struct libnet_JoinCtx *j = NULL;
     615           6 :         int use_kerberos = 0;
     616           6 :         const char *username = NULL;
     617             : 
     618           6 :         werr = libnet_init_JoinCtx(mem_ctx, &j);
     619           6 :         if (!W_ERROR_IS_OK(werr)) {
     620           0 :                 return werr;
     621             :         }
     622             : 
     623           6 :         j->in.domain_name = talloc_strdup(j, r->in.domain);
     624           6 :         if (j->in.domain_name == NULL) {
     625           0 :                 talloc_free(j);
     626           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     627             :         }
     628             : 
     629           6 :         talloc_free(discard_const_p(char *, j->in.machine_name));
     630           6 :         j->in.machine_name = talloc_strdup(j, r->in.machine_name);
     631           6 :         if (j->in.machine_name == NULL) {
     632           0 :                 talloc_free(j);
     633           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     634             :         }
     635             : 
     636           6 :         if (r->in.dcname) {
     637           4 :                 j->in.dc_name = talloc_strdup(j, r->in.dcname);
     638           4 :                 if (j->in.dc_name == NULL) {
     639           0 :                         talloc_free(j);
     640           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     641             :                 }
     642             :         }
     643             : 
     644           6 :         if (r->in.machine_account_ou) {
     645           0 :                 j->in.account_ou = talloc_strdup(j, r->in.machine_account_ou);
     646           0 :                 if (j->in.account_ou == NULL) {
     647           0 :                         talloc_free(j);
     648           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     649             :                 }
     650             :         }
     651             : 
     652           6 :         libnetapi_get_username(ctx, &username);
     653           6 :         if (username == NULL) {
     654           0 :                 talloc_free(j);
     655           0 :                 return WERR_NERR_BADUSERNAME;
     656             :         }
     657             : 
     658           6 :         j->in.admin_account = talloc_strdup(j, username);
     659           6 :         if (j->in.admin_account == NULL) {
     660           0 :                 talloc_free(j);
     661           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     662             :         }
     663             : 
     664           6 :         libnetapi_get_use_kerberos(ctx, &use_kerberos);
     665           6 :         if (!use_kerberos) {
     666           6 :                 const char *password = NULL;
     667             : 
     668           6 :                 libnetapi_get_password(ctx, &password);
     669           6 :                 if (password == NULL) {
     670           0 :                         talloc_free(j);
     671           0 :                         return WERR_NERR_BADPASSWORD;
     672             :                 }
     673           6 :                 j->in.admin_password = talloc_strdup(j, password);
     674           6 :                 if (j->in.admin_password == NULL) {
     675           0 :                         talloc_free(j);
     676           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     677             :                 }
     678             :         }
     679             : 
     680           6 :         j->in.use_kerberos = use_kerberos;
     681           6 :         j->in.debug = true;
     682           6 :         j->in.join_flags     = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
     683             :                                   WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE;
     684             : 
     685           6 :         if (r->in.options & NETSETUP_PROVISION_REUSE_ACCOUNT) {
     686           0 :                 j->in.join_flags |= WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
     687             :         }
     688             : 
     689           6 :         if (r->in.options & NETSETUP_PROVISION_USE_DEFAULT_PASSWORD) {
     690           2 :                 j->in.join_flags |= WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
     691           2 :                 j->in.machine_password = talloc_strdup(j, r->in.machine_name);
     692           2 :                 if (j->in.machine_password == NULL) {
     693           0 :                         talloc_free(j);
     694           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     695             :                 }
     696             :         }
     697             : 
     698           6 :         j->in.provision_computer_account_only = true;
     699             : 
     700           6 :         werr = libnet_Join(mem_ctx, j);
     701           6 :         if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
     702           0 :                 libnetapi_set_error_string(ctx, "%s", j->out.error_string);
     703           0 :                 talloc_free(j);
     704           0 :                 return werr;
     705             :         }
     706             : 
     707           6 :         werr = libnet_odj_compose_ODJ_PROVISION_DATA(mem_ctx, j, p);
     708           6 :         if (!W_ERROR_IS_OK(werr)) {
     709           0 :                 talloc_free(j);
     710           0 :                 return werr;
     711             :         }
     712             : 
     713           6 :         TALLOC_FREE(j);
     714             : 
     715           6 :         return WERR_OK;
     716             : }
     717             : 
     718           6 : WERROR NetProvisionComputerAccount_l(struct libnetapi_ctx *ctx,
     719             :                                      struct NetProvisionComputerAccount *r)
     720             : {
     721             :         WERROR werr;
     722             :         enum ndr_err_code ndr_err;
     723             :         const char *b64_bin_data_str;
     724             :         DATA_BLOB blob;
     725             :         struct ODJ_PROVISION_DATA_serialized_ptr odj_provision_data;
     726             :         struct ODJ_PROVISION_DATA *p;
     727           6 :         TALLOC_CTX *mem_ctx = talloc_new(ctx);
     728             : 
     729           9 :         if (r->in.provision_bin_data == NULL &&
     730           6 :             r->in.provision_text_data == NULL) {
     731           0 :                 return WERR_INVALID_PARAMETER;
     732             :         }
     733           6 :         if (r->in.provision_bin_data != NULL &&
     734           0 :             r->in.provision_text_data != NULL) {
     735           0 :                 return WERR_INVALID_PARAMETER;
     736             :         }
     737           9 :         if (r->in.provision_bin_data == NULL &&
     738           6 :             r->in.provision_bin_data_size != NULL) {
     739           0 :                 return WERR_INVALID_PARAMETER;
     740             :         }
     741           6 :         if (r->in.provision_bin_data != NULL &&
     742           0 :            r->in.provision_bin_data_size == NULL) {
     743           0 :                 return WERR_INVALID_PARAMETER;
     744             :         }
     745             : 
     746           6 :         if (r->in.domain == NULL) {
     747           0 :                 return WERR_INVALID_PARAMETER;
     748             :         }
     749             : 
     750           6 :         if (r->in.machine_name == NULL) {
     751           0 :                 return WERR_INVALID_PARAMETER;
     752             :         }
     753             : 
     754           6 :         werr = NetProvisionComputerAccount_backend(ctx, r, mem_ctx, &p);
     755           6 :         if (!W_ERROR_IS_OK(werr)) {
     756           0 :                 talloc_free(mem_ctx);
     757           0 :                 return werr;
     758             :         }
     759             : 
     760           6 :         ZERO_STRUCT(odj_provision_data);
     761             : 
     762           6 :         odj_provision_data.s.p = p;
     763             : 
     764           6 :         ndr_err = ndr_push_struct_blob(&blob, ctx, &odj_provision_data,
     765             :                 (ndr_push_flags_fn_t)ndr_push_ODJ_PROVISION_DATA_serialized_ptr);
     766           6 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     767           0 :                 talloc_free(mem_ctx);
     768           0 :                 return W_ERROR(NERR_BadOfflineJoinInfo);
     769             :         }
     770             : 
     771           6 :         talloc_free(mem_ctx);
     772             : 
     773           6 :         if (r->out.provision_text_data != NULL) {
     774           6 :                 b64_bin_data_str = base64_encode_data_blob(ctx, blob);
     775           6 :                 if (b64_bin_data_str == NULL) {
     776           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     777             :                 }
     778           6 :                 *r->out.provision_text_data = b64_bin_data_str;
     779             :         }
     780             : 
     781           6 :         if (r->out.provision_bin_data != NULL &&
     782           0 :             r->out.provision_bin_data_size != NULL) {
     783           0 :                 *r->out.provision_bin_data = blob.data;
     784           0 :                 *r->out.provision_bin_data_size = blob.length;
     785             :         }
     786             : 
     787           6 :         return werr;
     788             : }
     789             : 
     790             : /****************************************************************
     791             : ****************************************************************/
     792             : 
     793           0 : WERROR NetRequestOfflineDomainJoin_r(struct libnetapi_ctx *ctx,
     794             :                                      struct NetRequestOfflineDomainJoin *r)
     795             : {
     796           0 :         return WERR_NOT_SUPPORTED;
     797             : }
     798             : 
     799             : /****************************************************************
     800             : ****************************************************************/
     801             : 
     802           6 : static WERROR NetRequestOfflineDomainJoin_backend(struct libnetapi_ctx *ctx,
     803             :                                                   const struct ODJ_WIN7BLOB *win7blob,
     804             :                                                   const struct ODJ_PROVISION_DATA *odj_provision_data)
     805             : {
     806           6 :         struct libnet_JoinCtx *j = NULL;
     807             :         WERROR werr;
     808             : 
     809           6 :         werr = libnet_init_JoinCtx(ctx, &j);
     810           6 :         if (!W_ERROR_IS_OK(werr)) {
     811           0 :                 return werr;
     812             :         }
     813             : 
     814           6 :         j->in.domain_name = talloc_strdup(j, win7blob->lpDomain);
     815           6 :         if (j->in.domain_name == NULL) {
     816           0 :                 talloc_free(j);
     817           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     818             :         }
     819             : 
     820           6 :         talloc_free(discard_const_p(char *, j->in.machine_name));
     821           6 :         j->in.machine_name = talloc_strdup(j, win7blob->lpMachineName);
     822           6 :         if (j->in.machine_name == NULL) {
     823           0 :                 talloc_free(j);
     824           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     825             :         }
     826             : 
     827           6 :         j->in.machine_password = talloc_strdup(j, win7blob->lpMachinePassword);
     828           6 :         if (j->in.machine_password == NULL) {
     829           0 :                 talloc_free(j);
     830           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     831             :         }
     832             : 
     833           6 :         j->in.request_offline_join = true;
     834           6 :         j->in.odj_provision_data = discard_const(odj_provision_data);
     835           6 :         j->in.debug = true;
     836           6 :         j->in.join_flags     = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
     837             :                                   WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
     838             : 
     839           6 :         werr = libnet_Join(j, j);
     840           6 :         if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
     841           0 :                 libnetapi_set_error_string(ctx, "%s", j->out.error_string);
     842           0 :                 talloc_free(j);
     843           0 :                 return werr;
     844             :         }
     845             : 
     846           6 :         TALLOC_FREE(j);
     847             : 
     848           6 :         return WERR_OK;
     849             : }
     850             : 
     851           6 : WERROR NetRequestOfflineDomainJoin_l(struct libnetapi_ctx *ctx,
     852             :                                      struct NetRequestOfflineDomainJoin *r)
     853             : {
     854             :         DATA_BLOB blob, blob_base64;
     855             :         enum ndr_err_code ndr_err;
     856             :         struct ODJ_PROVISION_DATA_serialized_ptr odj_provision_data;
     857             :         bool ok;
     858           6 :         struct ODJ_WIN7BLOB win7blob = { 0 };
     859             :         WERROR werr;
     860             : 
     861           9 :         if (r->in.provision_bin_data == NULL ||
     862           6 :             r->in.provision_bin_data_size == 0) {
     863           0 :                 return W_ERROR(NERR_NoOfflineJoinInfo);
     864             :         }
     865             : 
     866           6 :         if (r->in.provision_bin_data_size < 2) {
     867           0 :                 return W_ERROR(NERR_BadOfflineJoinInfo);
     868             :         }
     869             : 
     870           9 :         if (r->in.provision_bin_data[0] == 0xff &&
     871           6 :             r->in.provision_bin_data[1] == 0xfe) {
     872           9 :                 ok = convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX,
     873           6 :                                            r->in.provision_bin_data+2,
     874           6 :                                            r->in.provision_bin_data_size-2,
     875             :                                            &blob_base64.data,
     876             :                                            &blob_base64.length);
     877           9 :                 if (!ok) {
     878           0 :                         return W_ERROR(NERR_BadOfflineJoinInfo);
     879             :                 }
     880             :         } else {
     881           0 :                 blob_base64 = data_blob(r->in.provision_bin_data,
     882             :                                         r->in.provision_bin_data_size);
     883             :         }
     884             : 
     885           6 :         blob = base64_decode_data_blob_talloc(ctx, (const char *)blob_base64.data);
     886             : 
     887           6 :         ndr_err = ndr_pull_struct_blob(&blob, ctx, &odj_provision_data,
     888             :                 (ndr_pull_flags_fn_t)ndr_pull_ODJ_PROVISION_DATA_serialized_ptr);
     889           6 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     890           0 :                 return W_ERROR(NERR_BadOfflineJoinInfo);
     891             :         }
     892             : 
     893           6 :         if (DEBUGLEVEL >= 10) {
     894           0 :                 NDR_PRINT_DEBUG(ODJ_PROVISION_DATA_serialized_ptr, &odj_provision_data);
     895             :         }
     896             : 
     897           6 :         if (odj_provision_data.s.p->ulVersion != 1) {
     898           0 :                 return W_ERROR(NERR_ProvisioningBlobUnsupported);
     899             :         }
     900             : 
     901           6 :         werr = libnet_odj_find_win7blob(odj_provision_data.s.p, &win7blob);
     902           6 :         if (!W_ERROR_IS_OK(werr)) {
     903           0 :                 return werr;
     904             :         }
     905             : 
     906           6 :         if (!(r->in.options & NETSETUP_PROVISION_ONLINE_CALLER)) {
     907           0 :                 return WERR_NERR_SETUPNOTJOINED;
     908             :         }
     909             : 
     910           6 :         werr = NetRequestOfflineDomainJoin_backend(ctx,
     911             :                                                    &win7blob,
     912           6 :                                                    odj_provision_data.s.p);
     913           6 :         if (!W_ERROR_IS_OK(werr)) {
     914           0 :                 return werr;
     915             :         }
     916             : 
     917           6 :         return W_ERROR(NERR_JoinPerformedMustRestart);
     918             : }

Generated by: LCOV version 1.13