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>
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 */
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);
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)
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;
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 }
|
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>
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 */
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);
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)
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;
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 }
|