Print this page
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-4064 NULL session setup gets internal error
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3080 SMB1 signing problem with Kerberos auth.
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-1404 fixed malformed entries in zone_sun.tab
NEX-1799 Failure to authenticate domain account from Win2003 with NTLM(v1)
SMB-149 mount.cifs RedHat\Centos 6 doesn't work with default security options
SMB-126 Unable to map share from win2003/win2003R2 client ...
SMB-107 Unable to map network drive in workgroup mode using Windows XP...
SMB-68 NTLM(v1) inbound with Extended Session Security
SMB-123 misleading log messages from smb_logon
SMB-56 extended security NTLMSSP, inbound
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/smbsrv/smbd/smbd_ntlmssp.c
+++ new/usr/src/cmd/smbsrv/smbd/smbd_ntlmssp.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 - * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
13 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
14 14 */
15 15
16 16 /*
17 17 * SPNEGO back-end for NTLMSSP. See [MS-NLMP]
18 18 */
19 19
20 20 #include <sys/types.h>
21 21 #include <sys/byteorder.h>
22 22 #include <strings.h>
23 23 #include "smbd.h"
24 24 #include "smbd_authsvc.h"
25 25 #include "netsmb/ntlmssp.h"
26 26 #include <assert.h>
27 27
28 28 /* A shorter alias for a crazy long name from [MS-NLMP] */
29 29 #define NTLMSSP_NEGOTIATE_NTLM2 \
30 30 NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
31 31
32 32 /* Need this in a header somewhere */
33 33 #ifdef _LITTLE_ENDIAN
34 34 /* little-endian values on little-endian */
35 35 #define htolel(x) ((uint32_t)(x))
36 36 #define letohl(x) ((uint32_t)(x))
37 37 #else /* (BYTE_ORDER == LITTLE_ENDIAN) */
38 38 /* little-endian values on big-endian (swap) */
39 39 #define letohl(x) BSWAP_32(x)
40 40 #define htolel(x) BSWAP_32(x)
41 41 #endif /* (BYTE_ORDER == LITTLE_ENDIAN) */
42 42
43 43 typedef struct ntlmssp_backend {
44 44 uint32_t expect_type;
45 45 uint32_t clnt_flags;
46 46 uint32_t srv_flags;
47 47 char srv_challenge[8];
48 48 } ntlmssp_backend_t;
49 49
50 50 struct genhdr {
51 51 char h_id[8]; /* "NTLMSSP" */
52 52 uint32_t h_type;
53 53 };
54 54
55 55 struct sec_buf {
56 56 uint16_t sb_length;
57 57 uint16_t sb_maxlen;
58 58 uint32_t sb_offset;
59 59 };
60 60
61 61 struct nego_hdr {
62 62 char h_id[8];
63 63 uint32_t h_type;
64 64 uint32_t h_flags;
65 65 /* workstation domain, name (place holders) */
66 66 uint16_t ws_dom[4];
67 67 uint16_t ws_name[4];
68 68 };
69 69
70 70 struct auth_hdr {
71 71 char h_id[8];
72 72 uint32_t h_type;
73 73 struct sec_buf h_lm_resp;
74 74 struct sec_buf h_nt_resp;
75 75 struct sec_buf h_domain;
76 76 struct sec_buf h_user;
77 77 struct sec_buf h_wksta;
78 78 struct sec_buf h_essn_key; /* encrypted session key */
79 79 uint32_t h_flags;
80 80 /* Version struct (optional) */
81 81 /* MIC hash (optional) */
82 82 };
83 83
84 84 /* Allow turning these off for debugging, etc. */
85 85 int smbd_signing_enabled = 1;
86 86
87 87 int smbd_constant_challenge = 0;
88 88 static uint8_t constant_chal[8] = {
89 89 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
90 90
91 91 static int smbd_ntlmssp_negotiate(authsvc_context_t *);
92 92 static int smbd_ntlmssp_authenticate(authsvc_context_t *);
93 93 static int encode_avpair_str(smb_msgbuf_t *, uint16_t, char *);
94 94 static int decode_secbuf_bin(smb_msgbuf_t *, struct sec_buf *, void **);
95 95 static int decode_secbuf_str(smb_msgbuf_t *, struct sec_buf *, char **);
96 96
97 97 /*
98 98 * Initialize this context for NTLMSSP, if possible.
99 99 */
100 100 int
101 101 smbd_ntlmssp_init(authsvc_context_t *ctx)
102 102 {
103 103 ntlmssp_backend_t *be;
104 104
105 105 be = malloc(sizeof (*be));
106 106 if (be == 0)
107 107 return (NT_STATUS_NO_MEMORY);
108 108 bzero(be, sizeof (*be));
109 109 be->expect_type = NTLMSSP_MSGTYPE_NEGOTIATE;
110 110 ctx->ctx_backend = be;
111 111
112 112 return (0);
113 113 }
114 114
115 115 void
116 116 smbd_ntlmssp_fini(authsvc_context_t *ctx)
117 117 {
118 118 free(ctx->ctx_backend);
119 119 }
120 120
121 121 /*
122 122 * Handle an auth message
123 123 */
124 124 int
125 125 smbd_ntlmssp_work(authsvc_context_t *ctx)
126 126 {
127 127 struct genhdr *ihdr = ctx->ctx_ibodybuf;
128 128 ntlmssp_backend_t *be = ctx->ctx_backend;
129 129 uint32_t mtype;
130 130 int rc;
131 131
132 132 if (ctx->ctx_ibodylen < sizeof (*ihdr))
133 133 return (NT_STATUS_INVALID_PARAMETER);
134 134
135 135 if (bcmp(ihdr->h_id, "NTLMSSP", 8))
136 136 return (NT_STATUS_INVALID_PARAMETER);
137 137 mtype = letohl(ihdr->h_type);
138 138 if (mtype != be->expect_type)
139 139 return (NT_STATUS_INVALID_PARAMETER);
140 140
141 141 switch (mtype) {
142 142 case NTLMSSP_MSGTYPE_NEGOTIATE:
143 143 ctx->ctx_orawtype = LSA_MTYPE_ES_CONT;
144 144 rc = smbd_ntlmssp_negotiate(ctx);
145 145 break;
146 146 case NTLMSSP_MSGTYPE_AUTHENTICATE:
147 147 ctx->ctx_orawtype = LSA_MTYPE_ES_DONE;
148 148 rc = smbd_ntlmssp_authenticate(ctx);
149 149 break;
150 150
151 151 default:
152 152 case NTLMSSP_MSGTYPE_CHALLENGE:
153 153 /* Sent by servers, not received. */
154 154 rc = NT_STATUS_INVALID_PARAMETER;
155 155 break;
156 156 }
157 157
158 158 return (rc);
159 159 }
160 160
161 161 #if (MAXHOSTNAMELEN < NETBIOS_NAME_SZ)
162 162 #error "MAXHOSTNAMELEN < NETBIOS_NAME_SZ"
163 163 #endif
164 164
165 165 /*
166 166 * Handle an NTLMSSP_MSGTYPE_NEGOTIATE message, and reply
167 167 * with an NTLMSSP_MSGTYPE_CHALLENGE message.
168 168 * See: [MS-NLMP] 2.2.1.1, 3.2.5.1.1
169 169 */
170 170 static int
171 171 smbd_ntlmssp_negotiate(authsvc_context_t *ctx)
172 172 {
173 173 char tmp_name[MAXHOSTNAMELEN];
174 174 ntlmssp_backend_t *be = ctx->ctx_backend;
175 175 struct nego_hdr *ihdr = ctx->ctx_ibodybuf;
176 176 smb_msgbuf_t mb;
177 177 uint8_t *save_scan;
178 178 int secmode;
179 179 int mbflags;
180 180 int rc;
181 181 size_t var_start, var_end;
182 182 uint16_t var_size;
183 183
184 184 if (ctx->ctx_ibodylen < sizeof (*ihdr))
185 185 return (NT_STATUS_INVALID_PARAMETER);
186 186 be->clnt_flags = letohl(ihdr->h_flags);
187 187
188 188 /*
189 189 * Looks like we can ignore ws_dom, ws_name.
190 190 * Otherwise would parse those here.
191 191 */
192 192
193 193 secmode = smb_config_get_secmode();
194 194 if (smbd_constant_challenge) {
195 195 (void) memcpy(be->srv_challenge, constant_chal,
196 196 sizeof (be->srv_challenge));
197 197 } else {
198 198 randomize(be->srv_challenge, sizeof (be->srv_challenge));
199 199 }
200 200
201 201 /*
202 202 * Compute srv_flags
203 203 */
204 204 be->srv_flags =
205 205 NTLMSSP_REQUEST_TARGET |
206 206 NTLMSSP_NEGOTIATE_NTLM |
207 207 NTLMSSP_NEGOTIATE_TARGET_INFO;
208 208 be->srv_flags |= be->clnt_flags & (
209 209 NTLMSSP_NEGOTIATE_NTLM2 |
210 210 NTLMSSP_NEGOTIATE_128 |
211 211 NTLMSSP_NEGOTIATE_KEY_EXCH |
212 212 NTLMSSP_NEGOTIATE_56);
213 213
214 214 if (smbd_signing_enabled) {
215 215 be->srv_flags |= be->clnt_flags & (
216 216 NTLMSSP_NEGOTIATE_SIGN |
217 217 NTLMSSP_NEGOTIATE_SEAL |
218 218 NTLMSSP_NEGOTIATE_ALWAYS_SIGN);
219 219 }
220 220
221 221 if (be->clnt_flags & NTLMSSP_NEGOTIATE_UNICODE)
222 222 be->srv_flags |= NTLMSSP_NEGOTIATE_UNICODE;
223 223 else if (be->clnt_flags & NTLMSSP_NEGOTIATE_OEM)
224 224 be->srv_flags |= NTLMSSP_NEGOTIATE_OEM;
225 225
226 226 /* LM Key is mutually exclusive with NTLM2 */
227 227 if ((be->srv_flags & NTLMSSP_NEGOTIATE_NTLM2) == 0 &&
228 228 (be->clnt_flags & NTLMSSP_NEGOTIATE_LM_KEY) != 0)
229 229 be->srv_flags |= NTLMSSP_NEGOTIATE_LM_KEY;
230 230
231 231 /* Get our "target name" */
232 232 if (secmode == SMB_SECMODE_DOMAIN) {
233 233 be->srv_flags |= NTLMSSP_TARGET_TYPE_DOMAIN;
234 234 rc = smb_getdomainname(tmp_name, NETBIOS_NAME_SZ);
235 235 } else {
236 236 be->srv_flags |= NTLMSSP_TARGET_TYPE_SERVER;
237 237 rc = smb_getnetbiosname(tmp_name, NETBIOS_NAME_SZ);
238 238 }
239 239 if (rc)
240 240 goto errout;
241 241
242 242 /*
243 243 * Build the NTLMSSP_MSGTYPE_CHALLENGE message.
244 244 */
245 245 mbflags = SMB_MSGBUF_NOTERM;
246 246 if (be->srv_flags & NTLMSSP_NEGOTIATE_UNICODE)
247 247 mbflags |= SMB_MSGBUF_UNICODE;
248 248 smb_msgbuf_init(&mb, ctx->ctx_obodybuf, ctx->ctx_obodylen, mbflags);
249 249
250 250 /*
251 251 * Fixed size parts
252 252 */
253 253 rc = smb_msgbuf_encode(
254 254 &mb, "8clwwll8cllwwl", /* offset, name (fmt) */
255 255 "NTLMSSP", /* 0: signature (8c) */
256 256 NTLMSSP_MSGTYPE_CHALLENGE, /* 8: type (l) */
257 257 0, 0, 0, /* filled later: 12: target name (wwl) */
258 258 be->srv_flags, /* 20: flags (l) */
259 259 be->srv_challenge, /* 24: (8c) */
260 260 0, 0, /* 32: reserved (ll) */
261 261 0, 0, 0); /* filled later: 40: target info (wwl) */
262 262 #define TARGET_NAME_OFFSET 12
263 263 #define TARGET_INFO_OFFSET 40
264 264 if (rc < 0)
265 265 goto errout;
266 266
267 267 /*
268 268 * Variable length parts.
269 269 *
270 270 * Target name
271 271 */
272 272 var_start = smb_msgbuf_used(&mb);
273 273 rc = smb_msgbuf_encode(&mb, "u", tmp_name);
274 274 var_end = smb_msgbuf_used(&mb);
275 275 var_size = (uint16_t)(var_end - var_start);
276 276 if (rc < 0)
277 277 goto errout;
278 278
279 279 /* overwrite target name offset+lengths */
280 280 save_scan = mb.scan;
281 281 mb.scan = mb.base + TARGET_NAME_OFFSET;
282 282 (void) smb_msgbuf_encode(&mb, "wwl", var_size, var_size, var_start);
283 283 mb.scan = save_scan;
284 284
285 285 /*
286 286 * Target info (AvPairList)
287 287 *
288 288 * These AV pairs are like our name/value pairs, but have
289 289 * numeric identifiers instead of names. There are many
290 290 * of these, but we put only the four expected by Windows:
291 291 * NetBIOS computer name
292 292 * NetBIOS domain name
293 293 * DNS computer name
294 294 * DNS domain name
295 295 * Note that "domain" above (even "DNS domain") refers to
296 296 * the AD domain of which we're a member, which may be
297 297 * _different_ from the configured DNS domain.
298 298 *
299 299 * Also note that in "workgroup" mode (not a domain member)
300 300 * all "domain" fields should be set to the same values as
301 301 * the "computer" fields ("bare" host name, not FQDN).
302 302 */
303 303 var_start = smb_msgbuf_used(&mb);
304 304
305 305 /* NetBIOS Computer Name */
306 306 if (smb_getnetbiosname(tmp_name, NETBIOS_NAME_SZ))
307 307 goto errout;
308 308 if (encode_avpair_str(&mb, MsvAvNbComputerName, tmp_name) < 0)
309 309 goto errout;
310 310
311 311 if (secmode != SMB_SECMODE_DOMAIN) {
312 312 /*
313 313 * Workgroup mode. Set all to hostname.
314 314 * tmp_name = netbios hostname from above.
315 315 */
316 316 if (encode_avpair_str(&mb, MsvAvNbDomainName, tmp_name) < 0)
317 317 goto errout;
318 318 /*
319 319 * Want the bare computer name here (not FQDN).
320 320 */
321 321 if (smb_gethostname(tmp_name, MAXHOSTNAMELEN, SMB_CASE_LOWER))
322 322 goto errout;
323 323 if (encode_avpair_str(&mb, MsvAvDnsComputerName, tmp_name) < 0)
324 324 goto errout;
325 325 if (encode_avpair_str(&mb, MsvAvDnsDomainName, tmp_name) < 0)
326 326 goto errout;
327 327 } else {
328 328 /*
329 329 * Domain mode. Use real host and domain values.
330 330 */
331 331
332 332 /* NetBIOS Domain Name */
333 333 if (smb_getdomainname(tmp_name, NETBIOS_NAME_SZ))
334 334 goto errout;
335 335 if (encode_avpair_str(&mb, MsvAvNbDomainName, tmp_name) < 0)
336 336 goto errout;
337 337
338 338 /* DNS Computer Name */
339 339 if (smb_getfqhostname(tmp_name, MAXHOSTNAMELEN))
340 340 goto errout;
341 341 if (encode_avpair_str(&mb, MsvAvDnsComputerName, tmp_name) < 0)
342 342 goto errout;
343 343
344 344 /* DNS Domain Name */
345 345 if (smb_getfqdomainname(tmp_name, MAXHOSTNAMELEN))
346 346 goto errout;
347 347 if (encode_avpair_str(&mb, MsvAvDnsDomainName, tmp_name) < 0)
348 348 goto errout;
349 349 }
350 350
351 351 /* End marker */
352 352 if (smb_msgbuf_encode(&mb, "ww", MsvAvEOL, 0) < 0)
353 353 goto errout;
354 354 var_end = smb_msgbuf_used(&mb);
355 355 var_size = (uint16_t)(var_end - var_start);
356 356
357 357 /* overwrite target offset+lengths */
358 358 save_scan = mb.scan;
359 359 mb.scan = mb.base + TARGET_INFO_OFFSET;
360 360 (void) smb_msgbuf_encode(&mb, "wwl", var_size, var_size, var_start);
361 361 mb.scan = save_scan;
362 362
363 363 ctx->ctx_obodylen = smb_msgbuf_used(&mb);
364 364 smb_msgbuf_term(&mb);
365 365
366 366 be->expect_type = NTLMSSP_MSGTYPE_AUTHENTICATE;
367 367
368 368 return (0);
369 369
370 370 errout:
371 371 smb_msgbuf_term(&mb);
372 372 return (NT_STATUS_INTERNAL_ERROR);
373 373 }
374 374
375 375 static int
376 376 encode_avpair_str(smb_msgbuf_t *mb, uint16_t AvId, char *name)
377 377 {
378 378 int rc;
379 379 uint16_t len;
380 380
381 381 len = smb_wcequiv_strlen(name);
382 382 rc = smb_msgbuf_encode(mb, "wwU", AvId, len, name);
383 383 return (rc);
384 384 }
385 385
386 386 /*
387 387 * Handle an NTLMSSP_MSGTYPE_AUTHENTICATE message.
388 388 * See: [MS-NLMP] 2.2.1.3, 3.2.5.1.2
389 389 */
390 390 static int
391 391 smbd_ntlmssp_authenticate(authsvc_context_t *ctx)
392 392 {
393 393 struct auth_hdr hdr;
394 394 smb_msgbuf_t mb;
395 395 smb_logon_t user_info;
396 396 smb_token_t *token = NULL;
397 397 ntlmssp_backend_t *be = ctx->ctx_backend;
398 398 void *lm_resp;
399 399 void *nt_resp;
400 400 char *domain;
401 401 char *user;
402 402 char *wksta;
403 403 void *essn_key; /* encrypted session key (optional) */
404 404 int mbflags;
405 405 uint_t status = NT_STATUS_INTERNAL_ERROR;
406 406 char combined_challenge[SMBAUTH_CHAL_SZ];
407 407 unsigned char kxkey[SMBAUTH_HASH_SZ];
408 408 boolean_t ntlm_v1x = B_FALSE;
409 409
410 410 bzero(&user_info, sizeof (user_info));
411 411
412 412 /*
413 413 * Parse the NTLMSSP_MSGTYPE_AUTHENTICATE message.
414 414 */
415 415 if (ctx->ctx_ibodylen < sizeof (hdr))
416 416 return (NT_STATUS_INVALID_PARAMETER);
417 417 mbflags = SMB_MSGBUF_NOTERM;
418 418 if (be->srv_flags & NTLMSSP_NEGOTIATE_UNICODE)
419 419 mbflags |= SMB_MSGBUF_UNICODE;
420 420 smb_msgbuf_init(&mb, ctx->ctx_ibodybuf, ctx->ctx_ibodylen, mbflags);
421 421 bzero(&hdr, sizeof (hdr));
422 422
423 423 if (smb_msgbuf_decode(&mb, "12.") < 0)
424 424 goto errout;
425 425 if (decode_secbuf_bin(&mb, &hdr.h_lm_resp, &lm_resp) < 0)
426 426 goto errout;
427 427 if (decode_secbuf_bin(&mb, &hdr.h_nt_resp, &nt_resp) < 0)
428 428 goto errout;
429 429 if (decode_secbuf_str(&mb, &hdr.h_domain, &domain) < 0)
430 430 goto errout;
431 431 if (decode_secbuf_str(&mb, &hdr.h_user, &user) < 0)
432 432 goto errout;
433 433 if (decode_secbuf_str(&mb, &hdr.h_wksta, &wksta) < 0)
434 434 goto errout;
435 435 if (decode_secbuf_bin(&mb, &hdr.h_essn_key, &essn_key) < 0)
436 436 goto errout;
437 437 if (smb_msgbuf_decode(&mb, "l", &be->clnt_flags) < 0)
438 438 goto errout;
439 439
440 440 if (be->clnt_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
441 441 if (hdr.h_essn_key.sb_length < 16 || essn_key == NULL)
442 442 goto errout;
443 443 }
444 444
445 445 user_info.lg_level = NETR_NETWORK_LOGON;
446 446 user_info.lg_flags = 0;
447 447
448 448 user_info.lg_ntlm_flags = be->clnt_flags;
449 449 user_info.lg_username = (user) ? user : "";
450 450 user_info.lg_domain = (domain) ? domain : "";
451 451 user_info.lg_workstation = (wksta) ? wksta : "";
452 452
453 453 user_info.lg_clnt_ipaddr =
454 454 ctx->ctx_clinfo.lci_clnt_ipaddr;
455 455 user_info.lg_local_port = 445;
456 456
457 457 user_info.lg_challenge_key.len = SMBAUTH_CHAL_SZ;
458 458 user_info.lg_challenge_key.val = (uint8_t *)be->srv_challenge;
459 459
460 460 user_info.lg_nt_password.len = hdr.h_nt_resp.sb_length;
461 461 user_info.lg_nt_password.val = nt_resp;
462 462
463 463 user_info.lg_lm_password.len = hdr.h_lm_resp.sb_length;
464 464 user_info.lg_lm_password.val = lm_resp;
465 465
466 466 user_info.lg_native_os = ctx->ctx_clinfo.lci_native_os;
467 467 user_info.lg_native_lm = ctx->ctx_clinfo.lci_native_lm;
468 468
469 469 /*
470 470 * If we're doing extended session security, the challenge
471 471 * this OWF was computed with is different. [MS-NLMP 3.3.1]
472 472 * It's: MD5(concat(ServerChallenge,ClientChallenge))
473 473 * where the ClientChallenge is in the LM resp. field.
474 474 */
475 475 if (user_info.lg_nt_password.len == SMBAUTH_LM_RESP_SZ &&
476 476 user_info.lg_lm_password.len >= SMBAUTH_CHAL_SZ &&
477 477 (be->clnt_flags & NTLMSSP_NEGOTIATE_NTLM2) != 0) {
478 478 smb_auth_ntlm2_mkchallenge(combined_challenge,
479 479 be->srv_challenge, lm_resp);
480 480 user_info.lg_challenge_key.val =
481 481 (uint8_t *)combined_challenge;
|
↓ open down ↓ |
458 lines elided |
↑ open up ↑ |
482 482 user_info.lg_lm_password.len = 0;
483 483 ntlm_v1x = B_TRUE;
484 484 }
485 485
486 486 /*
487 487 * This (indirectly) calls smb_auth_validate() to
488 488 * check that the client gave us a valid hash.
489 489 */
490 490 token = smbd_user_auth_logon(&user_info);
491 491 if (token == NULL) {
492 - status = NT_STATUS_ACCESS_DENIED;
492 + status = user_info.lg_status;
493 + if (status == 0) /* should not happen */
494 + status = NT_STATUS_INTERNAL_ERROR;
493 495 goto errout;
494 496 }
495 497
496 498 if (token->tkn_ssnkey.val != NULL &&
497 499 token->tkn_ssnkey.len == SMBAUTH_HASH_SZ) {
498 500
499 501 /*
500 502 * At this point, token->tkn_session_key is the
501 503 * "Session Base Key" [MS-NLMP] 3.2.5.1.2
502 504 * Compute the final session key. First need the
503 505 * "Key Exchange Key" [MS-NLMP] 3.4.5.1
504 506 */
505 507 if (ntlm_v1x) {
506 508 smb_auth_ntlm2_kxkey(kxkey,
507 509 be->srv_challenge, lm_resp,
508 510 token->tkn_ssnkey.val);
509 511 } else {
510 512 /* KXKEY is the Session Base Key. */
511 513 (void) memcpy(kxkey, token->tkn_ssnkey.val,
512 514 SMBAUTH_HASH_SZ);
513 515 }
514 516
515 517 /*
516 518 * If the client give us an encrypted session key,
517 519 * decrypt it (RC4) using the "key exchange key".
518 520 */
519 521 if (be->clnt_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
520 522 /* RC4 args: result, key, data */
521 523 (void) smb_auth_RC4(token->tkn_ssnkey.val,
522 524 SMBAUTH_HASH_SZ, kxkey, SMBAUTH_HASH_SZ,
523 525 essn_key, hdr.h_essn_key.sb_length);
524 526 } else {
525 527 /* Final key is the KXKEY */
526 528 (void) memcpy(token->tkn_ssnkey.val, kxkey,
527 529 SMBAUTH_HASH_SZ);
528 530 }
529 531 }
530 532
531 533 ctx->ctx_token = token;
532 534 ctx->ctx_obodylen = 0;
533 535
534 536 smb_msgbuf_term(&mb);
535 537 return (0);
536 538
537 539 errout:
538 540 smb_msgbuf_term(&mb);
539 541 return (status);
540 542 }
541 543
542 544 static int
543 545 decode_secbuf_bin(smb_msgbuf_t *mb, struct sec_buf *sb, void **binp)
544 546 {
545 547 int rc;
546 548
547 549 *binp = NULL;
548 550 rc = smb_msgbuf_decode(
549 551 mb, "wwl",
550 552 &sb->sb_length,
551 553 &sb->sb_maxlen,
552 554 &sb->sb_offset);
553 555 if (rc < 0)
554 556 return (rc);
555 557
556 558 if (sb->sb_offset > mb->max)
557 559 return (SMB_MSGBUF_UNDERFLOW);
558 560 if (sb->sb_length > (mb->max - sb->sb_offset))
559 561 return (SMB_MSGBUF_UNDERFLOW);
560 562 if (sb->sb_length == 0)
561 563 return (rc);
562 564
563 565 *binp = mb->base + sb->sb_offset;
564 566 return (0);
565 567 }
566 568
567 569 static int
568 570 decode_secbuf_str(smb_msgbuf_t *mb, struct sec_buf *sb, char **cpp)
569 571 {
570 572 uint8_t *save_scan;
571 573 int rc;
572 574
573 575 *cpp = NULL;
574 576 rc = smb_msgbuf_decode(
575 577 mb, "wwl",
576 578 &sb->sb_length,
577 579 &sb->sb_maxlen,
578 580 &sb->sb_offset);
579 581 if (rc < 0)
580 582 return (rc);
581 583
582 584 if (sb->sb_offset > mb->max)
583 585 return (SMB_MSGBUF_UNDERFLOW);
584 586 if (sb->sb_length > (mb->max - sb->sb_offset))
585 587 return (SMB_MSGBUF_UNDERFLOW);
586 588 if (sb->sb_length == 0)
587 589 return (rc);
588 590
589 591 save_scan = mb->scan;
590 592 mb->scan = mb->base + sb->sb_offset;
591 593 rc = smb_msgbuf_decode(mb, "#u", (int)sb->sb_length, cpp);
592 594 mb->scan = save_scan;
593 595
594 596 return (rc);
595 597 }
|
↓ open down ↓ |
93 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX