1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 /* 28 * NT Lan Manager Security Support Provider (NTLMSSP) 29 * 30 * Based on information from the "Davenport NTLM" page: 31 * http://davenport.sourceforge.net/ntlm.html 32 */ 33 34 35 #include <errno.h> 36 #include <stdio.h> 37 #include <stddef.h> 38 #include <stdlib.h> 39 #include <unistd.h> 40 #include <strings.h> 41 #include <netdb.h> 42 #include <libintl.h> 43 #include <xti.h> 44 #include <assert.h> 45 46 #include <sys/types.h> 47 #include <sys/time.h> 48 #include <sys/byteorder.h> 49 #include <sys/socket.h> 50 #include <sys/fcntl.h> 51 52 #include <netinet/in.h> 53 #include <netinet/tcp.h> 54 #include <arpa/inet.h> 55 56 #include <netsmb/smb.h> 57 #include <netsmb/smb_lib.h> 58 #include <netsmb/mchain.h> 59 60 #include "private.h" 61 #include "charsets.h" 62 #include "smb_crypt.h" 63 #include "spnego.h" 64 #include "derparse.h" 65 #include "ssp.h" 66 #include "ntlm.h" 67 #include "ntlmssp.h" 68 69 /* A shorter alias for a crazy long name from [MS-NLMP] */ 70 #define NTLMSSP_NEGOTIATE_NTLM2 \ 71 NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 72 73 typedef struct ntlmssp_state { 74 uint32_t ss_flags; 75 char *ss_target_name; /* Primary domain or server name */ 76 struct mbuf *ss_target_info; 77 uchar_t ss_kxkey[NTLM_HASH_SZ]; 78 } ntlmssp_state_t; 79 80 /* 81 * So called "security buffer". 82 * A lot like an RPC string. 83 */ 84 struct sec_buf { 85 uint16_t sb_length; 86 uint16_t sb_maxlen; 87 uint32_t sb_offset; 88 }; 89 #define ID_SZ 8 90 static const char ntlmssp_id[ID_SZ] = "NTLMSSP"; 91 92 static int 93 ntlm_rand_ssn_key(struct smb_ctx *ctx, 94 ntlmssp_state_t *ssp_st, struct mbdata *ek_mbp); 95 96 /* 97 * Get a "security buffer" (header part) 98 */ 99 static int 100 md_get_sb_hdr(struct mbdata *mbp, struct sec_buf *sb) 101 { 102 int err; 103 104 (void) md_get_uint16le(mbp, &sb->sb_length); 105 (void) md_get_uint16le(mbp, &sb->sb_maxlen); 106 err = md_get_uint32le(mbp, &sb->sb_offset); 107 108 return (err); 109 } 110 111 /* 112 * Get a "security buffer" (data part), where 113 * the data is delivered as an mbuf. 114 */ 115 static int 116 md_get_sb_data(struct mbdata *mbp, struct sec_buf *sb, struct mbuf **mp) 117 { 118 struct mbdata tmp_mb; 119 int err; 120 121 /* 122 * Setup tmp_mb to point to the start of the header. 123 * This is a dup ref - do NOT free it. 124 */ 125 mb_initm(&tmp_mb, mbp->mb_top); 126 127 /* Skip data up to the offset. */ 128 err = md_get_mem(&tmp_mb, NULL, sb->sb_offset, MB_MSYSTEM); 129 if (err) 130 return (err); 131 132 /* Get the data (as an mbuf). */ 133 err = md_get_mbuf(&tmp_mb, sb->sb_maxlen, mp); 134 135 return (err); 136 } 137 138 /* 139 * Put a "security buffer" (header part) 140 */ 141 static int 142 mb_put_sb_hdr(struct mbdata *mbp, struct sec_buf *sb) 143 { 144 int err; 145 146 (void) mb_put_uint16le(mbp, sb->sb_length); 147 (void) mb_put_uint16le(mbp, sb->sb_maxlen); 148 err = mb_put_uint32le(mbp, sb->sb_offset); 149 150 return (err); 151 } 152 153 /* 154 * Put a "security buffer" (data part), where 155 * the data is an mbuf. Note: consumes m. 156 */ 157 static int 158 mb_put_sb_data(struct mbdata *mbp, struct sec_buf *sb, struct mbuf *m) 159 { 160 int cnt0; 161 int err = 0; 162 163 sb->sb_offset = cnt0 = mbp->mb_count; 164 if (m != NULL) 165 err = mb_put_mbuf(mbp, m); 166 sb->sb_maxlen = sb->sb_length = mbp->mb_count - cnt0; 167 168 return (err); 169 } 170 171 /* 172 * Put a "security buffer" (data part), where 173 * the data is a string (OEM or unicode). 174 * 175 * The string is NOT null terminated. 176 */ 177 static int 178 mb_put_sb_string(struct mbdata *mbp, struct sec_buf *sb, 179 const char *str, int unicode) 180 { 181 int err, trim; 182 struct mbdata tmp_mb; 183 184 bzero(&tmp_mb, sizeof (tmp_mb)); 185 186 if (str != NULL && *str != '\0') { 187 /* 188 * Put the string into a temp. mbuf, 189 * then chop off the null terminator 190 * before appending to caller's mbp. 191 */ 192 err = mb_init(&tmp_mb); 193 if (err) 194 return (err); 195 err = mb_put_string(&tmp_mb, str, unicode); 196 if (err) 197 return (err); 198 199 trim = (unicode) ? 2 : 1; 200 if (tmp_mb.mb_cur->m_len < trim) 201 trim = 0; 202 tmp_mb.mb_cur->m_len -= trim; 203 } 204 205 err = mb_put_sb_data(mbp, sb, tmp_mb.mb_top); 206 /* 207 * Note: tmp_mb.mb_top (if any) is consumed, 208 * so do NOT free it (no mb_done) 209 */ 210 return (err); 211 } 212 213 /* 214 * Build a Type 1 message 215 * 216 * This message has a header section containing offsets to 217 * data later in the message. We use the common trick of 218 * building it in two parts and then concatenatening. 219 */ 220 int 221 ntlmssp_put_type1(struct ssp_ctx *sp, struct mbdata *out_mb) 222 { 223 struct type1hdr { 224 char h_id[ID_SZ]; 225 uint32_t h_type; 226 uint32_t h_flags; 227 struct sec_buf h_cldom; 228 struct sec_buf h_wksta; 229 } hdr; 230 struct mbdata mb2; /* 2nd part */ 231 int err; 232 struct smb_ctx *ctx = sp->smb_ctx; 233 ntlmssp_state_t *ssp_st = sp->sp_private; 234 235 if ((err = mb_init(&mb2)) != 0) 236 return (err); 237 mb2.mb_count = sizeof (hdr); 238 239 /* 240 * The initial negotiation flags represent the union of all 241 * options we support. The server selects from these. 242 * See: [MS-NLMP 2.2.2.5 NEGOTIATE] 243 */ 244 ssp_st->ss_flags = 245 NTLMSSP_NEGOTIATE_UNICODE | 246 NTLMSSP_NEGOTIATE_OEM | 247 NTLMSSP_REQUEST_TARGET | 248 NTLMSSP_NEGOTIATE_SIGN | 249 NTLMSSP_NEGOTIATE_SEAL | 250 /* NTLMSSP_NEGOTIATE_LM_KEY (never) */ 251 NTLMSSP_NEGOTIATE_NTLM | 252 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN (set below) */ 253 NTLMSSP_NEGOTIATE_NTLM2 | 254 NTLMSSP_NEGOTIATE_128 | 255 NTLMSSP_NEGOTIATE_KEY_EXCH | 256 NTLMSSP_NEGOTIATE_56; 257 258 if (ctx->ct_vcflags & SMBV_WILL_SIGN) { 259 ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 260 ctx->ct_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE; 261 } 262 263 bcopy(ntlmssp_id, &hdr.h_id, ID_SZ); 264 hdr.h_type = NTLMSSP_MSGTYPE_NEGOTIATE; 265 hdr.h_flags = ssp_st->ss_flags; 266 267 /* 268 * We could put the client domain, client name strings 269 * here, (always in OEM format, upper-case), and set 270 * NTLMSSP_NEGOTIATE_OEM_..._SUPPLIED, but Windows 271 * leaves these NULL so let's do the same. 272 */ 273 (void) mb_put_sb_string(&mb2, &hdr.h_cldom, NULL, 0); 274 (void) mb_put_sb_string(&mb2, &hdr.h_wksta, NULL, 0); 275 276 /* 277 * Marshal the header (in LE order) 278 * then concatenate the 2nd part. 279 */ 280 (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM); 281 (void) mb_put_uint32le(out_mb, hdr.h_type); 282 (void) mb_put_uint32le(out_mb, hdr.h_flags); 283 (void) mb_put_sb_hdr(out_mb, &hdr.h_cldom); 284 (void) mb_put_sb_hdr(out_mb, &hdr.h_wksta); 285 286 err = mb_put_mbuf(out_mb, mb2.mb_top); 287 288 return (err); 289 } 290 291 /* 292 * Parse a Type 2 message 293 */ 294 int 295 ntlmssp_get_type2(struct ssp_ctx *sp, struct mbdata *in_mb) 296 { 297 struct type2hdr { 298 char h_id[ID_SZ]; 299 uint32_t h_type; 300 struct sec_buf h_target_name; 301 uint32_t h_flags; 302 uint8_t h_challenge[8]; 303 uint32_t h_context[2]; /* optional */ 304 struct sec_buf h_target_info; /* optional */ 305 } hdr; 306 struct mbdata top_mb, tmp_mb; 307 struct mbuf *m; 308 int err, uc; 309 int min_hdr_sz = offsetof(struct type2hdr, h_context); 310 struct smb_ctx *ctx = sp->smb_ctx; 311 ntlmssp_state_t *ssp_st = sp->sp_private; 312 char *buf = NULL; 313 314 if (m_totlen(in_mb->mb_top) < min_hdr_sz) { 315 err = EBADRPC; 316 goto out; 317 } 318 319 /* 320 * Save the mbdata pointers before we consume anything. 321 * Careful to NOT free this (would be dup. free) 322 * We use this below to find data based on offsets 323 * from the start of the header. 324 */ 325 top_mb = *in_mb; 326 327 /* Parse the fixed size header stuff. */ 328 bzero(&hdr, sizeof (hdr)); 329 (void) md_get_mem(in_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM); 330 (void) md_get_uint32le(in_mb, &hdr.h_type); 331 if (hdr.h_type != NTLMSSP_MSGTYPE_CHALLENGE) { 332 err = EPROTO; 333 goto out; 334 } 335 (void) md_get_sb_hdr(in_mb, &hdr.h_target_name); 336 (void) md_get_uint32le(in_mb, &hdr.h_flags); 337 (void) md_get_mem(in_mb, &hdr.h_challenge, NTLM_CHAL_SZ, MB_MSYSTEM); 338 339 /* 340 * Save flags, server challenge for later. 341 */ 342 ssp_st->ss_flags = hdr.h_flags; 343 bcopy(&hdr.h_challenge, ctx->ct_srv_chal, NTLM_CHAL_SZ); 344 345 /* 346 * Turn off flags that might have been given but 347 * that we don't want to send with authenticate. 348 */ 349 uc = hdr.h_flags & NTLMSSP_NEGOTIATE_UNICODE; 350 ssp_st->ss_flags &= ~NTLMSSP_NEGOTIATE_VERSION; 351 352 /* 353 * Now find out if the optional parts are there. 354 */ 355 if ((m_totlen(top_mb.mb_top) > sizeof (hdr)) && 356 (hdr.h_target_name.sb_offset >= sizeof (hdr))) { 357 (void) md_get_uint32le(in_mb, &hdr.h_context[0]); 358 (void) md_get_uint32le(in_mb, &hdr.h_context[1]); 359 (void) md_get_sb_hdr(in_mb, &hdr.h_target_info); 360 } 361 362 /* 363 * Get the target name string. (Server name or 364 * Primary domain name.) First get a copy of the 365 * data from the offset/length indicated in the 366 * security buffer header; then parse the string. 367 */ 368 err = md_get_sb_data(&top_mb, &hdr.h_target_name, &m); 369 if (err) 370 goto out; 371 mb_initm(&tmp_mb, m); 372 err = md_get_string(&tmp_mb, &ssp_st->ss_target_name, uc); 373 mb_done(&tmp_mb); 374 375 /* 376 * Get the target info blob, if present. 377 */ 378 if (hdr.h_target_info.sb_offset >= sizeof (hdr)) { 379 err = md_get_sb_data(&top_mb, &hdr.h_target_info, 380 &ssp_st->ss_target_info); 381 } 382 383 out: 384 if (buf != NULL) 385 free(buf); 386 387 return (err); 388 } 389 390 /* 391 * Build a Type 3 message 392 * 393 * This message has a header section containing offsets to 394 * data later in the message. We use the common trick of 395 * building it in two parts and then concatenatening. 396 */ 397 int 398 ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb) 399 { 400 struct type3hdr { 401 char h_id[ID_SZ]; 402 uint32_t h_type; 403 struct sec_buf h_lm_resp; 404 struct sec_buf h_nt_resp; 405 struct sec_buf h_domain; 406 struct sec_buf h_user; 407 struct sec_buf h_wksta; 408 struct sec_buf h_ssn_key; 409 uint32_t h_flags; 410 /* Version struct (ommitted) */ 411 uchar_t h_mic[NTLM_HASH_SZ]; 412 } hdr; 413 struct mbdata lm_mbc; /* LM response */ 414 struct mbdata nt_mbc; /* NT response */ 415 struct mbdata ti_mbc; /* target info */ 416 struct mbdata ek_mbc; /* encrypted session key */ 417 struct mbdata mb2; /* payload */ 418 int err, uc; 419 struct smb_ctx *ctx = sp->smb_ctx; 420 ntlmssp_state_t *ssp_st = sp->sp_private; 421 uchar_t *pmic; 422 423 bzero(&hdr, sizeof (hdr)); 424 bzero(&lm_mbc, sizeof (lm_mbc)); 425 bzero(&nt_mbc, sizeof (nt_mbc)); 426 bzero(&ti_mbc, sizeof (ti_mbc)); 427 bzero(&ek_mbc, sizeof (ek_mbc)); 428 bzero(&mb2, sizeof (mb2)); 429 430 /* 431 * Fill in the NTLMSSP header, etc. 432 */ 433 if ((err = mb_init(&mb2)) != 0) 434 goto out; 435 mb2.mb_count = sizeof (hdr); 436 uc = ssp_st->ss_flags & NTLMSSP_NEGOTIATE_UNICODE; 437 438 bcopy(ntlmssp_id, &hdr.h_id, ID_SZ); 439 hdr.h_type = NTLMSSP_MSGTYPE_AUTHENTICATE; 440 hdr.h_flags = ssp_st->ss_flags; 441 442 /* 443 * Put the NTLMv2/LMv2 or NTLM/LM (v1) responses, 444 * and compute the session key, etc. 445 */ 446 if (ctx->ct_authflags & SMB_AT_ANON) { 447 /* 448 * We're setting up a NULL session, meaning 449 * the lm_mbc, nt_mbc parts remain empty. 450 * Let's add the "anon" flag (hint). 451 * As there is no session key, disable the 452 * fancy session key stuff. 453 */ 454 hdr.h_flags |= NTLMSSP_NEGOTIATE_NULL_SESSION; 455 ssp_st->ss_flags &= ~( 456 NTLMSSP_NEGOTIATE_NTLM2 | 457 NTLMSSP_NEGOTIATE_KEY_EXCH); 458 err = 0; 459 } else if (ctx->ct_authflags & SMB_AT_NTLM2) { 460 /* 461 * Doing NTLMv2/LMv2 462 */ 463 err = ntlm_build_target_info(ctx, 464 ssp_st->ss_target_info, &ti_mbc); 465 if (err) 466 goto out; 467 err = ntlm_put_v2_responses(ctx, &ti_mbc, 468 &lm_mbc, &nt_mbc); 469 if (err) 470 goto out; 471 /* The "key exg. key" is the session base key */ 472 memcpy(ssp_st->ss_kxkey, ctx->ct_ssn_key, NTLM_HASH_SZ); 473 474 } else if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_NTLM2) { 475 /* 476 * Doing NTLM ("v1x") which is NTLM with 477 * "Extended Session Security" 478 */ 479 err = ntlm_put_v1x_responses(ctx, 480 &lm_mbc, &nt_mbc); 481 if (err) 482 goto out; 483 /* Compute the "Key exchange key". */ 484 ntlm2_kxkey(ctx, &lm_mbc, ssp_st->ss_kxkey); 485 } else { 486 /* 487 * Doing plain old NTLM (and LM if enabled) 488 */ 489 err = ntlm_put_v1_responses(ctx, 490 &lm_mbc, &nt_mbc); 491 if (err) 492 goto out; 493 /* The "key exg. key" is the session base key */ 494 memcpy(ssp_st->ss_kxkey, ctx->ct_ssn_key, NTLM_HASH_SZ); 495 } 496 497 /* 498 * Compute the "Exported Session Key" and (possibly) 499 * the "Encrypted Random Sesion Key". 500 * [MS-NLMP 3.1.5.1.2] 501 */ 502 if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { 503 err = ntlm_rand_ssn_key(ctx, ssp_st, &ek_mbc); 504 if (err) 505 goto out; 506 } else { 507 /* ExportedSessionKey is the KeyExchangeKey */ 508 memcpy(ctx->ct_ssn_key, ssp_st->ss_kxkey, NTLM_HASH_SZ); 509 /* EncryptedRandomSessionKey remains NULL */ 510 } 511 512 err = mb_put_sb_data(&mb2, &hdr.h_lm_resp, lm_mbc.mb_top); 513 lm_mbc.mb_top = NULL; /* consumed */ 514 if (err) 515 goto out; 516 err = mb_put_sb_data(&mb2, &hdr.h_nt_resp, nt_mbc.mb_top); 517 nt_mbc.mb_top = NULL; /* consumed */ 518 if (err) 519 goto out; 520 521 /* 522 * Put the "target" (domain), user, workstation 523 */ 524 err = mb_put_sb_string(&mb2, &hdr.h_domain, ctx->ct_domain, uc); 525 if (err) 526 goto out; 527 err = mb_put_sb_string(&mb2, &hdr.h_user, ctx->ct_user, uc); 528 if (err) 529 goto out; 530 err = mb_put_sb_string(&mb2, &hdr.h_wksta, ctx->ct_locname, uc); 531 if (err) 532 goto out; 533 534 /* 535 * Put the "Encrypted Random Session Key", if any. 536 * (ek_mbc.mb_top may be NULL) 537 */ 538 err = mb_put_sb_data(&mb2, &hdr.h_ssn_key, ek_mbc.mb_top); 539 ek_mbc.mb_top = NULL; /* consumed (if any) */ 540 if (err) 541 goto out; 542 543 /* 544 * Marshal the header (in LE order) 545 * then concatenate the 2nd part. 546 */ 547 (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM); 548 (void) mb_put_uint32le(out_mb, hdr.h_type); 549 550 (void) mb_put_sb_hdr(out_mb, &hdr.h_lm_resp); 551 (void) mb_put_sb_hdr(out_mb, &hdr.h_nt_resp); 552 553 (void) mb_put_sb_hdr(out_mb, &hdr.h_domain); 554 (void) mb_put_sb_hdr(out_mb, &hdr.h_user); 555 (void) mb_put_sb_hdr(out_mb, &hdr.h_wksta); 556 557 (void) mb_put_sb_hdr(out_mb, &hdr.h_ssn_key); 558 (void) mb_put_uint32le(out_mb, hdr.h_flags); 559 560 /* Put zeros for the MIC - filled in later */ 561 pmic = mb_reserve(out_mb, NTLM_HASH_SZ); 562 563 /* Put the payload. */ 564 err = mb_put_mbuf(out_mb, mb2.mb_top); 565 mb2.mb_top = NULL; /* consumed */ 566 567 /* 568 * Compute the MIC and stuff that in... 569 * The MIC is apparently optional. 570 */ 571 (void) pmic; 572 573 out: 574 mb_done(&mb2); 575 mb_done(&lm_mbc); 576 mb_done(&nt_mbc); 577 mb_done(&ti_mbc); 578 mb_done(&ek_mbc); 579 580 return (err); 581 } 582 583 /* 584 * Helper for ntlmssp_put_type3 when doing key exchange. 585 * 586 * "ExportedSessionKey" is what we give to the "application" 587 * layer, which in here means the MAC key for SMB signing. 588 * With "key exchange", we replace the ExportedSessionKey 589 * with random data and send that (encrypted) to the peer. 590 */ 591 static int 592 ntlm_rand_ssn_key( 593 struct smb_ctx *ctx, 594 ntlmssp_state_t *ssp_st, 595 struct mbdata *ek_mbp) 596 { 597 598 uchar_t *encr_ssn_key; 599 int err; 600 601 if ((err = mb_init(ek_mbp)) != 0) 602 return (err); 603 encr_ssn_key = mb_reserve(ek_mbp, NTLM_HASH_SZ); 604 605 /* Set "ExportedSessionKey to NONCE(16) */ 606 (void) smb_get_urandom(ctx->ct_ssn_key, NTLM_HASH_SZ); 607 608 /* Set "EncryptedRandomSessionKey" to RC4(...) */ 609 err = smb_encrypt_RC4(encr_ssn_key, NTLM_HASH_SZ, 610 ssp_st->ss_kxkey, NTLM_HASH_SZ, 611 ctx->ct_ssn_key, NTLM_HASH_SZ); 612 613 return (err); 614 } 615 616 /* 617 * ntlmssp_final 618 * 619 * Called after successful authentication. 620 * Setup the MAC key for signing. 621 */ 622 int 623 ntlmssp_final(struct ssp_ctx *sp) 624 { 625 struct smb_ctx *ctx = sp->smb_ctx; 626 int err = 0; 627 628 /* 629 * MAC_key is just the session key, but 630 * Only on the first successful auth. 631 */ 632 if ((ctx->ct_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) && 633 (ctx->ct_mackey == NULL)) { 634 ctx->ct_mackeylen = NTLM_HASH_SZ; 635 ctx->ct_mackey = malloc(ctx->ct_mackeylen); 636 if (ctx->ct_mackey == NULL) { 637 ctx->ct_mackeylen = 0; 638 err = ENOMEM; 639 goto out; 640 } 641 memcpy(ctx->ct_mackey, ctx->ct_ssn_key, NTLM_HASH_SZ); 642 /* 643 * Apparently, the server used seq. no. zero 644 * for our previous message, so next is two. 645 */ 646 ctx->ct_mac_seqno = 2; 647 } 648 649 out: 650 return (err); 651 } 652 653 /* 654 * ntlmssp_next_token 655 * 656 * See ssp.c: ssp_ctx_next_token 657 */ 658 int 659 ntlmssp_next_token(struct ssp_ctx *sp, struct mbdata *in_mb, 660 struct mbdata *out_mb) 661 { 662 int err; 663 664 if (out_mb == NULL) { 665 /* final call on successful auth. */ 666 err = ntlmssp_final(sp); 667 goto out; 668 } 669 670 /* Will build an ouptut token. */ 671 err = mb_init(out_mb); 672 if (err) 673 goto out; 674 675 /* 676 * When called with in_mb == NULL, it means 677 * this is the first call for this session, 678 * so put a Type 1 (initialize) token. 679 */ 680 if (in_mb == NULL) { 681 err = ntlmssp_put_type1(sp, out_mb); 682 goto out; 683 } 684 685 /* 686 * This is not the first call, so 687 * parse the response token we received. 688 * It should be a Type 2 (challenge). 689 * Then put a Type 3 (authenticate) 690 */ 691 err = ntlmssp_get_type2(sp, in_mb); 692 if (err) 693 goto out; 694 695 err = ntlmssp_put_type3(sp, out_mb); 696 697 out: 698 if (err) 699 DPRINT("ret: %d", err); 700 return (err); 701 } 702 703 /* 704 * ntlmssp_ctx_destroy 705 * 706 * Destroy mechanism-specific data. 707 */ 708 void 709 ntlmssp_destroy(struct ssp_ctx *sp) 710 { 711 ntlmssp_state_t *ssp_st; 712 713 ssp_st = sp->sp_private; 714 if (ssp_st != NULL) { 715 sp->sp_private = NULL; 716 free(ssp_st->ss_target_name); 717 m_freem(ssp_st->ss_target_info); 718 free(ssp_st); 719 } 720 } 721 722 /* 723 * ntlmssp_init_clnt 724 * 725 * Initialize a new NTLMSSP client context. 726 */ 727 int 728 ntlmssp_init_client(struct ssp_ctx *sp) 729 { 730 ntlmssp_state_t *ssp_st; 731 732 if ((sp->smb_ctx->ct_authflags & 733 (SMB_AT_NTLM2 | SMB_AT_NTLM1 | SMB_AT_ANON)) == 0) { 734 DPRINT("No NTLM authflags"); 735 return (EINVAL); 736 } 737 738 ssp_st = calloc(1, sizeof (*ssp_st)); 739 if (ssp_st == NULL) 740 return (ENOMEM); 741 742 sp->sp_nexttok = ntlmssp_next_token; 743 sp->sp_destroy = ntlmssp_destroy; 744 sp->sp_private = ssp_st; 745 746 return (0); 747 } 748