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 2018 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_ESS \ 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_ssnkey[NTLM_HASH_SZ]; 78 uchar_t ss_kxkey[NTLM_HASH_SZ]; 79 } ntlmssp_state_t; 80 81 /* 82 * So called "security buffer". 83 * A lot like an RPC string. 84 */ 85 struct sec_buf { 86 uint16_t sb_length; 87 uint16_t sb_maxlen; 88 uint32_t sb_offset; 89 }; 90 #define ID_SZ 8 91 static const char ntlmssp_id[ID_SZ] = "NTLMSSP"; 92 93 static int 94 ntlm_rand_ssn_key(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 | 253 NTLMSSP_NEGOTIATE_ESS | 254 NTLMSSP_NEGOTIATE_128 | 255 NTLMSSP_NEGOTIATE_KEY_EXCH | 256 NTLMSSP_NEGOTIATE_56; 257 258 if ((ctx->ct_vopt & SMBVOPT_SIGNING_ENABLED) == 0) 259 ssp_st->ss_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 260 261 bcopy(ntlmssp_id, &hdr.h_id, ID_SZ); 262 hdr.h_type = NTLMSSP_MSGTYPE_NEGOTIATE; 263 hdr.h_flags = ssp_st->ss_flags; 264 265 /* 266 * We could put the client domain, client name strings 267 * here, (always in OEM format, upper-case), and set 268 * NTLMSSP_NEGOTIATE_OEM_..._SUPPLIED, but Windows 269 * leaves these NULL so let's do the same. 270 */ 271 (void) mb_put_sb_string(&mb2, &hdr.h_cldom, NULL, 0); 272 (void) mb_put_sb_string(&mb2, &hdr.h_wksta, NULL, 0); 273 274 /* 275 * Marshal the header (in LE order) 276 * then concatenate the 2nd part. 277 */ 278 (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM); 279 (void) mb_put_uint32le(out_mb, hdr.h_type); 280 (void) mb_put_uint32le(out_mb, hdr.h_flags); 281 (void) mb_put_sb_hdr(out_mb, &hdr.h_cldom); 282 (void) mb_put_sb_hdr(out_mb, &hdr.h_wksta); 283 284 err = mb_put_mbuf(out_mb, mb2.mb_top); 285 286 return (err); 287 } 288 289 /* 290 * Parse a Type 2 message 291 */ 292 int 293 ntlmssp_get_type2(struct ssp_ctx *sp, struct mbdata *in_mb) 294 { 295 struct type2hdr { 296 char h_id[ID_SZ]; 297 uint32_t h_type; 298 struct sec_buf h_target_name; 299 uint32_t h_flags; 300 uint8_t h_challenge[8]; 301 uint32_t h_context[2]; /* optional */ 302 struct sec_buf h_target_info; /* optional */ 303 } hdr; 304 struct mbdata top_mb, tmp_mb; 305 struct mbuf *m; 306 int err, uc; 307 int min_hdr_sz = offsetof(struct type2hdr, h_context); 308 struct smb_ctx *ctx = sp->smb_ctx; 309 ntlmssp_state_t *ssp_st = sp->sp_private; 310 char *buf = NULL; 311 312 if (m_totlen(in_mb->mb_top) < min_hdr_sz) { 313 err = EBADRPC; 314 goto out; 315 } 316 317 /* 318 * Save the mbdata pointers before we consume anything. 319 * Careful to NOT free this (would be dup. free) 320 * We use this below to find data based on offsets 321 * from the start of the header. 322 */ 323 top_mb = *in_mb; 324 325 /* Parse the fixed size header stuff. */ 326 bzero(&hdr, sizeof (hdr)); 327 (void) md_get_mem(in_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM); 328 (void) md_get_uint32le(in_mb, &hdr.h_type); 329 if (hdr.h_type != NTLMSSP_MSGTYPE_CHALLENGE) { 330 err = EPROTO; 331 goto out; 332 } 333 (void) md_get_sb_hdr(in_mb, &hdr.h_target_name); 334 (void) md_get_uint32le(in_mb, &hdr.h_flags); 335 (void) md_get_mem(in_mb, &hdr.h_challenge, NTLM_CHAL_SZ, MB_MSYSTEM); 336 337 /* 338 * Save flags, server challenge for later. 339 */ 340 ssp_st->ss_flags = hdr.h_flags; 341 bcopy(&hdr.h_challenge, ctx->ct_srv_chal, NTLM_CHAL_SZ); 342 343 /* 344 * Turn off flags that might have been given but 345 * that we don't want to send with authenticate. 346 */ 347 uc = hdr.h_flags & NTLMSSP_NEGOTIATE_UNICODE; 348 ssp_st->ss_flags &= ~NTLMSSP_NEGOTIATE_VERSION; 349 350 /* 351 * Now find out if the optional parts are there. 352 */ 353 if ((m_totlen(top_mb.mb_top) > sizeof (hdr)) && 354 (hdr.h_target_name.sb_offset >= sizeof (hdr))) { 355 (void) md_get_uint32le(in_mb, &hdr.h_context[0]); 356 (void) md_get_uint32le(in_mb, &hdr.h_context[1]); 357 (void) md_get_sb_hdr(in_mb, &hdr.h_target_info); 358 } 359 360 /* 361 * Get the target name string. (Server name or 362 * Primary domain name.) First get a copy of the 363 * data from the offset/length indicated in the 364 * security buffer header; then parse the string. 365 */ 366 err = md_get_sb_data(&top_mb, &hdr.h_target_name, &m); 367 if (err) 368 goto out; 369 mb_initm(&tmp_mb, m); 370 err = md_get_string(&tmp_mb, &ssp_st->ss_target_name, uc); 371 mb_done(&tmp_mb); 372 373 /* 374 * Get the target info blob, if present. 375 */ 376 if (hdr.h_target_info.sb_offset >= sizeof (hdr)) { 377 err = md_get_sb_data(&top_mb, &hdr.h_target_info, 378 &ssp_st->ss_target_info); 379 } 380 381 out: 382 if (buf != NULL) 383 free(buf); 384 385 return (err); 386 } 387 388 /* 389 * Build a Type 3 message 390 * 391 * This message has a header section containing offsets to 392 * data later in the message. We use the common trick of 393 * building it in two parts and then concatenatening. 394 */ 395 int 396 ntlmssp_put_type3(struct ssp_ctx *sp, struct mbdata *out_mb) 397 { 398 struct type3hdr { 399 char h_id[ID_SZ]; 400 uint32_t h_type; 401 struct sec_buf h_lm_resp; 402 struct sec_buf h_nt_resp; 403 struct sec_buf h_domain; 404 struct sec_buf h_user; 405 struct sec_buf h_wksta; 406 struct sec_buf h_ssn_key; 407 uint32_t h_flags; 408 /* Version struct (ommitted) */ 409 uchar_t h_mic[NTLM_HASH_SZ]; 410 } hdr; 411 struct mbdata lm_mbc; /* LM response */ 412 struct mbdata nt_mbc; /* NT response */ 413 struct mbdata ti_mbc; /* target info */ 414 struct mbdata ek_mbc; /* encrypted session key */ 415 struct mbdata mb2; /* payload */ 416 int err, uc; 417 struct smb_ctx *ctx = sp->smb_ctx; 418 ntlmssp_state_t *ssp_st = sp->sp_private; 419 uchar_t *pmic; 420 421 bzero(&hdr, sizeof (hdr)); 422 bzero(&lm_mbc, sizeof (lm_mbc)); 423 bzero(&nt_mbc, sizeof (nt_mbc)); 424 bzero(&ti_mbc, sizeof (ti_mbc)); 425 bzero(&ek_mbc, sizeof (ek_mbc)); 426 bzero(&mb2, sizeof (mb2)); 427 428 /* 429 * Fill in the NTLMSSP header, etc. 430 */ 431 if ((err = mb_init(&mb2)) != 0) 432 goto out; 433 mb2.mb_count = sizeof (hdr); 434 uc = ssp_st->ss_flags & NTLMSSP_NEGOTIATE_UNICODE; 435 436 bcopy(ntlmssp_id, &hdr.h_id, ID_SZ); 437 hdr.h_type = NTLMSSP_MSGTYPE_AUTHENTICATE; 438 hdr.h_flags = ssp_st->ss_flags; 439 440 /* 441 * Put the NTLMv2/LMv2 or NTLM/LM (v1) responses, 442 * and compute the session key, etc. 443 */ 444 if (ctx->ct_authflags & SMB_AT_ANON) { 445 /* 446 * We're setting up a NULL session, meaning 447 * the lm_mbc, nt_mbc parts remain empty. 448 * Let's add the "anon" flag (hint), and 449 * as we have no OWF hashes, we can't use 450 * "extended session security" (_ESS). 451 * The SessionBaseKey is all zeros, so 452 * the KeyExchangeKey is too. Otherwise 453 * this is like NTLMv2/LMv2 454 */ 455 ssp_st->ss_flags |= NTLMSSP_NEGOTIATE_NULL_SESSION; 456 ssp_st->ss_flags &= ~NTLMSSP_NEGOTIATE_ESS; 457 hdr.h_flags = ssp_st->ss_flags; 458 err = 0; 459 /* KeyExchangeKey = SessionBaseKey = (zeros) */ 460 memset(ssp_st->ss_ssnkey, 0, NTLM_HASH_SZ); 461 memset(ssp_st->ss_kxkey, 0, NTLM_HASH_SZ); 462 } else if (ctx->ct_authflags & SMB_AT_NTLM2) { 463 /* 464 * Doing NTLMv2/LMv2 465 */ 466 err = ntlm_build_target_info(ctx, 467 ssp_st->ss_target_info, &ti_mbc); 468 if (err) 469 goto out; 470 err = ntlm_put_v2_responses(ctx, &ti_mbc, 471 &lm_mbc, &nt_mbc, ssp_st->ss_ssnkey); 472 if (err) 473 goto out; 474 /* KeyExchangeKey = SessionBaseKey (v2) */ 475 memcpy(ssp_st->ss_kxkey, ssp_st->ss_ssnkey, NTLM_HASH_SZ); 476 } else if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_ESS) { 477 /* 478 * Doing NTLM ("v1x") which is NTLM with 479 * "Extended Session Security" 480 */ 481 err = ntlm_put_v1x_responses(ctx, 482 &lm_mbc, &nt_mbc, ssp_st->ss_ssnkey); 483 if (err) 484 goto out; 485 /* 486 * "v1x computes the KeyExchangeKey from both the 487 * server and client nonce and (v1) SessionBaseKey. 488 */ 489 ntlm2_kxkey(ctx, &lm_mbc, ssp_st->ss_ssnkey, 490 ssp_st->ss_kxkey); 491 } else { 492 /* 493 * Doing plain old NTLM (and LM if enabled) 494 */ 495 err = ntlm_put_v1_responses(ctx, 496 &lm_mbc, &nt_mbc, ssp_st->ss_ssnkey); 497 if (err) 498 goto out; 499 /* KeyExchangeKey = SessionBaseKey (v1) */ 500 memcpy(ssp_st->ss_kxkey, ssp_st->ss_ssnkey, NTLM_HASH_SZ); 501 } 502 503 /* 504 * Compute the "ExportedSessionKey" and (possibly) the 505 * "EncryptedRandomSesionKey". [MS-NLMP 3.1.5.1.2] 506 */ 507 if (ssp_st->ss_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { 508 err = ntlm_rand_ssn_key(ssp_st, &ek_mbc); 509 if (err) 510 goto out; 511 } else { 512 /* ExportedSessionKey is the KeyExchangeKey */ 513 memcpy(ssp_st->ss_ssnkey, ssp_st->ss_kxkey, NTLM_HASH_SZ); 514 /* EncryptedRandomSessionKey remains NULL */ 515 } 516 517 err = mb_put_sb_data(&mb2, &hdr.h_lm_resp, lm_mbc.mb_top); 518 lm_mbc.mb_top = NULL; /* consumed */ 519 if (err) 520 goto out; 521 err = mb_put_sb_data(&mb2, &hdr.h_nt_resp, nt_mbc.mb_top); 522 nt_mbc.mb_top = NULL; /* consumed */ 523 if (err) 524 goto out; 525 526 /* 527 * Put the "target" (domain), user, workstation 528 */ 529 err = mb_put_sb_string(&mb2, &hdr.h_domain, ctx->ct_domain, uc); 530 if (err) 531 goto out; 532 err = mb_put_sb_string(&mb2, &hdr.h_user, ctx->ct_user, uc); 533 if (err) 534 goto out; 535 err = mb_put_sb_string(&mb2, &hdr.h_wksta, ctx->ct_locname, uc); 536 if (err) 537 goto out; 538 539 /* 540 * Put the "Encrypted Random Session Key", if any. 541 * (ek_mbc.mb_top may be NULL) 542 */ 543 err = mb_put_sb_data(&mb2, &hdr.h_ssn_key, ek_mbc.mb_top); 544 ek_mbc.mb_top = NULL; /* consumed (if any) */ 545 if (err) 546 goto out; 547 548 /* 549 * Marshal the header (in LE order) 550 * then concatenate the 2nd part. 551 */ 552 (void) mb_put_mem(out_mb, &hdr.h_id, ID_SZ, MB_MSYSTEM); 553 (void) mb_put_uint32le(out_mb, hdr.h_type); 554 555 (void) mb_put_sb_hdr(out_mb, &hdr.h_lm_resp); 556 (void) mb_put_sb_hdr(out_mb, &hdr.h_nt_resp); 557 558 (void) mb_put_sb_hdr(out_mb, &hdr.h_domain); 559 (void) mb_put_sb_hdr(out_mb, &hdr.h_user); 560 (void) mb_put_sb_hdr(out_mb, &hdr.h_wksta); 561 562 (void) mb_put_sb_hdr(out_mb, &hdr.h_ssn_key); 563 (void) mb_put_uint32le(out_mb, hdr.h_flags); 564 565 /* Put zeros for the MIC - filled in later */ 566 pmic = mb_reserve(out_mb, NTLM_HASH_SZ); 567 568 /* Put the payload. */ 569 err = mb_put_mbuf(out_mb, mb2.mb_top); 570 mb2.mb_top = NULL; /* consumed */ 571 572 /* 573 * Compute the MIC and stuff that in... 574 * The MIC is apparently optional. 575 */ 576 (void) pmic; 577 578 out: 579 mb_done(&mb2); 580 mb_done(&lm_mbc); 581 mb_done(&nt_mbc); 582 mb_done(&ti_mbc); 583 mb_done(&ek_mbc); 584 585 return (err); 586 } 587 588 /* 589 * Helper for ntlmssp_put_type3 when doing key exchange. 590 * 591 * "ExportedSessionKey" is what we give to the "application" 592 * layer, which in here means the MAC key for SMB signing. 593 * With "key exchange", we replace the ExportedSessionKey 594 * with random data and send that (encrypted) to the peer. 595 */ 596 static int 597 ntlm_rand_ssn_key( 598 ntlmssp_state_t *ssp_st, 599 struct mbdata *ek_mbp) 600 { 601 602 uchar_t *encr_ssn_key; 603 int err; 604 605 if ((err = mb_init(ek_mbp)) != 0) 606 return (err); 607 encr_ssn_key = mb_reserve(ek_mbp, NTLM_HASH_SZ); 608 609 /* Set "ExportedSessionKey to NONCE(16) */ 610 (void) smb_get_urandom(ssp_st->ss_ssnkey, NTLM_HASH_SZ); 611 612 /* Set "EncryptedRandomSessionKey" to RC4(...) */ 613 err = smb_encrypt_RC4(encr_ssn_key, NTLM_HASH_SZ, 614 ssp_st->ss_kxkey, NTLM_HASH_SZ, 615 ssp_st->ss_ssnkey, NTLM_HASH_SZ); 616 617 return (err); 618 } 619 620 /* 621 * ntlmssp_final 622 * 623 * Called after successful authentication. 624 * Save the session key. 625 */ 626 int 627 ntlmssp_final(struct ssp_ctx *sp) 628 { 629 struct smb_ctx *ctx = sp->smb_ctx; 630 ntlmssp_state_t *ssp_st = sp->sp_private; 631 int err = 0; 632 633 /* 634 * Update/save the session key. 635 */ 636 if (ctx->ct_ssnkey_buf != NULL) { 637 free(ctx->ct_ssnkey_buf); 638 ctx->ct_ssnkey_buf = NULL; 639 } 640 ctx->ct_ssnkey_buf = malloc(NTLM_HASH_SZ); 641 if (ctx->ct_ssnkey_buf == NULL) { 642 err = ENOMEM; 643 goto out; 644 } 645 ctx->ct_ssnkey_len = NTLM_HASH_SZ; 646 memcpy(ctx->ct_ssnkey_buf, ssp_st->ss_ssnkey, NTLM_HASH_SZ); 647 648 out: 649 return (err); 650 } 651 652 /* 653 * ntlmssp_next_token 654 * 655 * See ssp.c: ssp_ctx_next_token 656 */ 657 int 658 ntlmssp_next_token(struct ssp_ctx *sp, struct mbdata *in_mb, 659 struct mbdata *out_mb) 660 { 661 int err; 662 663 if (out_mb == NULL) { 664 /* final call on successful auth. */ 665 err = ntlmssp_final(sp); 666 goto out; 667 } 668 669 /* Will build an ouptut token. */ 670 err = mb_init(out_mb); 671 if (err) 672 goto out; 673 674 /* 675 * When called with in_mb == NULL, it means 676 * this is the first call for this session, 677 * so put a Type 1 (initialize) token. 678 */ 679 if (in_mb == NULL) { 680 err = ntlmssp_put_type1(sp, out_mb); 681 goto out; 682 } 683 684 /* 685 * This is not the first call, so 686 * parse the response token we received. 687 * It should be a Type 2 (challenge). 688 * Then put a Type 3 (authenticate) 689 */ 690 err = ntlmssp_get_type2(sp, in_mb); 691 if (err) 692 goto out; 693 694 err = ntlmssp_put_type3(sp, out_mb); 695 696 out: 697 if (err) 698 DPRINT("ret: %d", err); 699 return (err); 700 } 701 702 /* 703 * ntlmssp_ctx_destroy 704 * 705 * Destroy mechanism-specific data. 706 */ 707 void 708 ntlmssp_destroy(struct ssp_ctx *sp) 709 { 710 ntlmssp_state_t *ssp_st; 711 712 ssp_st = sp->sp_private; 713 if (ssp_st != NULL) { 714 sp->sp_private = NULL; 715 free(ssp_st->ss_target_name); 716 m_freem(ssp_st->ss_target_info); 717 free(ssp_st); 718 } 719 } 720 721 /* 722 * ntlmssp_init_clnt 723 * 724 * Initialize a new NTLMSSP client context. 725 */ 726 int 727 ntlmssp_init_client(struct ssp_ctx *sp) 728 { 729 ntlmssp_state_t *ssp_st; 730 smb_ctx_t *ctx = sp->smb_ctx; 731 732 if ((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 /* Get the client nonce. */ 739 (void) smb_get_urandom(ctx->ct_clnonce, NTLM_CHAL_SZ); 740 741 ssp_st = calloc(1, sizeof (*ssp_st)); 742 if (ssp_st == NULL) 743 return (ENOMEM); 744 745 sp->sp_nexttok = ntlmssp_next_token; 746 sp->sp_destroy = ntlmssp_destroy; 747 sp->sp_private = ssp_st; 748 749 return (0); 750 } 751