root/source3/lib/netapi/joindomain.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. NetJoinDomain_l
  2. NetJoinDomain_r
  3. NetUnjoinDomain_l
  4. NetUnjoinDomain_r
  5. NetGetJoinInformation_r
  6. NetGetJoinInformation_l
  7. NetGetJoinableOUs_l
  8. NetGetJoinableOUs_r
  9. NetRenameMachineInDomain_r
  10. NetRenameMachineInDomain_l

   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 
  22 #include "librpc/gen_ndr/libnetapi.h"
  23 #include "lib/netapi/netapi.h"
  24 #include "lib/netapi/netapi_private.h"
  25 #include "lib/netapi/libnetapi.h"
  26 #include "libnet/libnet.h"
  27 
  28 /****************************************************************
  29 ****************************************************************/
  30 
  31 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  32                        struct NetJoinDomain *r)
  33 {
  34         struct libnet_JoinCtx *j = NULL;
  35         WERROR werr;
  36 
  37         if (!r->in.domain) {
  38                 return WERR_INVALID_PARAM;
  39         }
  40 
  41         werr = libnet_init_JoinCtx(mem_ctx, &j);
  42         W_ERROR_NOT_OK_RETURN(werr);
  43 
  44         j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
  45         W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
  46 
  47         if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
  48                 NTSTATUS status;
  49                 struct netr_DsRGetDCNameInfo *info = NULL;
  50                 const char *dc = NULL;
  51                 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
  52                                  DS_WRITABLE_REQUIRED |
  53                                  DS_RETURN_DNS_NAME;
  54                 status = dsgetdcname(mem_ctx, NULL, r->in.domain,
  55                                      NULL, NULL, flags, &info);
  56                 if (!NT_STATUS_IS_OK(status)) {
  57                         libnetapi_set_error_string(mem_ctx,
  58                                 "%s", get_friendly_nt_error_msg(status));
  59                         return ntstatus_to_werror(status);
  60                 }
  61 
  62                 dc = strip_hostname(info->dc_unc);
  63                 j->in.dc_name = talloc_strdup(mem_ctx, dc);
  64                 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
  65         }
  66 
  67         if (r->in.account_ou) {
  68                 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
  69                 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
  70         }
  71 
  72         if (r->in.account) {
  73                 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
  74                 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
  75         }
  76 
  77         if (r->in.password) {
  78                 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
  79                 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
  80         }
  81 
  82         j->in.join_flags = r->in.join_flags;
  83         j->in.modify_config = true;
  84         j->in.debug = true;
  85 
  86         werr = libnet_Join(mem_ctx, j);
  87         if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
  88                 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
  89         }
  90         TALLOC_FREE(j);
  91 
  92         return werr;
  93 }
  94 
  95 /****************************************************************
  96 ****************************************************************/
  97 
  98 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  99                        struct NetJoinDomain *r)
 100 {
 101         struct rpc_pipe_client *pipe_cli = NULL;
 102         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
 103         NTSTATUS status;
 104         WERROR werr;
 105         unsigned int old_timeout = 0;
 106 
 107         werr = libnetapi_open_pipe(ctx, r->in.server,
 108                                    &ndr_table_wkssvc.syntax_id,
 109                                    &pipe_cli);
 110         if (!W_ERROR_IS_OK(werr)) {
 111                 goto done;
 112         }
 113 
 114         if (r->in.password) {
 115                 encode_wkssvc_join_password_buffer(ctx,
 116                                                    r->in.password,
 117                                                    &pipe_cli->auth->user_session_key,
 118                                                    &encrypted_password);
 119         }
 120 
 121         old_timeout = rpccli_set_timeout(pipe_cli, 600000);
 122 
 123         status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
 124                                                r->in.server,
 125                                                r->in.domain,
 126                                                r->in.account_ou,
 127                                                r->in.account,
 128                                                encrypted_password,
 129                                                r->in.join_flags,
 130                                                &werr);
 131         if (!NT_STATUS_IS_OK(status)) {
 132                 werr = ntstatus_to_werror(status);
 133                 goto done;
 134         }
 135 
 136  done:
 137         if (pipe_cli && old_timeout) {
 138                 rpccli_set_timeout(pipe_cli, old_timeout);
 139         }
 140 
 141         return werr;
 142 }
 143 /****************************************************************
 144 ****************************************************************/
 145 
 146 WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 147                          struct NetUnjoinDomain *r)
 148 {
 149         struct libnet_UnjoinCtx *u = NULL;
 150         struct dom_sid domain_sid;
 151         const char *domain = NULL;
 152         WERROR werr;
 153 
 154         if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
 155                 return WERR_SETUP_NOT_JOINED;
 156         }
 157 
 158         werr = libnet_init_UnjoinCtx(mem_ctx, &u);
 159         W_ERROR_NOT_OK_RETURN(werr);
 160 
 161         if (lp_realm()) {
 162                 domain = lp_realm();
 163         } else {
 164                 domain = lp_workgroup();
 165         }
 166 
 167         if (r->in.server_name) {
 168                 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
 169                 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
 170         } else {
 171                 NTSTATUS status;
 172                 struct netr_DsRGetDCNameInfo *info = NULL;
 173                 const char *dc = NULL;
 174                 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
 175                                  DS_WRITABLE_REQUIRED |
 176                                  DS_RETURN_DNS_NAME;
 177                 status = dsgetdcname(mem_ctx, NULL, domain,
 178                                      NULL, NULL, flags, &info);
 179                 if (!NT_STATUS_IS_OK(status)) {
 180                         libnetapi_set_error_string(mem_ctx,
 181                                 "failed to find DC for domain %s: %s",
 182                                 domain,
 183                                 get_friendly_nt_error_msg(status));
 184                         return ntstatus_to_werror(status);
 185                 }
 186 
 187                 dc = strip_hostname(info->dc_unc);
 188                 u->in.dc_name = talloc_strdup(mem_ctx, dc);
 189                 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
 190 
 191                 u->in.domain_name = domain;
 192         }
 193 
 194         if (r->in.account) {
 195                 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
 196                 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
 197         }
 198 
 199         if (r->in.password) {
 200                 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
 201                 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
 202         }
 203 
 204         u->in.domain_name = domain;
 205         u->in.unjoin_flags = r->in.unjoin_flags;
 206         u->in.delete_machine_account = false;
 207         u->in.modify_config = true;
 208         u->in.debug = true;
 209 
 210         u->in.domain_sid = &domain_sid;
 211 
 212         werr = libnet_Unjoin(mem_ctx, u);
 213         if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
 214                 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
 215         }
 216         TALLOC_FREE(u);
 217 
 218         return werr;
 219 }
 220 
 221 /****************************************************************
 222 ****************************************************************/
 223 
 224 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 225                          struct NetUnjoinDomain *r)
 226 {
 227         struct rpc_pipe_client *pipe_cli = NULL;
 228         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
 229         NTSTATUS status;
 230         WERROR werr;
 231         unsigned int old_timeout = 0;
 232 
 233         werr = libnetapi_open_pipe(ctx, r->in.server_name,
 234                                    &ndr_table_wkssvc.syntax_id,
 235                                    &pipe_cli);
 236         if (!W_ERROR_IS_OK(werr)) {
 237                 goto done;
 238         }
 239 
 240         if (r->in.password) {
 241                 encode_wkssvc_join_password_buffer(ctx,
 242                                                    r->in.password,
 243                                                    &pipe_cli->auth->user_session_key,
 244                                                    &encrypted_password);
 245         }
 246 
 247         old_timeout = rpccli_set_timeout(pipe_cli, 60000);
 248 
 249         status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
 250                                                  r->in.server_name,
 251                                                  r->in.account,
 252                                                  encrypted_password,
 253                                                  r->in.unjoin_flags,
 254                                                  &werr);
 255         if (!NT_STATUS_IS_OK(status)) {
 256                 werr = ntstatus_to_werror(status);
 257                 goto done;
 258         }
 259 
 260  done:
 261         if (pipe_cli && old_timeout) {
 262                 rpccli_set_timeout(pipe_cli, old_timeout);
 263         }
 264 
 265         return werr;
 266 }
 267 
 268 /****************************************************************
 269 ****************************************************************/
 270 
 271 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 272                                struct NetGetJoinInformation *r)
 273 {
 274         struct rpc_pipe_client *pipe_cli = NULL;
 275         NTSTATUS status;
 276         WERROR werr;
 277         const char *buffer = NULL;
 278 
 279         werr = libnetapi_open_pipe(ctx, r->in.server_name,
 280                                    &ndr_table_wkssvc.syntax_id,
 281                                    &pipe_cli);
 282         if (!W_ERROR_IS_OK(werr)) {
 283                 goto done;
 284         }
 285 
 286         status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
 287                                                       r->in.server_name,
 288                                                       &buffer,
 289                                                       (enum wkssvc_NetJoinStatus *)r->out.name_type,
 290                                                       &werr);
 291         if (!NT_STATUS_IS_OK(status)) {
 292                 werr = ntstatus_to_werror(status);
 293                 goto done;
 294         }
 295 
 296         *r->out.name_buffer = talloc_strdup(ctx, buffer);
 297         W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
 298 
 299  done:
 300         return werr;
 301 }
 302 
 303 /****************************************************************
 304 ****************************************************************/
 305 
 306 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 307                                struct NetGetJoinInformation *r)
 308 {
 309         if ((lp_security() == SEC_ADS) && lp_realm()) {
 310                 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
 311         } else {
 312                 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
 313         }
 314         if (!*r->out.name_buffer) {
 315                 return WERR_NOMEM;
 316         }
 317 
 318         switch (lp_server_role()) {
 319                 case ROLE_DOMAIN_MEMBER:
 320                 case ROLE_DOMAIN_PDC:
 321                 case ROLE_DOMAIN_BDC:
 322                         *r->out.name_type = NetSetupDomainName;
 323                         break;
 324                 case ROLE_STANDALONE:
 325                 default:
 326                         *r->out.name_type = NetSetupWorkgroupName;
 327                         break;
 328         }
 329 
 330         return WERR_OK;
 331 }
 332 
 333 /****************************************************************
 334 ****************************************************************/
 335 
 336 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 337                            struct NetGetJoinableOUs *r)
 338 {
 339 #ifdef WITH_ADS
 340         NTSTATUS status;
 341         ADS_STATUS ads_status;
 342         ADS_STRUCT *ads = NULL;
 343         struct netr_DsRGetDCNameInfo *info = NULL;
 344         const char *dc = NULL;
 345         uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
 346                          DS_RETURN_DNS_NAME;
 347 
 348         status = dsgetdcname(ctx, NULL, r->in.domain,
 349                              NULL, NULL, flags, &info);
 350         if (!NT_STATUS_IS_OK(status)) {
 351                 libnetapi_set_error_string(ctx, "%s",
 352                         get_friendly_nt_error_msg(status));
 353                 return ntstatus_to_werror(status);
 354         }
 355 
 356         dc = strip_hostname(info->dc_unc);
 357 
 358         ads = ads_init(info->domain_name, info->domain_name, dc);
 359         if (!ads) {
 360                 return WERR_GENERAL_FAILURE;
 361         }
 362 
 363         SAFE_FREE(ads->auth.user_name);
 364         if (r->in.account) {
 365                 ads->auth.user_name = SMB_STRDUP(r->in.account);
 366         } else if (ctx->username) {
 367                 ads->auth.user_name = SMB_STRDUP(ctx->username);
 368         }
 369 
 370         SAFE_FREE(ads->auth.password);
 371         if (r->in.password) {
 372                 ads->auth.password = SMB_STRDUP(r->in.password);
 373         } else if (ctx->password) {
 374                 ads->auth.password = SMB_STRDUP(ctx->password);
 375         }
 376 
 377         ads_status = ads_connect_user_creds(ads);
 378         if (!ADS_ERR_OK(ads_status)) {
 379                 ads_destroy(&ads);
 380                 return WERR_DEFAULT_JOIN_REQUIRED;
 381         }
 382 
 383         ads_status = ads_get_joinable_ous(ads, ctx,
 384                                           (char ***)r->out.ous,
 385                                           (size_t *)r->out.ou_count);
 386         if (!ADS_ERR_OK(ads_status)) {
 387                 ads_destroy(&ads);
 388                 return WERR_DEFAULT_JOIN_REQUIRED;
 389         }
 390 
 391         ads_destroy(&ads);
 392         return WERR_OK;
 393 #else
 394         return WERR_NOT_SUPPORTED;
 395 #endif
 396 }
 397 
 398 /****************************************************************
 399 ****************************************************************/
 400 
 401 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 402                            struct NetGetJoinableOUs *r)
 403 {
 404         struct rpc_pipe_client *pipe_cli = NULL;
 405         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
 406         NTSTATUS status;
 407         WERROR werr;
 408 
 409         werr = libnetapi_open_pipe(ctx, r->in.server_name,
 410                                    &ndr_table_wkssvc.syntax_id,
 411                                    &pipe_cli);
 412         if (!W_ERROR_IS_OK(werr)) {
 413                 goto done;
 414         }
 415 
 416         if (r->in.password) {
 417                 encode_wkssvc_join_password_buffer(ctx,
 418                                                    r->in.password,
 419                                                    &pipe_cli->auth->user_session_key,
 420                                                    &encrypted_password);
 421         }
 422 
 423         status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
 424                                                    r->in.server_name,
 425                                                    r->in.domain,
 426                                                    r->in.account,
 427                                                    encrypted_password,
 428                                                    r->out.ou_count,
 429                                                    r->out.ous,
 430                                                    &werr);
 431         if (!NT_STATUS_IS_OK(status)) {
 432                 werr = ntstatus_to_werror(status);
 433                 goto done;
 434         }
 435 
 436  done:
 437         return werr;
 438 }
 439 
 440 /****************************************************************
 441 ****************************************************************/
 442 
 443 WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 444                                   struct NetRenameMachineInDomain *r)
 445 {
 446         struct rpc_pipe_client *pipe_cli = NULL;
 447         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
 448         NTSTATUS status;
 449         WERROR werr;
 450 
 451         werr = libnetapi_open_pipe(ctx, r->in.server_name,
 452                                    &ndr_table_wkssvc.syntax_id,
 453                                    &pipe_cli);
 454         if (!W_ERROR_IS_OK(werr)) {
 455                 goto done;
 456         }
 457 
 458         if (r->in.password) {
 459                 encode_wkssvc_join_password_buffer(ctx,
 460                                                    r->in.password,
 461                                                    &pipe_cli->auth->user_session_key,
 462                                                    &encrypted_password);
 463         }
 464 
 465         status = rpccli_wkssvc_NetrRenameMachineInDomain2(pipe_cli, ctx,
 466                                                           r->in.server_name,
 467                                                           r->in.new_machine_name,
 468                                                           r->in.account,
 469                                                           encrypted_password,
 470                                                           r->in.rename_options,
 471                                                           &werr);
 472         if (!NT_STATUS_IS_OK(status)) {
 473                 werr = ntstatus_to_werror(status);
 474                 goto done;
 475         }
 476 
 477  done:
 478         return werr;
 479 }
 480 
 481 /****************************************************************
 482 ****************************************************************/
 483 
 484 WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 485                                   struct NetRenameMachineInDomain *r)
 486 {
 487         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);
 488 }

/* [<][>][^][v][top][bottom][index][help] */