root/source3/libsmb/clifsinfo.c

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

DEFINITIONS

This source file includes following definitions.
  1. cli_unix_extensions_version
  2. cli_set_unix_extensions_capabilities
  3. cli_get_fs_attr_info
  4. cli_get_fs_volume_info_old
  5. cli_get_fs_volume_info
  6. cli_get_fs_full_size_info
  7. cli_get_posix_fs_info
  8. enc_blob_send_receive
  9. make_cli_enc_state
  10. cli_raw_ntlm_smb_encryption_start
  11. make_cli_gss_blob
  12. cli_gss_smb_encryption_start
  13. cli_gss_smb_encryption_start
  14. cli_force_encryption

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    FS info functions
   4    Copyright (C) Stefan (metze) Metzmacher      2003
   5    Copyright (C) Jeremy Allison 2007
   6    
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11    
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16    
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 #include "includes.h"
  22 
  23 /****************************************************************************
  24  Get UNIX extensions version info.
  25 ****************************************************************************/
  26 
  27 bool cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, uint16 *pminor,
     /* [<][>][^][v][top][bottom][index][help] */
  28                                         uint32 *pcaplow, uint32 *pcaphigh)
  29 {
  30         bool ret = False;
  31         uint16 setup;
  32         char param[2];
  33         char *rparam=NULL, *rdata=NULL;
  34         unsigned int rparam_count=0, rdata_count=0;
  35 
  36         setup = TRANSACT2_QFSINFO;
  37 
  38         SSVAL(param,0,SMB_QUERY_CIFS_UNIX_INFO);
  39 
  40         if (!cli_send_trans(cli, SMBtrans2,
  41                     NULL,
  42                     0, 0,
  43                     &setup, 1, 0,
  44                     param, 2, 0,
  45                     NULL, 0, 560)) {
  46                 goto cleanup;
  47         }
  48 
  49         if (!cli_receive_trans(cli, SMBtrans2,
  50                               &rparam, &rparam_count,
  51                               &rdata, &rdata_count)) {
  52                 goto cleanup;
  53         }
  54 
  55         if (cli_is_error(cli)) {
  56                 ret = False;
  57                 goto cleanup;
  58         } else {
  59                 ret = True;
  60         }
  61 
  62         if (rdata_count < 12) {
  63                 goto cleanup;
  64         }
  65 
  66         *pmajor = SVAL(rdata,0);
  67         *pminor = SVAL(rdata,2);
  68         cli->posix_capabilities = *pcaplow = IVAL(rdata,4);
  69         *pcaphigh = IVAL(rdata,8);
  70 
  71         /* todo: but not yet needed
  72          *       return the other stuff
  73          */
  74 
  75 cleanup:
  76         SAFE_FREE(rparam);
  77         SAFE_FREE(rdata);
  78 
  79         return ret;
  80 }
  81 
  82 /****************************************************************************
  83  Set UNIX extensions capabilities.
  84 ****************************************************************************/
  85 
  86 bool cli_set_unix_extensions_capabilities(struct cli_state *cli, uint16 major, uint16 minor,
     /* [<][>][^][v][top][bottom][index][help] */
  87                                         uint32 caplow, uint32 caphigh)
  88 {
  89         bool ret = False;
  90         uint16 setup;
  91         char param[4];
  92         char data[12];
  93         char *rparam=NULL, *rdata=NULL;
  94         unsigned int rparam_count=0, rdata_count=0;
  95 
  96         setup = TRANSACT2_SETFSINFO;
  97 
  98         SSVAL(param,0,0);
  99         SSVAL(param,2,SMB_SET_CIFS_UNIX_INFO);
 100 
 101         SSVAL(data,0,major);
 102         SSVAL(data,2,minor);
 103         SIVAL(data,4,caplow);
 104         SIVAL(data,8,caphigh);
 105 
 106         if (!cli_send_trans(cli, SMBtrans2,
 107                     NULL,
 108                     0, 0,
 109                     &setup, 1, 0,
 110                     param, 4, 0,
 111                     data, 12, 560)) {
 112                 goto cleanup;
 113         }
 114 
 115         if (!cli_receive_trans(cli, SMBtrans2,
 116                               &rparam, &rparam_count,
 117                               &rdata, &rdata_count)) {
 118                 goto cleanup;
 119         }
 120 
 121         if (cli_is_error(cli)) {
 122                 ret = False;
 123                 goto cleanup;
 124         } else {
 125                 ret = True;
 126         }
 127 
 128 cleanup:
 129         SAFE_FREE(rparam);
 130         SAFE_FREE(rdata);
 131 
 132         return ret;
 133 }
 134 
 135 bool cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr)
     /* [<][>][^][v][top][bottom][index][help] */
 136 {
 137         bool ret = False;
 138         uint16 setup;
 139         char param[2];
 140         char *rparam=NULL, *rdata=NULL;
 141         unsigned int rparam_count=0, rdata_count=0;
 142 
 143         if (!cli||!fs_attr)
 144                 smb_panic("cli_get_fs_attr_info() called with NULL Pionter!");
 145 
 146         setup = TRANSACT2_QFSINFO;
 147 
 148         SSVAL(param,0,SMB_QUERY_FS_ATTRIBUTE_INFO);
 149 
 150         if (!cli_send_trans(cli, SMBtrans2,
 151                     NULL,
 152                     0, 0,
 153                     &setup, 1, 0,
 154                     param, 2, 0,
 155                     NULL, 0, 560)) {
 156                 goto cleanup;
 157         }
 158 
 159         if (!cli_receive_trans(cli, SMBtrans2,
 160                               &rparam, &rparam_count,
 161                               &rdata, &rdata_count)) {
 162                 goto cleanup;
 163         }
 164 
 165         if (cli_is_error(cli)) {
 166                 ret = False;
 167                 goto cleanup;
 168         } else {
 169                 ret = True;
 170         }
 171 
 172         if (rdata_count < 12) {
 173                 goto cleanup;
 174         }
 175 
 176         *fs_attr = IVAL(rdata,0);
 177 
 178         /* todo: but not yet needed
 179          *       return the other stuff
 180          */
 181 
 182 cleanup:
 183         SAFE_FREE(rparam);
 184         SAFE_FREE(rdata);
 185 
 186         return ret;
 187 }
 188 
 189 bool cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint32 *pserial_number)
     /* [<][>][^][v][top][bottom][index][help] */
 190 {
 191         bool ret = False;
 192         uint16 setup;
 193         char param[2];
 194         char *rparam=NULL, *rdata=NULL;
 195         unsigned int rparam_count=0, rdata_count=0;
 196         unsigned char nlen;
 197 
 198         setup = TRANSACT2_QFSINFO;
 199 
 200         SSVAL(param,0,SMB_INFO_VOLUME);
 201 
 202         if (!cli_send_trans(cli, SMBtrans2,
 203                     NULL,
 204                     0, 0,
 205                     &setup, 1, 0,
 206                     param, 2, 0,
 207                     NULL, 0, 560)) {
 208                 goto cleanup;
 209         }
 210 
 211         if (!cli_receive_trans(cli, SMBtrans2,
 212                               &rparam, &rparam_count,
 213                               &rdata, &rdata_count)) {
 214                 goto cleanup;
 215         }
 216 
 217         if (cli_is_error(cli)) {
 218                 ret = False;
 219                 goto cleanup;
 220         } else {
 221                 ret = True;
 222         }
 223 
 224         if (rdata_count < 5) {
 225                 goto cleanup;
 226         }
 227 
 228         if (pserial_number) {
 229                 *pserial_number = IVAL(rdata,0);
 230         }
 231         nlen = CVAL(rdata,l2_vol_cch);
 232         clistr_pull(cli->inbuf, volume_name, rdata + l2_vol_szVolLabel,
 233                     sizeof(fstring), nlen, STR_NOALIGN);
 234 
 235         /* todo: but not yet needed
 236          *       return the other stuff
 237          */
 238 
 239 cleanup:
 240         SAFE_FREE(rparam);
 241         SAFE_FREE(rdata);
 242 
 243         return ret;
 244 }
 245 
 246 bool cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 *pserial_number, time_t *pdate)
     /* [<][>][^][v][top][bottom][index][help] */
 247 {
 248         bool ret = False;
 249         uint16 setup;
 250         char param[2];
 251         char *rparam=NULL, *rdata=NULL;
 252         unsigned int rparam_count=0, rdata_count=0;
 253         unsigned int nlen;
 254 
 255         setup = TRANSACT2_QFSINFO;
 256 
 257         SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO);
 258 
 259         if (!cli_send_trans(cli, SMBtrans2,
 260                     NULL,
 261                     0, 0,
 262                     &setup, 1, 0,
 263                     param, 2, 0,
 264                     NULL, 0, 560)) {
 265                 goto cleanup;
 266         }
 267 
 268         if (!cli_receive_trans(cli, SMBtrans2,
 269                               &rparam, &rparam_count,
 270                               &rdata, &rdata_count)) {
 271                 goto cleanup;
 272         }
 273 
 274         if (cli_is_error(cli)) {
 275                 ret = False;
 276                 goto cleanup;
 277         } else {
 278                 ret = True;
 279         }
 280 
 281         if (rdata_count < 19) {
 282                 goto cleanup;
 283         }
 284 
 285         if (pdate) {
 286                 struct timespec ts;
 287                 ts = interpret_long_date(rdata);
 288                 *pdate = ts.tv_sec;
 289         }
 290         if (pserial_number) {
 291                 *pserial_number = IVAL(rdata,8);
 292         }
 293         nlen = IVAL(rdata,12);
 294         clistr_pull(cli->inbuf, volume_name, rdata + 18, sizeof(fstring),
 295                     nlen, STR_UNICODE);
 296 
 297         /* todo: but not yet needed
 298          *       return the other stuff
 299          */
 300 
 301 cleanup:
 302         SAFE_FREE(rparam);
 303         SAFE_FREE(rdata);
 304 
 305         return ret;
 306 }
 307 
 308 bool cli_get_fs_full_size_info(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
 309                                uint64_t *total_allocation_units,
 310                                uint64_t *caller_allocation_units,
 311                                uint64_t *actual_allocation_units,
 312                                uint64_t *sectors_per_allocation_unit,
 313                                uint64_t *bytes_per_sector)
 314 {
 315         bool ret = False;
 316         uint16 setup;
 317         char param[2];
 318         char *rparam=NULL, *rdata=NULL;
 319         unsigned int rparam_count=0, rdata_count=0;
 320 
 321         setup = TRANSACT2_QFSINFO;
 322 
 323         SSVAL(param,0,SMB_FS_FULL_SIZE_INFORMATION);
 324 
 325         if (!cli_send_trans(cli, SMBtrans2,
 326                     NULL,
 327                     0, 0,
 328                     &setup, 1, 0,
 329                     param, 2, 0,
 330                     NULL, 0, 560)) {
 331                 goto cleanup;
 332         }
 333 
 334         if (!cli_receive_trans(cli, SMBtrans2,
 335                               &rparam, &rparam_count,
 336                               &rdata, &rdata_count)) {
 337                 goto cleanup;
 338         }
 339 
 340         if (cli_is_error(cli)) {
 341                 ret = False;
 342                 goto cleanup;
 343         } else {
 344                 ret = True;
 345         }
 346 
 347         if (rdata_count != 32) {
 348                 goto cleanup;
 349         }
 350 
 351         if (total_allocation_units) {
 352                 *total_allocation_units = BIG_UINT(rdata, 0);
 353         }
 354         if (caller_allocation_units) {
 355                 *caller_allocation_units = BIG_UINT(rdata,8);
 356         }
 357         if (actual_allocation_units) {
 358                 *actual_allocation_units = BIG_UINT(rdata,16);
 359         }
 360         if (sectors_per_allocation_unit) {
 361                 *sectors_per_allocation_unit = IVAL(rdata,24);
 362         }
 363         if (bytes_per_sector) {
 364                 *bytes_per_sector = IVAL(rdata,28);
 365         }
 366 
 367 cleanup:
 368         SAFE_FREE(rparam);
 369         SAFE_FREE(rdata);
 370 
 371         return ret;
 372 }
 373 
 374 bool cli_get_posix_fs_info(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
 375                            uint32 *optimal_transfer_size,
 376                            uint32 *block_size,
 377                            uint64_t *total_blocks,
 378                            uint64_t *blocks_available,
 379                            uint64_t *user_blocks_available,
 380                            uint64_t *total_file_nodes,
 381                            uint64_t *free_file_nodes,
 382                            uint64_t *fs_identifier)
 383 {
 384         bool ret = False;
 385         uint16 setup;
 386         char param[2];
 387         char *rparam=NULL, *rdata=NULL;
 388         unsigned int rparam_count=0, rdata_count=0;
 389 
 390         setup = TRANSACT2_QFSINFO;
 391 
 392         SSVAL(param,0,SMB_QUERY_POSIX_FS_INFO);
 393 
 394         if (!cli_send_trans(cli, SMBtrans2,
 395                     NULL,
 396                     0, 0,
 397                     &setup, 1, 0,
 398                     param, 2, 0,
 399                     NULL, 0, 560)) {
 400                 goto cleanup;
 401         }
 402 
 403         if (!cli_receive_trans(cli, SMBtrans2,
 404                               &rparam, &rparam_count,
 405                               &rdata, &rdata_count)) {
 406                 goto cleanup;
 407         }
 408 
 409         if (cli_is_error(cli)) {
 410                 ret = False;
 411                 goto cleanup;
 412         } else {
 413                 ret = True;
 414         }
 415 
 416         if (rdata_count != 56) {
 417                 goto cleanup;
 418         }
 419 
 420         if (optimal_transfer_size) {
 421                 *optimal_transfer_size = IVAL(rdata, 0);
 422         }
 423         if (block_size) {
 424                 *block_size = IVAL(rdata,4);
 425         }
 426         if (total_blocks) {
 427                 *total_blocks = BIG_UINT(rdata,8);
 428         }
 429         if (blocks_available) {
 430                 *blocks_available = BIG_UINT(rdata,16);
 431         }
 432         if (user_blocks_available) {
 433                 *user_blocks_available = BIG_UINT(rdata,24);
 434         }
 435         if (total_file_nodes) {
 436                 *total_file_nodes = BIG_UINT(rdata,32);
 437         }
 438         if (free_file_nodes) {
 439                 *free_file_nodes = BIG_UINT(rdata,40);
 440         }
 441         if (fs_identifier) {
 442                 *fs_identifier = BIG_UINT(rdata,48);
 443         }
 444 
 445 cleanup:
 446         SAFE_FREE(rparam);
 447         SAFE_FREE(rdata);
 448 
 449         return ret;
 450 }
 451 
 452 
 453 /******************************************************************************
 454  Send/receive the request encryption blob.
 455 ******************************************************************************/
 456 
 457 static NTSTATUS enc_blob_send_receive(struct cli_state *cli, DATA_BLOB *in, DATA_BLOB *out, DATA_BLOB *param_out)
     /* [<][>][^][v][top][bottom][index][help] */
 458 {
 459         uint16 setup;
 460         char param[4];
 461         char *rparam=NULL, *rdata=NULL;
 462         unsigned int rparam_count=0, rdata_count=0;
 463         NTSTATUS status = NT_STATUS_OK;
 464 
 465         setup = TRANSACT2_SETFSINFO;
 466 
 467         SSVAL(param,0,0);
 468         SSVAL(param,2,SMB_REQUEST_TRANSPORT_ENCRYPTION);
 469 
 470         if (!cli_send_trans(cli, SMBtrans2,
 471                                 NULL,
 472                                 0, 0,
 473                                 &setup, 1, 0,
 474                                 param, 4, 0,
 475                                 (char *)in->data, in->length, CLI_BUFFER_SIZE)) {
 476                 status = cli_nt_error(cli);
 477                 goto out;
 478         }
 479 
 480         if (!cli_receive_trans(cli, SMBtrans2,
 481                                 &rparam, &rparam_count,
 482                                 &rdata, &rdata_count)) {
 483                 status = cli_nt_error(cli);
 484                 goto out;
 485         }
 486 
 487         if (cli_is_error(cli)) {
 488                 status = cli_nt_error(cli);
 489                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
 490                         goto out;
 491                 }
 492         }
 493 
 494         *out = data_blob(rdata, rdata_count);
 495         *param_out = data_blob(rparam, rparam_count);
 496 
 497   out:
 498 
 499         SAFE_FREE(rparam);
 500         SAFE_FREE(rdata);
 501         return status;
 502 }
 503 
 504 /******************************************************************************
 505  Make a client state struct.
 506 ******************************************************************************/
 507 
 508 static struct smb_trans_enc_state *make_cli_enc_state(enum smb_trans_enc_type smb_enc_type)
     /* [<][>][^][v][top][bottom][index][help] */
 509 {
 510         struct smb_trans_enc_state *es = NULL;
 511         es = SMB_MALLOC_P(struct smb_trans_enc_state);
 512         if (!es) {
 513                 return NULL;
 514         }
 515         ZERO_STRUCTP(es);
 516         es->smb_enc_type = smb_enc_type;
 517 
 518 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
 519         if (smb_enc_type == SMB_TRANS_ENC_GSS) {
 520                 es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss);
 521                 if (!es->s.gss_state) {
 522                         SAFE_FREE(es);
 523                         return NULL;
 524                 }
 525                 ZERO_STRUCTP(es->s.gss_state);
 526         }
 527 #endif
 528         return es;
 529 }
 530 
 531 /******************************************************************************
 532  Start a raw ntlmssp encryption.
 533 ******************************************************************************/
 534 
 535 NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli, 
     /* [<][>][^][v][top][bottom][index][help] */
 536                                 const char *user,
 537                                 const char *pass,
 538                                 const char *domain)
 539 {
 540         DATA_BLOB blob_in = data_blob_null;
 541         DATA_BLOB blob_out = data_blob_null;
 542         DATA_BLOB param_out = data_blob_null;
 543         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
 544         struct smb_trans_enc_state *es = make_cli_enc_state(SMB_TRANS_ENC_NTLM);
 545 
 546         if (!es) {
 547                 return NT_STATUS_NO_MEMORY;
 548         }
 549         status = ntlmssp_client_start(&es->s.ntlmssp_state);
 550         if (!NT_STATUS_IS_OK(status)) {
 551                 goto fail;
 552         }
 553 
 554         ntlmssp_want_feature(es->s.ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
 555         es->s.ntlmssp_state->neg_flags |= (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
 556 
 557         if (!NT_STATUS_IS_OK(status = ntlmssp_set_username(es->s.ntlmssp_state, user))) {
 558                 goto fail;
 559         }
 560         if (!NT_STATUS_IS_OK(status = ntlmssp_set_domain(es->s.ntlmssp_state, domain))) {
 561                 goto fail;
 562         }
 563         if (!NT_STATUS_IS_OK(status = ntlmssp_set_password(es->s.ntlmssp_state, pass))) {
 564                 goto fail;
 565         }
 566 
 567         do {
 568                 status = ntlmssp_update(es->s.ntlmssp_state, blob_in, &blob_out);
 569                 data_blob_free(&blob_in);
 570                 data_blob_free(&param_out);
 571                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(status)) {
 572                         NTSTATUS trans_status = enc_blob_send_receive(cli,
 573                                                                         &blob_out,
 574                                                                         &blob_in,
 575                                                                         &param_out);
 576                         if (!NT_STATUS_EQUAL(trans_status,
 577                                         NT_STATUS_MORE_PROCESSING_REQUIRED) &&
 578                                         !NT_STATUS_IS_OK(trans_status)) {
 579                                 status = trans_status;
 580                         } else {
 581                                 if (param_out.length == 2) {
 582                                         es->enc_ctx_num = SVAL(param_out.data, 0);
 583                                 }
 584                         }
 585                 }
 586                 data_blob_free(&blob_out);
 587         } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
 588 
 589         data_blob_free(&blob_in);
 590 
 591         if (NT_STATUS_IS_OK(status)) {
 592                 /* Replace the old state, if any. */
 593                 if (cli->trans_enc_state) {
 594                         common_free_encryption_state(&cli->trans_enc_state);
 595                 }
 596                 cli->trans_enc_state = es;
 597                 cli->trans_enc_state->enc_on = True;
 598                 es = NULL;
 599         }
 600 
 601   fail:
 602 
 603         common_free_encryption_state(&es);
 604         return status;
 605 }
 606 
 607 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
 608 
 609 #ifndef SMB_GSS_REQUIRED_FLAGS
 610 #define SMB_GSS_REQUIRED_FLAGS (GSS_C_CONF_FLAG|GSS_C_INTEG_FLAG|GSS_C_MUTUAL_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)
 611 #endif
 612 
 613 /******************************************************************************
 614  Get client gss blob to send to a server.
 615 ******************************************************************************/
 616 
 617 static NTSTATUS make_cli_gss_blob(struct smb_trans_enc_state *es,
     /* [<][>][^][v][top][bottom][index][help] */
 618                                 const char *service,
 619                                 const char *host,
 620                                 NTSTATUS status_in,
 621                                 DATA_BLOB spnego_blob_in,
 622                                 DATA_BLOB *p_blob_out)
 623 {
 624         const char *krb_mechs[] = {OID_KERBEROS5, NULL};
 625         OM_uint32 ret;
 626         OM_uint32 min;
 627         gss_name_t srv_name;
 628         gss_buffer_desc input_name;
 629         gss_buffer_desc *p_tok_in;
 630         gss_buffer_desc tok_out, tok_in;
 631         DATA_BLOB blob_out = data_blob_null;
 632         DATA_BLOB blob_in = data_blob_null;
 633         char *host_princ_s = NULL;
 634         OM_uint32 ret_flags = 0;
 635         NTSTATUS status = NT_STATUS_OK;
 636 
 637         gss_OID_desc nt_hostbased_service =
 638         {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")};
 639 
 640         memset(&tok_out, '\0', sizeof(tok_out));
 641 
 642         /* Get a ticket for the service@host */
 643         if (asprintf(&host_princ_s, "%s@%s", service, host) == -1) {
 644                 return NT_STATUS_NO_MEMORY;
 645         }
 646 
 647         input_name.value = host_princ_s;
 648         input_name.length = strlen(host_princ_s) + 1;
 649 
 650         ret = gss_import_name(&min,
 651                                 &input_name,
 652                                 &nt_hostbased_service,
 653                                 &srv_name);
 654 
 655         if (ret != GSS_S_COMPLETE) {
 656                 SAFE_FREE(host_princ_s);
 657                 return map_nt_error_from_gss(ret, min);
 658         }
 659 
 660         if (spnego_blob_in.length == 0) {
 661                 p_tok_in = GSS_C_NO_BUFFER;
 662         } else {
 663                 /* Remove the SPNEGO wrapper */
 664                 if (!spnego_parse_auth_response(spnego_blob_in, status_in, OID_KERBEROS5, &blob_in)) {
 665                         status = NT_STATUS_UNSUCCESSFUL;
 666                         goto fail;
 667                 }
 668                 tok_in.value = blob_in.data;
 669                 tok_in.length = blob_in.length;
 670                 p_tok_in = &tok_in;
 671         }
 672 
 673         ret = gss_init_sec_context(&min,
 674                                 GSS_C_NO_CREDENTIAL, /* Use our default cred. */
 675                                 &es->s.gss_state->gss_ctx,
 676                                 srv_name,
 677                                 GSS_C_NO_OID, /* default OID. */
 678                                 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG,
 679                                 GSS_C_INDEFINITE,       /* requested ticket lifetime. */
 680                                 NULL,   /* no channel bindings */
 681                                 p_tok_in,
 682                                 NULL,   /* ignore mech type */
 683                                 &tok_out,
 684                                 &ret_flags,
 685                                 NULL);  /* ignore time_rec */
 686 
 687         status = map_nt_error_from_gss(ret, min);
 688         if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
 689                 ADS_STATUS adss = ADS_ERROR_GSS(ret, min);
 690                 DEBUG(10,("make_cli_gss_blob: gss_init_sec_context failed with %s\n",
 691                         ads_errstr(adss)));
 692                 goto fail;
 693         }
 694 
 695         if ((ret_flags & SMB_GSS_REQUIRED_FLAGS) != SMB_GSS_REQUIRED_FLAGS) {
 696                 status = NT_STATUS_ACCESS_DENIED;
 697         }
 698 
 699         blob_out = data_blob(tok_out.value, tok_out.length);
 700 
 701         /* Wrap in an SPNEGO wrapper */
 702         *p_blob_out = gen_negTokenTarg(krb_mechs, blob_out);
 703 
 704   fail:
 705 
 706         data_blob_free(&blob_out);
 707         data_blob_free(&blob_in);
 708         SAFE_FREE(host_princ_s);
 709         gss_release_name(&min, &srv_name);
 710         if (tok_out.value) {
 711                 gss_release_buffer(&min, &tok_out);
 712         }
 713         return status;
 714 }
 715 
 716 /******************************************************************************
 717  Start a SPNEGO gssapi encryption context.
 718 ******************************************************************************/
 719 
 720 NTSTATUS cli_gss_smb_encryption_start(struct cli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
 721 {
 722         DATA_BLOB blob_recv = data_blob_null;
 723         DATA_BLOB blob_send = data_blob_null;
 724         DATA_BLOB param_out = data_blob_null;
 725         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
 726         fstring fqdn;
 727         const char *servicename;
 728         struct smb_trans_enc_state *es = make_cli_enc_state(SMB_TRANS_ENC_GSS);
 729 
 730         if (!es) {
 731                 return NT_STATUS_NO_MEMORY;
 732         }
 733 
 734         name_to_fqdn(fqdn, cli->desthost);
 735         strlower_m(fqdn);
 736 
 737         servicename = "cifs";
 738         status = make_cli_gss_blob(es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send);
 739         if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
 740                 servicename = "host";
 741                 status = make_cli_gss_blob(es, servicename, fqdn, NT_STATUS_OK, blob_recv, &blob_send);
 742                 if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
 743                         goto fail;
 744                 }
 745         }
 746 
 747         do {
 748                 data_blob_free(&blob_recv);
 749                 status = enc_blob_send_receive(cli, &blob_send, &blob_recv, &param_out);
 750                 if (param_out.length == 2) {
 751                         es->enc_ctx_num = SVAL(param_out.data, 0);
 752                 }
 753                 data_blob_free(&blob_send);
 754                 status = make_cli_gss_blob(es, servicename, fqdn, status, blob_recv, &blob_send);
 755         } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
 756         data_blob_free(&blob_recv);
 757 
 758         if (NT_STATUS_IS_OK(status)) {
 759                 /* Replace the old state, if any. */
 760                 if (cli->trans_enc_state) {
 761                         common_free_encryption_state(&cli->trans_enc_state);
 762                 }
 763                 cli->trans_enc_state = es;
 764                 cli->trans_enc_state->enc_on = True;
 765                 es = NULL;
 766         }
 767 
 768   fail:
 769 
 770         common_free_encryption_state(&es);
 771         return status;
 772 }
 773 #else
 774 NTSTATUS cli_gss_smb_encryption_start(struct cli_state *cli)
     /* [<][>][^][v][top][bottom][index][help] */
 775 {
 776         return NT_STATUS_NOT_SUPPORTED;
 777 }
 778 #endif
 779 
 780 /********************************************************************
 781  Ensure a connection is encrypted.
 782 ********************************************************************/
 783 
 784 NTSTATUS cli_force_encryption(struct cli_state *c,
     /* [<][>][^][v][top][bottom][index][help] */
 785                         const char *username,
 786                         const char *password,
 787                         const char *domain)
 788 {
 789         uint16 major, minor;
 790         uint32 caplow, caphigh;
 791 
 792         if (!SERVER_HAS_UNIX_CIFS(c)) {
 793                 return NT_STATUS_NOT_SUPPORTED;
 794         }
 795 
 796         if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) {
 797                 return NT_STATUS_UNKNOWN_REVISION;
 798         }
 799 
 800         if (!(caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)) {
 801                 return NT_STATUS_UNSUPPORTED_COMPRESSION;
 802         }
 803 
 804         if (c->use_kerberos) {
 805                 return cli_gss_smb_encryption_start(c);
 806         }
 807         return cli_raw_ntlm_smb_encryption_start(c,
 808                                         username,
 809                                         password,
 810                                         domain);
 811 }

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