1/* 2 Unix SMB/CIFS implementation. 3 SMB Transport encryption (sealing) code - server code. 4 Copyright (C) Jeremy Allison 2007. 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 "smbd/globals.h" 22#include "../libcli/auth/spnego.h" 23 24/****************************************************************************** 25 Server side encryption. 26******************************************************************************/ 27 28/****************************************************************************** 29 Global server state. 30******************************************************************************/ 31 32struct smb_srv_trans_enc_ctx { 33 struct smb_trans_enc_state *es; 34 AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */ 35}; 36 37/****************************************************************************** 38 Return global enc context - this must change if we ever do multiple contexts. 39******************************************************************************/ 40 41uint16_t srv_enc_ctx(void) 42{ 43 return srv_trans_enc_ctx->es->enc_ctx_num; 44} 45 46/****************************************************************************** 47 Is this an incoming encrypted packet ? 48******************************************************************************/ 49 50bool is_encrypted_packet(const uint8_t *inbuf) 51{ 52 NTSTATUS status; 53 uint16_t enc_num; 54 55 /* Ignore non-session messages or non 0xFF'E' messages. */ 56 if(CVAL(inbuf,0) || !(inbuf[4] == 0xFF && inbuf[5] == 'E')) { 57 return false; 58 } 59 60 status = get_enc_ctx_num(inbuf, &enc_num); 61 if (!NT_STATUS_IS_OK(status)) { 62 return false; 63 } 64 65 /* Encrypted messages are 0xFF'E'<ctx> */ 66 if (srv_trans_enc_ctx && enc_num == srv_enc_ctx()) { 67 return true; 68 } 69 return false; 70} 71 72/****************************************************************************** 73 Create an auth_ntlmssp_state and ensure pointer copy is correct. 74******************************************************************************/ 75 76static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) 77{ 78 NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state); 79 if (!NT_STATUS_IS_OK(status)) { 80 return nt_status_squash(status); 81 } 82 83 /* 84 * We must remember to update the pointer copy for the common 85 * functions after any auth_ntlmssp_start/auth_ntlmssp_end. 86 */ 87 ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state; 88 return status; 89} 90 91/****************************************************************************** 92 Destroy an auth_ntlmssp_state and ensure pointer copy is correct. 93******************************************************************************/ 94 95static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec) 96{ 97 /* 98 * We must remember to update the pointer copy for the common 99 * functions after any auth_ntlmssp_start/auth_ntlmssp_end. 100 */ 101 102 if (ec->auth_ntlmssp_state) { 103 auth_ntlmssp_end(&ec->auth_ntlmssp_state); 104 /* The auth_ntlmssp_end killed this already. */ 105 ec->es->s.ntlmssp_state = NULL; 106 } 107} 108 109#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) 110 111/****************************************************************************** 112 Import a name. 113******************************************************************************/ 114 115static NTSTATUS get_srv_gss_creds(const char *service, 116 const char *name, 117 gss_cred_usage_t cred_type, 118 gss_cred_id_t *p_srv_cred) 119{ 120 OM_uint32 ret; 121 OM_uint32 min; 122 gss_name_t srv_name; 123 gss_buffer_desc input_name; 124 char *host_princ_s = NULL; 125 NTSTATUS status = NT_STATUS_OK; 126 127 gss_OID_desc nt_hostbased_service = 128 {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")}; 129 130 if (asprintf(&host_princ_s, "%s@%s", service, name) == -1) { 131 return NT_STATUS_NO_MEMORY; 132 } 133 134 input_name.value = host_princ_s; 135 input_name.length = strlen(host_princ_s) + 1; 136 137 ret = gss_import_name(&min, 138 &input_name, 139 &nt_hostbased_service, 140 &srv_name); 141 142 DEBUG(10,("get_srv_gss_creds: imported name %s\n", 143 host_princ_s )); 144 145 if (ret != GSS_S_COMPLETE) { 146 SAFE_FREE(host_princ_s); 147 return map_nt_error_from_gss(ret, min); 148 } 149 150 /* 151 * We're accessing the krb5.keytab file here. 152 * ensure we have permissions to do so. 153 */ 154 become_root(); 155 156 ret = gss_acquire_cred(&min, 157 srv_name, 158 GSS_C_INDEFINITE, 159 GSS_C_NULL_OID_SET, 160 cred_type, 161 p_srv_cred, 162 NULL, 163 NULL); 164 unbecome_root(); 165 166 if (ret != GSS_S_COMPLETE) { 167 ADS_STATUS adss = ADS_ERROR_GSS(ret, min); 168 DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n", 169 ads_errstr(adss))); 170 status = map_nt_error_from_gss(ret, min); 171 } 172 173 SAFE_FREE(host_princ_s); 174 gss_release_name(&min, &srv_name); 175 return status; 176} 177 178/****************************************************************************** 179 Create a gss state. 180 Try and get the cifs/server@realm principal first, then fall back to 181 host/server@realm. 182******************************************************************************/ 183 184static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec) 185{ 186 NTSTATUS status; 187 gss_cred_id_t srv_cred; 188 fstring fqdn; 189 190 name_to_fqdn(fqdn, global_myname()); 191 strlower_m(fqdn); 192 193 status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred); 194 if (!NT_STATUS_IS_OK(status)) { 195 status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred); 196 if (!NT_STATUS_IS_OK(status)) { 197 return nt_status_squash(status); 198 } 199 } 200 201 ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss); 202 if (!ec->es->s.gss_state) { 203 OM_uint32 min; 204 gss_release_cred(&min, &srv_cred); 205 return NT_STATUS_NO_MEMORY; 206 } 207 ZERO_STRUCTP(ec->es->s.gss_state); 208 ec->es->s.gss_state->creds = srv_cred; 209 210 /* No context yet. */ 211 ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT; 212 213 return NT_STATUS_OK; 214} 215#endif 216 217/****************************************************************************** 218 Shutdown a server encryption context. 219******************************************************************************/ 220 221static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec) 222{ 223 struct smb_srv_trans_enc_ctx *ec = *pp_ec; 224 225 if (!ec) { 226 return; 227 } 228 229 if (ec->es) { 230 switch (ec->es->smb_enc_type) { 231 case SMB_TRANS_ENC_NTLM: 232 destroy_auth_ntlmssp(ec); 233 break; 234#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) 235 case SMB_TRANS_ENC_GSS: 236 break; 237#endif 238 } 239 common_free_encryption_state(&ec->es); 240 } 241 242 SAFE_FREE(ec); 243 *pp_ec = NULL; 244} 245 246/****************************************************************************** 247 Create a server encryption context. 248******************************************************************************/ 249 250static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec) 251{ 252 struct smb_srv_trans_enc_ctx *ec; 253 254 *pp_ec = NULL; 255 256 ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx); 257 if (!ec) { 258 return NT_STATUS_NO_MEMORY; 259 } 260 ZERO_STRUCTP(partial_srv_trans_enc_ctx); 261 ec->es = SMB_MALLOC_P(struct smb_trans_enc_state); 262 if (!ec->es) { 263 SAFE_FREE(ec); 264 return NT_STATUS_NO_MEMORY; 265 } 266 ZERO_STRUCTP(ec->es); 267 ec->es->smb_enc_type = smb_enc_type; 268 switch (smb_enc_type) { 269 case SMB_TRANS_ENC_NTLM: 270 { 271 NTSTATUS status = make_auth_ntlmssp(ec); 272 if (!NT_STATUS_IS_OK(status)) { 273 srv_free_encryption_context(&ec); 274 return status; 275 } 276 } 277 break; 278 279#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) 280 case SMB_TRANS_ENC_GSS: 281 /* Acquire our credentials by calling gss_acquire_cred here. */ 282 { 283 NTSTATUS status = make_auth_gss(ec); 284 if (!NT_STATUS_IS_OK(status)) { 285 srv_free_encryption_context(&ec); 286 return status; 287 } 288 } 289 break; 290#endif 291 default: 292 srv_free_encryption_context(&ec); 293 return NT_STATUS_INVALID_PARAMETER; 294 } 295 *pp_ec = ec; 296 return NT_STATUS_OK; 297} 298 299/****************************************************************************** 300 Free an encryption-allocated buffer. 301******************************************************************************/ 302 303void srv_free_enc_buffer(char *buf) 304{ 305 /* We know this is an smb buffer, and we 306 * didn't malloc, only copy, for a keepalive, 307 * so ignore non-session messages. */ 308 309 if(CVAL(buf,0)) { 310 return; 311 } 312 313 if (srv_trans_enc_ctx) { 314 common_free_enc_buffer(srv_trans_enc_ctx->es, buf); 315 } 316} 317 318/****************************************************************************** 319 Decrypt an incoming buffer. 320******************************************************************************/ 321 322NTSTATUS srv_decrypt_buffer(char *buf) 323{ 324 /* Ignore non-session messages. */ 325 if(CVAL(buf,0)) { 326 return NT_STATUS_OK; 327 } 328 329 if (srv_trans_enc_ctx) { 330 return common_decrypt_buffer(srv_trans_enc_ctx->es, buf); 331 } 332 333 return NT_STATUS_OK; 334} 335 336/****************************************************************************** 337 Encrypt an outgoing buffer. Return the encrypted pointer in buf_out. 338******************************************************************************/ 339 340NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out) 341{ 342 *buf_out = buf; 343 344 /* Ignore non-session messages. */ 345 if(CVAL(buf,0)) { 346 return NT_STATUS_OK; 347 } 348 349 if (srv_trans_enc_ctx) { 350 return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out); 351 } 352 /* Not encrypting. */ 353 return NT_STATUS_OK; 354} 355 356/****************************************************************************** 357 Do the gss encryption negotiation. Parameters are in/out. 358 Until success we do everything on the partial enc ctx. 359******************************************************************************/ 360 361#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) 362static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob) 363{ 364 OM_uint32 ret; 365 OM_uint32 min; 366 OM_uint32 flags = 0; 367 gss_buffer_desc in_buf, out_buf; 368 struct smb_tran_enc_state_gss *gss_state; 369 DATA_BLOB auth_reply = data_blob_null; 370 DATA_BLOB response = data_blob_null; 371 NTSTATUS status; 372 373 if (!partial_srv_trans_enc_ctx) { 374 status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx); 375 if (!NT_STATUS_IS_OK(status)) { 376 return status; 377 } 378 } 379 380 gss_state = partial_srv_trans_enc_ctx->es->s.gss_state; 381 382 in_buf.value = secblob.data; 383 in_buf.length = secblob.length; 384 385 out_buf.value = NULL; 386 out_buf.length = 0; 387 388 become_root(); 389 390 ret = gss_accept_sec_context(&min, 391 &gss_state->gss_ctx, 392 gss_state->creds, 393 &in_buf, 394 GSS_C_NO_CHANNEL_BINDINGS, 395 NULL, 396 NULL, /* Ignore oids. */ 397 &out_buf, /* To return. */ 398 &flags, 399 NULL, /* Ingore time. */ 400 NULL); /* Ignore delegated creds. */ 401 unbecome_root(); 402 403 status = gss_err_to_ntstatus(ret, min); 404 if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { 405 return status; 406 } 407 408 /* Ensure we've got sign+seal available. */ 409 if (ret == GSS_S_COMPLETE) { 410 if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) != 411 (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) { 412 DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough " 413 "for SMB sealing.\n")); 414 gss_release_buffer(&min, &out_buf); 415 return NT_STATUS_ACCESS_DENIED; 416 } 417 } 418 419 auth_reply = data_blob(out_buf.value, out_buf.length); 420 gss_release_buffer(&min, &out_buf); 421 422 /* Wrap in SPNEGO. */ 423 response = spnego_gen_auth_response(&auth_reply, status, OID_KERBEROS5); 424 data_blob_free(&auth_reply); 425 426 SAFE_FREE(*ppdata); 427 *ppdata = (unsigned char *)memdup(response.data, response.length); 428 if ((*ppdata) == NULL && response.length > 0) { 429 status = NT_STATUS_NO_MEMORY; 430 } 431 *p_data_size = response.length; 432 433 data_blob_free(&response); 434 435 return status; 436} 437#endif 438 439/****************************************************************************** 440 Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out. 441 Until success we do everything on the partial enc ctx. 442******************************************************************************/ 443 444static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, bool spnego_wrap) 445{ 446 NTSTATUS status; 447 DATA_BLOB chal = data_blob_null; 448 DATA_BLOB response = data_blob_null; 449 450 status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx); 451 if (!NT_STATUS_IS_OK(status)) { 452 return status; 453 } 454 455 status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal); 456 457 /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED 458 * for success ... */ 459 460 if (spnego_wrap) { 461 response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); 462 data_blob_free(&chal); 463 } else { 464 /* Return the raw blob. */ 465 response = chal; 466 } 467 468 SAFE_FREE(*ppdata); 469 *ppdata = (unsigned char *)memdup(response.data, response.length); 470 if ((*ppdata) == NULL && response.length > 0) { 471 status = NT_STATUS_NO_MEMORY; 472 } 473 *p_data_size = response.length; 474 data_blob_free(&response); 475 476 return status; 477} 478 479/****************************************************************************** 480 Do the SPNEGO encryption negotiation. Parameters are in/out. 481 Based off code in smbd/sesssionsetup.c 482 Until success we do everything on the partial enc ctx. 483******************************************************************************/ 484 485static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn, 486 unsigned char **ppdata, 487 size_t *p_data_size, 488 unsigned char **pparam, 489 size_t *p_param_size) 490{ 491 NTSTATUS status; 492 DATA_BLOB blob = data_blob_null; 493 DATA_BLOB secblob = data_blob_null; 494 char *kerb_mech = NULL; 495 496 blob = data_blob_const(*ppdata, *p_data_size); 497 498 status = parse_spnego_mechanisms(blob, &secblob, &kerb_mech); 499 if (!NT_STATUS_IS_OK(status)) { 500 return nt_status_squash(status); 501 } 502 503 /* We should have no partial context at this point. */ 504 505 srv_free_encryption_context(&partial_srv_trans_enc_ctx); 506 507 if (kerb_mech) { 508 SAFE_FREE(kerb_mech); 509 510#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5) 511 status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob); 512#else 513 /* Currently we don't SPNEGO negotiate 514 * back to NTLMSSP as we do in sessionsetupX. We should... */ 515 return NT_STATUS_LOGON_FAILURE; 516#endif 517 } else { 518 status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, true); 519 } 520 521 data_blob_free(&secblob); 522 523 if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { 524 srv_free_encryption_context(&partial_srv_trans_enc_ctx); 525 return nt_status_squash(status); 526 } 527 528 if (NT_STATUS_IS_OK(status)) { 529 /* Return the context we're using for this encryption state. */ 530 if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { 531 return NT_STATUS_NO_MEMORY; 532 } 533 SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num); 534 *p_param_size = 2; 535 } 536 537 return status; 538} 539 540/****************************************************************************** 541 Complete a SPNEGO encryption negotiation. Parameters are in/out. 542 We only get this for a NTLM auth second stage. 543******************************************************************************/ 544 545static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn, 546 unsigned char **ppdata, 547 size_t *p_data_size, 548 unsigned char **pparam, 549 size_t *p_param_size) 550{ 551 NTSTATUS status; 552 DATA_BLOB blob = data_blob_null; 553 DATA_BLOB auth = data_blob_null; 554 DATA_BLOB auth_reply = data_blob_null; 555 DATA_BLOB response = data_blob_null; 556 struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx; 557 558 /* We must have a partial context here. */ 559 560 if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { 561 srv_free_encryption_context(&partial_srv_trans_enc_ctx); 562 return NT_STATUS_INVALID_PARAMETER; 563 } 564 565 blob = data_blob_const(*ppdata, *p_data_size); 566 if (!spnego_parse_auth(blob, &auth)) { 567 srv_free_encryption_context(&partial_srv_trans_enc_ctx); 568 return NT_STATUS_INVALID_PARAMETER; 569 } 570 571 status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply); 572 data_blob_free(&auth); 573 574 /* From RFC4178. 575 * 576 * supportedMech 577 * 578 * This field SHALL only be present in the first reply from the 579 * target. 580 * So set mechOID to NULL here. 581 */ 582 583 response = spnego_gen_auth_response(&auth_reply, status, NULL); 584 data_blob_free(&auth_reply); 585 586 if (NT_STATUS_IS_OK(status)) { 587 /* Return the context we're using for this encryption state. */ 588 if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { 589 return NT_STATUS_NO_MEMORY; 590 } 591 SSVAL(*pparam,0,ec->es->enc_ctx_num); 592 *p_param_size = 2; 593 } 594 595 SAFE_FREE(*ppdata); 596 *ppdata = (unsigned char *)memdup(response.data, response.length); 597 if ((*ppdata) == NULL && response.length > 0) 598 return NT_STATUS_NO_MEMORY; 599 *p_data_size = response.length; 600 data_blob_free(&response); 601 return status; 602} 603 604/****************************************************************************** 605 Raw NTLM encryption negotiation. Parameters are in/out. 606 This function does both steps. 607******************************************************************************/ 608 609static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn, 610 unsigned char **ppdata, 611 size_t *p_data_size, 612 unsigned char **pparam, 613 size_t *p_param_size) 614{ 615 NTSTATUS status; 616 DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size); 617 DATA_BLOB response = data_blob_null; 618 struct smb_srv_trans_enc_ctx *ec; 619 620 if (!partial_srv_trans_enc_ctx) { 621 /* This is the initial step. */ 622 status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, false); 623 if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) { 624 srv_free_encryption_context(&partial_srv_trans_enc_ctx); 625 return nt_status_squash(status); 626 } 627 return status; 628 } 629 630 ec = partial_srv_trans_enc_ctx; 631 if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) { 632 srv_free_encryption_context(&partial_srv_trans_enc_ctx); 633 return NT_STATUS_INVALID_PARAMETER; 634 } 635 636 /* Second step. */ 637 status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response); 638 639 if (NT_STATUS_IS_OK(status)) { 640 /* Return the context we're using for this encryption state. */ 641 if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) { 642 return NT_STATUS_NO_MEMORY; 643 } 644 SSVAL(*pparam,0,ec->es->enc_ctx_num); 645 *p_param_size = 2; 646 } 647 648 /* Return the raw blob. */ 649 SAFE_FREE(*ppdata); 650 *ppdata = (unsigned char *)memdup(response.data, response.length); 651 if ((*ppdata) == NULL && response.length > 0) 652 return NT_STATUS_NO_MEMORY; 653 *p_data_size = response.length; 654 data_blob_free(&response); 655 return status; 656} 657 658/****************************************************************************** 659 Do the SPNEGO encryption negotiation. Parameters are in/out. 660******************************************************************************/ 661 662NTSTATUS srv_request_encryption_setup(connection_struct *conn, 663 unsigned char **ppdata, 664 size_t *p_data_size, 665 unsigned char **pparam, 666 size_t *p_param_size) 667{ 668 unsigned char *pdata = *ppdata; 669 670 SAFE_FREE(*pparam); 671 *p_param_size = 0; 672 673 if (*p_data_size < 1) { 674 return NT_STATUS_INVALID_PARAMETER; 675 } 676 677 if (pdata[0] == ASN1_APPLICATION(0)) { 678 /* its a negTokenTarg packet */ 679 return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size); 680 } 681 682 if (pdata[0] == ASN1_CONTEXT(1)) { 683 /* It's an auth packet */ 684 return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); 685 } 686 687 /* Maybe it's a raw unwrapped auth ? */ 688 if (*p_data_size < 7) { 689 return NT_STATUS_INVALID_PARAMETER; 690 } 691 692 if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) { 693 return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size); 694 } 695 696 DEBUG(1,("srv_request_encryption_setup: Unknown packet\n")); 697 698 return NT_STATUS_LOGON_FAILURE; 699} 700 701/****************************************************************************** 702 Negotiation was successful - turn on server-side encryption. 703******************************************************************************/ 704 705static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec) 706{ 707 if (!ec || !ec->es) { 708 return NT_STATUS_LOGON_FAILURE; 709 } 710 711 if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) { 712 if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) != 713 (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) { 714 return NT_STATUS_INVALID_PARAMETER; 715 } 716 } 717 /* Todo - check gssapi case. */ 718 719 return NT_STATUS_OK; 720} 721 722/****************************************************************************** 723 Negotiation was successful - turn on server-side encryption. 724******************************************************************************/ 725 726NTSTATUS srv_encryption_start(connection_struct *conn) 727{ 728 NTSTATUS status; 729 730 /* Check that we are really doing sign+seal. */ 731 status = check_enc_good(partial_srv_trans_enc_ctx); 732 if (!NT_STATUS_IS_OK(status)) { 733 return status; 734 } 735 /* Throw away the context we're using currently (if any). */ 736 srv_free_encryption_context(&srv_trans_enc_ctx); 737 738 /* Steal the partial pointer. Deliberate shallow copy. */ 739 srv_trans_enc_ctx = partial_srv_trans_enc_ctx; 740 srv_trans_enc_ctx->es->enc_on = true; 741 742 partial_srv_trans_enc_ctx = NULL; 743 744 DEBUG(1,("srv_encryption_start: context negotiated\n")); 745 return NT_STATUS_OK; 746} 747 748/****************************************************************************** 749 Shutdown all server contexts. 750******************************************************************************/ 751 752void server_encryption_shutdown(void) 753{ 754 srv_free_encryption_context(&partial_srv_trans_enc_ctx); 755 srv_free_encryption_context(&srv_trans_enc_ctx); 756} 757