root/source3/rpc_client/cli_netlogon.c

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

DEFINITIONS

This source file includes following definitions.
  1. rpccli_netlogon_setup_creds
  2. rpccli_netlogon_sam_logon
  3. rpccli_netlogon_sam_network_logon
  4. rpccli_netlogon_sam_network_logon_ex
  5. rpccli_netlogon_set_trust_password

   1 /*
   2    Unix SMB/CIFS implementation.
   3    NT Domain Authentication SMB / MSRPC client
   4    Copyright (C) Andrew Tridgell 1992-2000
   5    Copyright (C) Jeremy Allison                    1998.
   6    Largely re-written by Jeremy Allison (C)        2005.
   7    Copyright (C) Guenther Deschner                 2008.
   8 
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13 
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18 
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "includes.h"
  24 
  25 /****************************************************************************
  26  Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
  27  credentials chain. Stores the credentials in the struct dcinfo in the
  28  netlogon pipe struct.
  29 ****************************************************************************/
  30 
  31 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
     /* [<][>][^][v][top][bottom][index][help] */
  32                                      const char *server_name,
  33                                      const char *domain,
  34                                      const char *clnt_name,
  35                                      const char *machine_account,
  36                                      const unsigned char machine_pwd[16],
  37                                      enum netr_SchannelType sec_chan_type,
  38                                      uint32_t *neg_flags_inout)
  39 {
  40         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
  41         struct netr_Credential clnt_chal_send;
  42         struct netr_Credential srv_chal_recv;
  43         struct dcinfo *dc;
  44         bool retried = false;
  45 
  46         SMB_ASSERT(ndr_syntax_id_equal(&cli->abstract_syntax,
  47                                        &ndr_table_netlogon.syntax_id));
  48 
  49         TALLOC_FREE(cli->dc);
  50         cli->dc = talloc_zero(cli, struct dcinfo);
  51         if (cli->dc == NULL) {
  52                 return NT_STATUS_NO_MEMORY;
  53         }
  54         dc = cli->dc;
  55 
  56         /* Store the machine account password we're going to use. */
  57         memcpy(dc->mach_pw, machine_pwd, 16);
  58 
  59         fstrcpy(dc->remote_machine, "\\\\");
  60         fstrcat(dc->remote_machine, server_name);
  61 
  62         fstrcpy(dc->domain, domain);
  63 
  64         fstr_sprintf( dc->mach_acct, "%s$", machine_account);
  65 
  66  again:
  67         /* Create the client challenge. */
  68         generate_random_buffer(clnt_chal_send.data, 8);
  69 
  70         /* Get the server challenge. */
  71         result = rpccli_netr_ServerReqChallenge(cli, talloc_tos(),
  72                                                 dc->remote_machine,
  73                                                 clnt_name,
  74                                                 &clnt_chal_send,
  75                                                 &srv_chal_recv);
  76         if (!NT_STATUS_IS_OK(result)) {
  77                 return result;
  78         }
  79 
  80         /* Calculate the session key and client credentials */
  81         creds_client_init(*neg_flags_inout,
  82                         dc,
  83                         &clnt_chal_send,
  84                         &srv_chal_recv,
  85                         machine_pwd,
  86                         &clnt_chal_send);
  87 
  88         /*
  89          * Send client auth-2 challenge and receive server repy.
  90          */
  91 
  92         result = rpccli_netr_ServerAuthenticate2(cli, talloc_tos(),
  93                                                  dc->remote_machine,
  94                                                  dc->mach_acct,
  95                                                  sec_chan_type,
  96                                                  clnt_name,
  97                                                  &clnt_chal_send, /* input. */
  98                                                  &srv_chal_recv, /* output. */
  99                                                  neg_flags_inout);
 100 
 101         /* we might be talking to NT4, so let's downgrade in that case and retry
 102          * with the returned neg_flags - gd */
 103 
 104         if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) {
 105                 retried = true;
 106                 goto again;
 107         }
 108 
 109         if (!NT_STATUS_IS_OK(result)) {
 110                 return result;
 111         }
 112 
 113         /*
 114          * Check the returned value using the initial
 115          * server received challenge.
 116          */
 117 
 118         if (!netlogon_creds_client_check(dc, &srv_chal_recv)) {
 119                 /*
 120                  * Server replied with bad credential. Fail.
 121                  */
 122                 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
 123                         "replied with bad credential\n",
 124                         cli->desthost ));
 125                 return NT_STATUS_ACCESS_DENIED;
 126         }
 127 
 128         DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
 129                 "chain established.\n",
 130                 cli->desthost ));
 131 
 132         return NT_STATUS_OK;
 133 }
 134 
 135 /* Logon domain user */
 136 
 137 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
     /* [<][>][^][v][top][bottom][index][help] */
 138                                    TALLOC_CTX *mem_ctx,
 139                                    uint32 logon_parameters,
 140                                    const char *domain,
 141                                    const char *username,
 142                                    const char *password,
 143                                    const char *workstation,
 144                                    int logon_type)
 145 {
 146         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 147         struct netr_Authenticator clnt_creds;
 148         struct netr_Authenticator ret_creds;
 149         union netr_LogonLevel *logon;
 150         union netr_Validation validation;
 151         uint8_t authoritative;
 152         int validation_level = 3;
 153         fstring clnt_name_slash;
 154         uint8 zeros[16];
 155 
 156         ZERO_STRUCT(ret_creds);
 157         ZERO_STRUCT(zeros);
 158 
 159         logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
 160         if (!logon) {
 161                 return NT_STATUS_NO_MEMORY;
 162         }
 163 
 164         if (workstation) {
 165                 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
 166         } else {
 167                 fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
 168         }
 169 
 170         /* Initialise input parameters */
 171 
 172         netlogon_creds_client_step(cli->dc, &clnt_creds);
 173 
 174         switch (logon_type) {
 175         case NetlogonInteractiveInformation: {
 176 
 177                 struct netr_PasswordInfo *password_info;
 178 
 179                 struct samr_Password lmpassword;
 180                 struct samr_Password ntpassword;
 181 
 182                 unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16];
 183 
 184                 unsigned char lm_owf[16];
 185                 unsigned char nt_owf[16];
 186                 unsigned char key[16];
 187 
 188                 password_info = TALLOC_ZERO_P(mem_ctx, struct netr_PasswordInfo);
 189                 if (!password_info) {
 190                         return NT_STATUS_NO_MEMORY;
 191                 }
 192 
 193                 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
 194 
 195 #ifdef DEBUG_PASSWORD
 196                 DEBUG(100,("lm cypher:"));
 197                 dump_data(100, lm_owf_user_pwd, 16);
 198 
 199                 DEBUG(100,("nt cypher:"));
 200                 dump_data(100, nt_owf_user_pwd, 16);
 201 #endif
 202                 memset(key, 0, 16);
 203                 memcpy(key, cli->dc->sess_key, 8);
 204 
 205                 memcpy(lm_owf, lm_owf_user_pwd, 16);
 206                 SamOEMhash(lm_owf, key, 16);
 207                 memcpy(nt_owf, nt_owf_user_pwd, 16);
 208                 SamOEMhash(nt_owf, key, 16);
 209 
 210 #ifdef DEBUG_PASSWORD
 211                 DEBUG(100,("encrypt of lm owf password:"));
 212                 dump_data(100, lm_owf, 16);
 213 
 214                 DEBUG(100,("encrypt of nt owf password:"));
 215                 dump_data(100, nt_owf, 16);
 216 #endif
 217                 memcpy(lmpassword.hash, lm_owf, 16);
 218                 memcpy(ntpassword.hash, nt_owf, 16);
 219 
 220                 init_netr_PasswordInfo(password_info,
 221                                        domain,
 222                                        logon_parameters,
 223                                        0xdead,
 224                                        0xbeef,
 225                                        username,
 226                                        clnt_name_slash,
 227                                        lmpassword,
 228                                        ntpassword);
 229 
 230                 logon->password = password_info;
 231 
 232                 break;
 233         }
 234         case NetlogonNetworkInformation: {
 235                 struct netr_NetworkInfo *network_info;
 236                 uint8 chal[8];
 237                 unsigned char local_lm_response[24];
 238                 unsigned char local_nt_response[24];
 239                 struct netr_ChallengeResponse lm;
 240                 struct netr_ChallengeResponse nt;
 241 
 242                 ZERO_STRUCT(lm);
 243                 ZERO_STRUCT(nt);
 244 
 245                 network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
 246                 if (!network_info) {
 247                         return NT_STATUS_NO_MEMORY;
 248                 }
 249 
 250                 generate_random_buffer(chal, 8);
 251 
 252                 SMBencrypt(password, chal, local_lm_response);
 253                 SMBNTencrypt(password, chal, local_nt_response);
 254 
 255                 lm.length = 24;
 256                 lm.data = local_lm_response;
 257 
 258                 nt.length = 24;
 259                 nt.data = local_nt_response;
 260 
 261                 init_netr_NetworkInfo(network_info,
 262                                       domain,
 263                                       logon_parameters,
 264                                       0xdead,
 265                                       0xbeef,
 266                                       username,
 267                                       clnt_name_slash,
 268                                       chal,
 269                                       nt,
 270                                       lm);
 271 
 272                 logon->network = network_info;
 273 
 274                 break;
 275         }
 276         default:
 277                 DEBUG(0, ("switch value %d not supported\n",
 278                         logon_type));
 279                 return NT_STATUS_INVALID_INFO_CLASS;
 280         }
 281 
 282         result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
 283                                            cli->dc->remote_machine,
 284                                            global_myname(),
 285                                            &clnt_creds,
 286                                            &ret_creds,
 287                                            logon_type,
 288                                            logon,
 289                                            validation_level,
 290                                            &validation,
 291                                            &authoritative);
 292 
 293         if (memcmp(zeros, &ret_creds.cred.data, sizeof(ret_creds.cred.data)) != 0) {
 294                 /* Check returned credentials if present. */
 295                 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
 296                         DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
 297                         return NT_STATUS_ACCESS_DENIED;
 298                 }
 299         }
 300 
 301         return result;
 302 }
 303 
 304 
 305 /**
 306  * Logon domain user with an 'network' SAM logon
 307  *
 308  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
 309  **/
 310 
 311 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
     /* [<][>][^][v][top][bottom][index][help] */
 312                                            TALLOC_CTX *mem_ctx,
 313                                            uint32 logon_parameters,
 314                                            const char *server,
 315                                            const char *username,
 316                                            const char *domain,
 317                                            const char *workstation,
 318                                            const uint8 chal[8],
 319                                            DATA_BLOB lm_response,
 320                                            DATA_BLOB nt_response,
 321                                            struct netr_SamInfo3 **info3)
 322 {
 323         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 324         int validation_level = 3;
 325         const char *workstation_name_slash;
 326         const char *server_name_slash;
 327         uint8 zeros[16];
 328         struct netr_Authenticator clnt_creds;
 329         struct netr_Authenticator ret_creds;
 330         union netr_LogonLevel *logon = NULL;
 331         struct netr_NetworkInfo *network_info;
 332         uint8_t authoritative;
 333         union netr_Validation validation;
 334         struct netr_ChallengeResponse lm;
 335         struct netr_ChallengeResponse nt;
 336 
 337         *info3 = NULL;
 338 
 339         ZERO_STRUCT(zeros);
 340         ZERO_STRUCT(ret_creds);
 341 
 342         ZERO_STRUCT(lm);
 343         ZERO_STRUCT(nt);
 344 
 345         logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
 346         if (!logon) {
 347                 return NT_STATUS_NO_MEMORY;
 348         }
 349 
 350         network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
 351         if (!network_info) {
 352                 return NT_STATUS_NO_MEMORY;
 353         }
 354 
 355         netlogon_creds_client_step(cli->dc, &clnt_creds);
 356 
 357         if (server[0] != '\\' && server[1] != '\\') {
 358                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
 359         } else {
 360                 server_name_slash = server;
 361         }
 362 
 363         if (workstation[0] != '\\' && workstation[1] != '\\') {
 364                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
 365         } else {
 366                 workstation_name_slash = workstation;
 367         }
 368 
 369         if (!workstation_name_slash || !server_name_slash) {
 370                 DEBUG(0, ("talloc_asprintf failed!\n"));
 371                 return NT_STATUS_NO_MEMORY;
 372         }
 373 
 374         /* Initialise input parameters */
 375 
 376         lm.data = lm_response.data;
 377         lm.length = lm_response.length;
 378         nt.data = nt_response.data;
 379         nt.length = nt_response.length;
 380 
 381         init_netr_NetworkInfo(network_info,
 382                               domain,
 383                               logon_parameters,
 384                               0xdead,
 385                               0xbeef,
 386                               username,
 387                               workstation_name_slash,
 388                               (uint8_t *) chal,
 389                               nt,
 390                               lm);
 391 
 392         logon->network = network_info;
 393 
 394         /* Marshall data and send request */
 395 
 396         result = rpccli_netr_LogonSamLogon(cli, mem_ctx,
 397                                            server_name_slash,
 398                                            global_myname(),
 399                                            &clnt_creds,
 400                                            &ret_creds,
 401                                            NetlogonNetworkInformation,
 402                                            logon,
 403                                            validation_level,
 404                                            &validation,
 405                                            &authoritative);
 406         if (!NT_STATUS_IS_OK(result)) {
 407                 return result;
 408         }
 409 
 410         if (memcmp(zeros, validation.sam3->base.key.key, 16) != 0) {
 411                 SamOEMhash(validation.sam3->base.key.key,
 412                            cli->dc->sess_key, 16);
 413         }
 414 
 415         if (memcmp(zeros, validation.sam3->base.LMSessKey.key, 8) != 0) {
 416                 SamOEMhash(validation.sam3->base.LMSessKey.key,
 417                            cli->dc->sess_key, 8);
 418         }
 419 
 420         if (memcmp(zeros, ret_creds.cred.data, sizeof(ret_creds.cred.data)) != 0) {
 421                 /* Check returned credentials if present. */
 422                 if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
 423                         DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
 424                         return NT_STATUS_ACCESS_DENIED;
 425                 }
 426         }
 427 
 428         *info3 = validation.sam3;
 429 
 430         return result;
 431 }
 432 
 433 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
     /* [<][>][^][v][top][bottom][index][help] */
 434                                               TALLOC_CTX *mem_ctx,
 435                                               uint32 logon_parameters,
 436                                               const char *server,
 437                                               const char *username,
 438                                               const char *domain,
 439                                               const char *workstation,
 440                                               const uint8 chal[8],
 441                                               DATA_BLOB lm_response,
 442                                               DATA_BLOB nt_response,
 443                                               struct netr_SamInfo3 **info3)
 444 {
 445         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 446         int validation_level = 3;
 447         const char *workstation_name_slash;
 448         const char *server_name_slash;
 449         uint8 zeros[16];
 450         union netr_LogonLevel *logon = NULL;
 451         struct netr_NetworkInfo *network_info;
 452         uint8_t authoritative;
 453         union netr_Validation validation;
 454         struct netr_ChallengeResponse lm;
 455         struct netr_ChallengeResponse nt;
 456         uint32_t flags = 0;
 457 
 458         *info3 = NULL;
 459 
 460         ZERO_STRUCT(zeros);
 461 
 462         ZERO_STRUCT(lm);
 463         ZERO_STRUCT(nt);
 464 
 465         logon = TALLOC_ZERO_P(mem_ctx, union netr_LogonLevel);
 466         if (!logon) {
 467                 return NT_STATUS_NO_MEMORY;
 468         }
 469 
 470         network_info = TALLOC_ZERO_P(mem_ctx, struct netr_NetworkInfo);
 471         if (!network_info) {
 472                 return NT_STATUS_NO_MEMORY;
 473         }
 474 
 475         if (server[0] != '\\' && server[1] != '\\') {
 476                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
 477         } else {
 478                 server_name_slash = server;
 479         }
 480 
 481         if (workstation[0] != '\\' && workstation[1] != '\\') {
 482                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
 483         } else {
 484                 workstation_name_slash = workstation;
 485         }
 486 
 487         if (!workstation_name_slash || !server_name_slash) {
 488                 DEBUG(0, ("talloc_asprintf failed!\n"));
 489                 return NT_STATUS_NO_MEMORY;
 490         }
 491 
 492         /* Initialise input parameters */
 493 
 494         lm.data = lm_response.data;
 495         lm.length = lm_response.length;
 496         nt.data = nt_response.data;
 497         nt.length = nt_response.length;
 498 
 499         init_netr_NetworkInfo(network_info,
 500                               domain,
 501                               logon_parameters,
 502                               0xdead,
 503                               0xbeef,
 504                               username,
 505                               workstation_name_slash,
 506                               (uint8_t *) chal,
 507                               nt,
 508                               lm);
 509 
 510         logon->network = network_info;
 511 
 512         /* Marshall data and send request */
 513 
 514         result = rpccli_netr_LogonSamLogonEx(cli, mem_ctx,
 515                                              server_name_slash,
 516                                              global_myname(),
 517                                              NetlogonNetworkInformation,
 518                                              logon,
 519                                              validation_level,
 520                                              &validation,
 521                                              &authoritative,
 522                                              &flags);
 523         if (!NT_STATUS_IS_OK(result)) {
 524                 return result;
 525         }
 526 
 527         if (memcmp(zeros, validation.sam3->base.key.key, 16) != 0) {
 528                 SamOEMhash(validation.sam3->base.key.key,
 529                            cli->dc->sess_key, 16);
 530         }
 531 
 532         if (memcmp(zeros, validation.sam3->base.LMSessKey.key, 8) != 0) {
 533                 SamOEMhash(validation.sam3->base.LMSessKey.key,
 534                            cli->dc->sess_key, 8);
 535         }
 536 
 537         *info3 = validation.sam3;
 538 
 539         return result;
 540 }
 541 
 542 /*********************************************************
 543  Change the domain password on the PDC.
 544 
 545  Just changes the password betwen the two values specified.
 546 
 547  Caller must have the cli connected to the netlogon pipe
 548  already.
 549 **********************************************************/
 550 
 551 NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
     /* [<][>][^][v][top][bottom][index][help] */
 552                                             TALLOC_CTX *mem_ctx,
 553                                             const unsigned char orig_trust_passwd_hash[16],
 554                                             const char *new_trust_pwd_cleartext,
 555                                             const unsigned char new_trust_passwd_hash[16],
 556                                             uint32_t sec_channel_type)
 557 {
 558         NTSTATUS result;
 559         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
 560         struct netr_Authenticator clnt_creds, srv_cred;
 561 
 562         result = rpccli_netlogon_setup_creds(cli,
 563                                              cli->desthost, /* server name */
 564                                              lp_workgroup(), /* domain */
 565                                              global_myname(), /* client name */
 566                                              global_myname(), /* machine account name */
 567                                              orig_trust_passwd_hash,
 568                                              sec_channel_type,
 569                                              &neg_flags);
 570 
 571         if (!NT_STATUS_IS_OK(result)) {
 572                 DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
 573                          nt_errstr(result)));
 574                 return result;
 575         }
 576 
 577         netlogon_creds_client_step(cli->dc, &clnt_creds);
 578 
 579         if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) {
 580 
 581                 struct netr_CryptPassword new_password;
 582 
 583                 init_netr_CryptPassword(new_trust_pwd_cleartext,
 584                                         cli->dc->sess_key,
 585                                         &new_password);
 586 
 587                 result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
 588                                                         cli->dc->remote_machine,
 589                                                         cli->dc->mach_acct,
 590                                                         sec_channel_type,
 591                                                         global_myname(),
 592                                                         &clnt_creds,
 593                                                         &srv_cred,
 594                                                         &new_password);
 595                 if (!NT_STATUS_IS_OK(result)) {
 596                         DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n",
 597                                 nt_errstr(result)));
 598                         return result;
 599                 }
 600         } else {
 601 
 602                 struct samr_Password new_password;
 603 
 604                 des_crypt112_16(new_password.hash,
 605                                 new_trust_passwd_hash,
 606                                 cli->dc->sess_key, 1);
 607 
 608                 result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
 609                                                        cli->dc->remote_machine,
 610                                                        cli->dc->mach_acct,
 611                                                        sec_channel_type,
 612                                                        global_myname(),
 613                                                        &clnt_creds,
 614                                                        &srv_cred,
 615                                                        &new_password);
 616                 if (!NT_STATUS_IS_OK(result)) {
 617                         DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n",
 618                                 nt_errstr(result)));
 619                         return result;
 620                 }
 621         }
 622 
 623         /* Always check returned credentials. */
 624         if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
 625                 DEBUG(0,("credentials chain check failed\n"));
 626                 return NT_STATUS_ACCESS_DENIED;
 627         }
 628 
 629         return result;
 630 }
 631 

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