1 /* 2 * Copyright (c) 2000-2001 Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: smb_smb.c,v 1.35.100.2 2005/06/02 00:55:39 lindak Exp $ 33 */ 34 35 /* 36 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 37 * Use is subject to license terms. 38 */ 39 40 /* 41 * various SMB requests. Most of the routines merely packs data into mbufs. 42 */ 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kmem.h> 46 #include <sys/proc.h> 47 #include <sys/lock.h> 48 #include <sys/socket.h> 49 #include <sys/uio.h> 50 #include <sys/random.h> 51 #include <sys/note.h> 52 #include <sys/cmn_err.h> 53 54 #ifdef APPLE 55 #include <sys/smb_apple.h> 56 #include <sys/utfconv.h> 57 #else 58 #include <netsmb/smb_osdep.h> 59 #endif 60 61 #include <netsmb/smb.h> 62 #include <netsmb/smb_conn.h> 63 #include <netsmb/smb_rq.h> 64 #include <netsmb/smb_subr.h> 65 #include <netsmb/smb_tran.h> 66 67 /* 68 * Largest size to use with LARGE_READ/LARGE_WRITE. 69 * Specs say up to 64k data bytes, but Windows traffic 70 * uses 60k... no doubt for some good reason. 71 * (Probably to keep 4k block alignment.) 72 * XXX: Move to smb.h maybe? 73 */ 74 #define SMB_MAX_LARGE_RW_SIZE (60*1024) 75 76 /* 77 * Default timeout values, all in seconds. 78 * Make these tunable (only via mdb for now). 79 */ 80 int smb_timo_notice = 15; 81 int smb_timo_default = 30; /* was SMB_DEFRQTIMO */ 82 int smb_timo_open = 45; 83 int smb_timo_read = 45; 84 int smb_timo_write = 60; /* was SMBWRTTIMO */ 85 int smb_timo_append = 90; 86 87 /* 88 * Debug/test feature to disable NTMLv2. 89 * Set this to zero to skip NTLMv2 90 */ 91 int nsmb_enable_ntlmv2 = 1; 92 93 static int smb_smb_read(struct smb_share *ssp, u_int16_t fid, 94 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo); 95 static int smb_smb_write(struct smb_share *ssp, u_int16_t fid, 96 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo); 97 98 static int smb_smb_readx(struct smb_share *ssp, u_int16_t fid, 99 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo); 100 static int smb_smb_writex(struct smb_share *ssp, u_int16_t fid, 101 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo); 102 103 struct smb_dialect { 104 int d_id; 105 const char *d_name; 106 }; 107 108 smb_unichar smb_unieol = 0; 109 110 static struct smb_dialect smb_dialects[] = { 111 {SMB_DIALECT_CORE, "PC NETWORK PROGRAM 1.0"}, 112 {SMB_DIALECT_LANMAN1_0, "LANMAN1.0"}, 113 {SMB_DIALECT_LANMAN2_0, "LM1.2X002"}, 114 {SMB_DIALECT_LANMAN2_1, "LANMAN2.1"}, 115 {SMB_DIALECT_NTLM0_12, "NT LM 0.12"}, 116 {-1, NULL} 117 }; 118 119 #define SMB_DIALECT_MAX \ 120 (sizeof (smb_dialects) / sizeof (struct smb_dialect) - 2) 121 122 /* 123 * Number of seconds between 1970 and 1601 year 124 */ 125 const u_int64_t DIFF1970TO1601 = 11644473600ULL; 126 127 void 128 smb_time_local2server(struct timespec *tsp, int tzoff, long *seconds) 129 { 130 /* 131 * XXX - what if we connected to the server when it was in 132 * daylight savings/summer time and we've subsequently switched 133 * to standard time, or vice versa, so that the time zone 134 * offset we got from the server is now wrong? 135 */ 136 *seconds = tsp->tv_sec - tzoff * 60; 137 /* - tz.tz_minuteswest * 60 - (wall_cmos_clock ? adjkerntz : 0) */ 138 } 139 140 void 141 smb_time_server2local(ulong_t seconds, int tzoff, struct timespec *tsp) 142 { 143 /* 144 * XXX - what if we connected to the server when it was in 145 * daylight savings/summer time and we've subsequently switched 146 * to standard time, or vice versa, so that the time zone 147 * offset we got from the server is now wrong? 148 */ 149 tsp->tv_sec = seconds + tzoff * 60; 150 /* + tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); */ 151 tsp->tv_nsec = 0; 152 } 153 154 /* 155 * Time from server comes as UTC, so no need to use tz 156 */ 157 /*ARGSUSED*/ 158 void 159 smb_time_NT2local(u_int64_t nsec, int tzoff, struct timespec *tsp) 160 { 161 smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp); 162 } 163 164 /*ARGSUSED*/ 165 void 166 smb_time_local2NT(struct timespec *tsp, int tzoff, u_int64_t *nsec) 167 { 168 long seconds; 169 170 smb_time_local2server(tsp, 0, &seconds); 171 *nsec = (((u_int64_t)(seconds) & ~1) + DIFF1970TO1601) * 172 (u_int64_t)10000000; 173 } 174 175 #if defined(NOICONVSUPPORT) || defined(lint) 176 extern int iconv_open(const char *to, const char *from, void **handle); 177 extern int iconv_close(void *handle); 178 #endif 179 180 int 181 smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred) 182 { 183 struct smb_dialect *dp; 184 struct smb_sopt *sp = NULL; 185 struct smb_rq *rqp; 186 struct mbchain *mbp; 187 struct mdchain *mdp; 188 u_int8_t wc, stime[8], sblen; 189 u_int16_t dindex, tw, tw1, swlen, bc; 190 int error; 191 int unicode = 0; 192 char *servercs; 193 void *servercshandle = NULL; 194 void *localcshandle = NULL; 195 int negotiated_signing = 0; 196 u_int16_t toklen; 197 198 /* 199 * We set various flags below to keep track of 200 * interesting things we learn from negotiation. 201 * Clear all the flags except these two, which 202 * are operational rather than protocol info. 203 */ 204 SMB_VC_LOCK(vcp); 205 vcp->vc_flags &= (SMBV_GONE | SMBV_RECONNECTING); 206 SMB_VC_UNLOCK(vcp); 207 208 /* 209 * Now vc_hflags and vc_hflags2. Careful with this: 210 * Leave SMB_FLAGS2_UNICODE off so mb_put_dstring 211 * marshalls the dialect strings in plain ascii. 212 * We'll turn that on below, if appropriate. 213 * 214 * Note: These flags are marshalled into the request 215 * when we call smb_rq_alloc, so changing them after 216 * this point does not affect THIS request. 217 */ 218 vcp->vc_hflags = SMB_FLAGS_CASELESS; 219 vcp->vc_hflags2 = (SMB_FLAGS2_ERR_STATUS | 220 SMB_FLAGS2_KNOWS_LONG_NAMES); 221 222 /* User-level may ask for extended security. */ 223 if (vcp->vc_vopt & SMBVOPT_EXT_SEC) 224 vcp->vc_hflags2 |= SMB_FLAGS2_EXT_SEC; 225 226 /* Also clear any old key (for reconnect) */ 227 if (vcp->vc_mackey != NULL) { 228 kmem_free(vcp->vc_mackey, vcp->vc_mackeylen); 229 vcp->vc_mackey = NULL; 230 vcp->vc_mackeylen = 0; 231 vcp->vc_seqno = 0; 232 } 233 234 sp = &vcp->vc_sopt; 235 bzero(sp, sizeof (struct smb_sopt)); 236 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_NEGOTIATE, scred, &rqp); 237 if (error) 238 return (error); 239 smb_rq_getrequest(rqp, &mbp); 240 smb_rq_wstart(rqp); 241 smb_rq_wend(rqp); 242 smb_rq_bstart(rqp); 243 for (dp = smb_dialects; dp->d_id != -1; dp++) { 244 mb_put_uint8(mbp, SMB_DT_DIALECT); 245 smb_put_dstring(mbp, vcp, dp->d_name, SMB_CS_NONE); 246 } 247 smb_rq_bend(rqp); 248 249 /* 250 * This request should not wait for 251 * connection state changes, etc. 252 */ 253 rqp->sr_flags |= SMBR_INTERNAL; 254 error = smb_rq_simple(rqp); 255 SMBSDEBUG("%d\n", error); 256 if (error) 257 goto bad; 258 259 smb_rq_getreply(rqp, &mdp); 260 do { 261 error = md_get_uint8(mdp, &wc); 262 if (error) 263 break; 264 error = md_get_uint16le(mdp, &dindex); 265 if (error) 266 break; 267 error = EBADRPC; 268 if (dindex > SMB_DIALECT_MAX) { 269 SMBERROR( 270 "Don't know how to talk with server %s (%d)\n", 271 vcp->vc_srvname, dindex); 272 break; 273 } 274 dp = smb_dialects + dindex; 275 if (dindex < SMB_DIALECT_MAX) { 276 SMBERROR( 277 "Server %s negotiated old dialect (%s)\n", 278 vcp->vc_srvname, dp->d_name); 279 } 280 sp->sv_proto = dp->d_id; 281 SMBSDEBUG("Dialect %s (%d, %d)\n", dp->d_name, dindex, wc); 282 if (dp->d_id >= SMB_DIALECT_NTLM0_12) { 283 if (wc != 17) 284 break; 285 md_get_uint8(mdp, &sp->sv_sm); 286 md_get_uint16le(mdp, &sp->sv_maxmux); 287 md_get_uint16le(mdp, &sp->sv_maxvcs); 288 md_get_uint32le(mdp, &sp->sv_maxtx); 289 md_get_uint32le(mdp, &sp->sv_maxraw); 290 md_get_uint32le(mdp, &sp->sv_skey); 291 md_get_uint32le(mdp, &sp->sv_caps); 292 md_get_mem(mdp, (char *)stime, 8, MB_MSYSTEM); 293 md_get_uint16le(mdp, (u_int16_t *)&sp->sv_tz); 294 md_get_uint8(mdp, &sblen); 295 error = md_get_uint16le(mdp, &bc); 296 if (error) 297 break; 298 299 /* BEGIN CSTYLED */ 300 /* 301 * Will we do SMB signing? Or block the connection? 302 * The table below describes this logic. References: 303 * [Windows Server Protocols: MS-SMB, sec. 3.2.4.2.3] 304 * http://msdn.microsoft.com/en-us/library/cc212511.aspx 305 * http://msdn.microsoft.com/en-us/library/cc212929.aspx 306 * 307 * Srv/Cli | Required | Enabled | If Required | Disabled 308 * ------------+----------+------------+-------------+----------- 309 * Required | Signed | Signed | Signed | Blocked [1] 310 * ------------+----------+------------+-------------+----------- 311 * Enabled | Signed | Signed | Not Signed | Not Signed 312 * ------------+----------+------------+-------------+----------- 313 * If Required | Signed | Not Signed | Not Signed | Not Signed 314 * ------------+----------+------------+-------------+----------- 315 * Disabled | Blocked | Not Signed | Not Signed | Not Signed 316 * 317 * [1] Like Windows 2003 and later, we don't really implement 318 * the "Disabled" setting. Instead we implement "If Required", 319 * so we always sign if the server requires signing. 320 */ 321 /* END CSTYLED */ 322 323 if (sp->sv_sm & SMB_SM_SIGS_REQUIRE) { 324 /* 325 * Server requires signing. 326 */ 327 negotiated_signing = 1; 328 } else if (sp->sv_sm & SMB_SM_SIGS) { 329 /* 330 * Server enables signing (client's option). 331 * If enabled locally, do signing. 332 */ 333 if (vcp->vc_vopt & SMBVOPT_SIGNING_ENABLED) 334 negotiated_signing = 1; 335 /* else not signing. */ 336 } else { 337 /* 338 * Server does not support signing. 339 * If we "require" it, bail now. 340 */ 341 if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) { 342 SMBERROR("Client requires signing " 343 "but server has it disabled.\n"); 344 error = EBADRPC; 345 break; 346 } 347 } 348 SMBSDEBUG("Security signatures: %d\n", 349 negotiated_signing); 350 if (negotiated_signing) { 351 SMB_VC_LOCK(vcp); 352 vcp->vc_flags |= SMBV_WILL_SIGN; 353 SMB_VC_UNLOCK(vcp); 354 } 355 356 if (sp->sv_caps & SMB_CAP_UNICODE) { 357 SMB_VC_LOCK(vcp); 358 vcp->vc_flags |= SMBV_UNICODE; 359 SMB_VC_UNLOCK(vcp); 360 unicode = 1; 361 } 362 if (!(sp->sv_caps & SMB_CAP_STATUS32)) { 363 /* 364 * They don't do NT error codes. 365 * 366 * If we send requests with 367 * SMB_FLAGS2_ERR_STATUS set in 368 * Flags2, Windows 98, at least, 369 * appears to send replies with that 370 * bit set even though it sends back 371 * DOS error codes. (They probably 372 * just use the request header as 373 * a template for the reply header, 374 * and don't bother clearing that bit.) 375 * 376 * Therefore, we clear that bit in 377 * our vc_hflags2 field. 378 */ 379 vcp->vc_hflags2 &= ~SMB_FLAGS2_ERR_STATUS; 380 } 381 if (dp->d_id == SMB_DIALECT_NTLM0_12 && 382 sp->sv_maxtx < 4096 && 383 (sp->sv_caps & SMB_CAP_NT_SMBS) == 0) { 384 SMB_VC_LOCK(vcp); 385 vcp->vc_flags |= SMBV_WIN95; 386 SMB_VC_UNLOCK(vcp); 387 SMBSDEBUG("Win95 detected\n"); 388 } 389 390 /* 391 * 3 cases here: 392 * 393 * 1) Extended security. 394 * Read bc bytes below for security blob. 395 * Note that we DON'T put the Caps flag in outtok. 396 * outtoklen = bc 397 * 398 * 2) No extended security, have challenge data and 399 * possibly a domain name (which might be zero 400 * bytes long, meaning "missing"). 401 * Copy challenge stuff to vcp->vc_ch (sblen bytes), 402 * then copy Cap flags and domain name (bc-sblen 403 * bytes) to outtok. 404 * outtoklen = bc-sblen+4, where the 4 is for the 405 * Caps flag. 406 * 407 * 3) No extended security, no challenge data, just 408 * possibly a domain name. 409 * Copy Capsflags and domain name (bc) to outtok. 410 * outtoklen = bc+4, where 4 is for the Caps flag 411 */ 412 413 /* 414 * Sanity check: make sure the challenge length 415 * isn't bigger than the byte count. 416 */ 417 if (sblen > bc) { 418 error = EBADRPC; 419 break; 420 } 421 toklen = bc; 422 423 if (sblen && sblen <= SMB_MAXCHALLENGELEN && 424 sp->sv_sm & SMB_SM_ENCRYPT) { 425 error = md_get_mem(mdp, 426 (char *)vcp->vc_challenge, 427 sblen, MB_MSYSTEM); 428 if (error) 429 break; 430 vcp->vc_chlen = sblen; 431 toklen -= sblen; 432 433 SMB_VC_LOCK(vcp); 434 vcp->vc_flags |= SMBV_ENCRYPT; 435 SMB_VC_UNLOCK(vcp); 436 } 437 438 /* 439 * For servers that don't support unicode 440 * there are 2 things we could do: 441 * 1) Pass the server Caps flags up to the 442 * user level so the logic up there will 443 * know whether the domain name is unicode 444 * (this is what I did). 445 * 2) Try to convert the non-unicode string 446 * to unicode. This doubles the length of 447 * the outtok buffer and would be guessing that 448 * the string was single-byte ascii, and that 449 * might be wrong. Why ask for trouble? 450 */ 451 452 /* Warning: NetApp may omit the GUID */ 453 454 if (!(sp->sv_caps & SMB_CAP_EXT_SECURITY)) { 455 /* 456 * No extended security. 457 * Stick domain name, if present, 458 * and caps in outtok. 459 */ 460 toklen = toklen + 4; /* space for Caps flags */ 461 vcp->vc_outtoklen = toklen; 462 vcp->vc_outtok = kmem_alloc(toklen, KM_SLEEP); 463 /* first store server capability bits */ 464 /*LINTED*/ 465 ASSERT(vcp->vc_outtok == 466 (caddr_t)(((u_int32_t *)vcp->vc_outtok))); 467 /*LINTED*/ 468 *(u_int32_t *)(vcp->vc_outtok) = sp->sv_caps; 469 470 /* 471 * Then store the domain name if present; 472 * be sure to subtract 4 from the length 473 * for the Caps flag. 474 */ 475 if (toklen > 4) { 476 error = md_get_mem(mdp, 477 vcp->vc_outtok+4, toklen-4, 478 MB_MSYSTEM); 479 } 480 } else { 481 /* 482 * Extended security. 483 * Stick the rest of the buffer in outtok. 484 */ 485 vcp->vc_outtoklen = toklen; 486 vcp->vc_outtok = kmem_alloc(toklen, KM_SLEEP); 487 error = md_get_mem(mdp, vcp->vc_outtok, toklen, 488 MB_MSYSTEM); 489 } 490 break; 491 } 492 vcp->vc_hflags2 &= ~(SMB_FLAGS2_EXT_SEC|SMB_FLAGS2_DFS| 493 SMB_FLAGS2_ERR_STATUS|SMB_FLAGS2_UNICODE); 494 if (dp->d_id > SMB_DIALECT_CORE) { 495 md_get_uint16le(mdp, &tw); 496 sp->sv_sm = (uchar_t)tw; 497 md_get_uint16le(mdp, &tw); 498 sp->sv_maxtx = tw; 499 md_get_uint16le(mdp, &sp->sv_maxmux); 500 md_get_uint16le(mdp, &sp->sv_maxvcs); 501 md_get_uint16le(mdp, &tw); /* rawmode */ 502 md_get_uint32le(mdp, &sp->sv_skey); 503 if (wc == 13) { /* >= LANMAN1 */ 504 md_get_uint16(mdp, &tw); /* time */ 505 md_get_uint16(mdp, &tw1); /* date */ 506 md_get_uint16le(mdp, (u_int16_t *)&sp->sv_tz); 507 md_get_uint16le(mdp, &swlen); 508 if (swlen > SMB_MAXCHALLENGELEN) 509 break; 510 md_get_uint16(mdp, NULL); /* mbz */ 511 if (md_get_uint16le(mdp, &bc) != 0) 512 break; 513 if (bc < swlen) 514 break; 515 if (swlen && (sp->sv_sm & SMB_SM_ENCRYPT)) { 516 error = md_get_mem(mdp, 517 (char *)vcp->vc_challenge, 518 swlen, MB_MSYSTEM); 519 if (error) 520 break; 521 vcp->vc_chlen = swlen; 522 523 SMB_VC_LOCK(vcp); 524 vcp->vc_flags |= SMBV_ENCRYPT; 525 SMB_VC_UNLOCK(vcp); 526 } 527 } 528 } else { /* an old CORE protocol */ 529 vcp->vc_hflags2 &= ~SMB_FLAGS2_KNOWS_LONG_NAMES; 530 sp->sv_maxmux = 1; 531 } 532 error = 0; 533 /*LINTED*/ 534 } while (0); 535 if (error == 0) { 536 uint32_t x; 537 538 /* 539 * Maximum outstanding requests. 540 */ 541 if (vcp->vc_maxmux < 1) 542 vcp->vc_maxmux = 1; 543 544 /* 545 * Max VCs between server and client. 546 * We only use one. 547 */ 548 vcp->vc_maxvcs = sp->sv_maxvcs; 549 if (vcp->vc_maxvcs < 1) 550 vcp->vc_maxvcs = 1; 551 552 /* 553 * Maximum transfer size. 554 * Sanity checks: 555 * 556 * Spec. says lower limit is 1024. OK. 557 * 558 * Let's be conservative about an upper limit here. 559 * Win2k uses 16644 (and others) so 32k should be a 560 * reasonable sanity limit for this value. 561 * 562 * Note that this limit does NOT affect READX/WRITEX 563 * with CAP_LARGE_xxx, which we nearly always use. 564 */ 565 vcp->vc_txmax = sp->sv_maxtx; 566 if (vcp->vc_txmax < 1024) 567 vcp->vc_txmax = 1024; 568 if (vcp->vc_txmax > 0x8000) 569 vcp->vc_txmax = 0x8000; 570 571 /* 572 * Max read/write sizes, WITHOUT overhead. 573 * This is just the payload size, so we must 574 * leave room for the SMB headers, etc. 575 * This is just the vc_txmax value, but 576 * reduced and rounded down. Tricky bit: 577 * 578 * Servers typically give us a value that's 579 * some nice "round" number, i.e 0x4000 plus 580 * some overhead, i.e. Win2k: 16644==0x4104 581 * Subtract for the SMB header (32) and the 582 * SMB command word and byte vectors (34?), 583 * then round down to a 512 byte multiple. 584 */ 585 x = (vcp->vc_txmax - 68) & 0xFE00; 586 vcp->vc_rxmax = x; 587 vcp->vc_wxmax = x; 588 589 SMBSDEBUG("TZ = %d\n", sp->sv_tz); 590 SMBSDEBUG("CAPS = %x\n", sp->sv_caps); 591 592 SMBSDEBUG("maxmux = %d\n", vcp->vc_maxmux); 593 SMBSDEBUG("maxvcs = %d\n", vcp->vc_maxvcs); 594 SMBSDEBUG("txmax = %d\n", vcp->vc_txmax); 595 SMBSDEBUG("rxmax = %d\n", vcp->vc_rxmax); 596 SMBSDEBUG("wxmax = %d\n", vcp->vc_wxmax); 597 } 598 599 /* 600 * If the server supports Unicode, set up to use Unicode 601 * when talking to them. Othewise, use code page 437. 602 */ 603 if (unicode) 604 servercs = "ucs-2"; 605 else { 606 /* 607 * todo: if we can't determine the server's encoding, we 608 * need to try a best-guess here. 609 */ 610 servercs = "cp437"; 611 } 612 #if defined(NOICONVSUPPORT) || defined(lint) 613 /* 614 * REVISIT 615 */ 616 error = iconv_open(servercs, "utf-8", &servercshandle); 617 if (error != 0) 618 goto bad; 619 error = iconv_open("utf-8", servercs, &localcshandle); 620 if (error != 0) { 621 iconv_close(servercshandle); 622 goto bad; 623 } 624 if (vcp->vc_toserver) 625 iconv_close(vcp->vc_toserver); 626 if (vcp->vc_tolocal) 627 iconv_close(vcp->vc_tolocal); 628 vcp->vc_toserver = servercshandle; 629 vcp->vc_tolocal = localcshandle; 630 #endif 631 if (unicode) 632 vcp->vc_hflags2 |= SMB_FLAGS2_UNICODE; 633 bad: 634 smb_rq_done(rqp); 635 return (error); 636 } 637 638 static void 639 get_ascii_password(struct smb_vc *vcp, int upper, char *pbuf) 640 { 641 const char *pw = smb_vc_getpass(vcp); 642 if (upper) 643 smb_toupper(pw, pbuf, SMB_MAXPASSWORDLEN); 644 else 645 strncpy(pbuf, pw, SMB_MAXPASSWORDLEN); 646 pbuf[SMB_MAXPASSWORDLEN] = '\0'; 647 } 648 649 #ifdef APPLE 650 static void 651 get_unicode_password(struct smb_vc *vcp, char *pbuf) 652 { 653 strncpy(pbuf, smb_vc_getpass(vcp), SMB_MAXPASSWORDLEN); 654 pbuf[SMB_MAXPASSWORDLEN] = '\0'; 655 } 656 #endif 657 658 /*ARGSUSED*/ 659 static uchar_t * 660 add_name_to_blob(uchar_t *blobnames, struct smb_vc *vcp, const uchar_t *name, 661 size_t namelen, int nametype, int uppercase) 662 { 663 struct ntlmv2_namehdr namehdr; 664 char *namebuf; 665 u_int16_t *uninamebuf; 666 size_t uninamelen; 667 668 if (name != NULL) { 669 uninamebuf = kmem_alloc(2 * namelen, KM_SLEEP); 670 if (uppercase) { 671 namebuf = kmem_alloc(namelen + 1, KM_SLEEP); 672 smb_toupper((const char *)name, namebuf, namelen); 673 namebuf[namelen] = '\0'; 674 uninamelen = smb_strtouni(uninamebuf, namebuf, namelen, 675 UCONV_IGNORE_NULL); 676 kmem_free(namebuf, namelen + 1); 677 } else { 678 uninamelen = smb_strtouni(uninamebuf, (char *)name, 679 namelen, UCONV_IGNORE_NULL); 680 } 681 } else { 682 uninamelen = 0; 683 uninamebuf = NULL; 684 } 685 namehdr.type = htoles(nametype); 686 namehdr.len = htoles(uninamelen); 687 bcopy(&namehdr, blobnames, sizeof (namehdr)); 688 blobnames += sizeof (namehdr); 689 if (uninamebuf != NULL) { 690 bcopy(uninamebuf, blobnames, uninamelen); 691 blobnames += uninamelen; 692 kmem_free(uninamebuf, namelen * 2); 693 } 694 return (blobnames); 695 } 696 697 static uchar_t * 698 make_ntlmv2_blob(struct smb_vc *vcp, u_int64_t client_nonce, 699 size_t *bloblen, size_t *blob_allocsz) 700 { 701 uchar_t *blob; 702 size_t blobsize; 703 size_t domainlen, srvlen; 704 struct ntlmv2_blobhdr *blobhdr; 705 struct timespec now; 706 u_int64_t timestamp; 707 uchar_t *blobnames; 708 ptrdiff_t diff; 709 710 /* 711 * XXX - the information at 712 * 713 * http://davenport.sourceforge.net/ntlm.html#theNtlmv2Response 714 * 715 * says that the "target information" comes from the Type 2 message, 716 * but, as we're not doing NTLMSSP, we don't have that. 717 * 718 * Should we use the names from the NegProt response? Can we trust 719 * the NegProt response? (I've seen captures where the primary 720 * domain name has an extra byte in front of it.) 721 * 722 * For now, we don't trust it - we use vcp->vc_domain and 723 * vcp->vc_srvname, instead. We upper-case them and convert 724 * them to Unicode, as that's what's supposed to be in the blob. 725 */ 726 domainlen = strlen(vcp->vc_domain); 727 srvlen = strlen(vcp->vc_srvname); 728 blobsize = sizeof (struct ntlmv2_blobhdr) 729 + 3*sizeof (struct ntlmv2_namehdr) + 4 + 2*domainlen + 2*srvlen; 730 *blob_allocsz = blobsize; 731 blobhdr = kmem_zalloc(blobsize, KM_SLEEP); 732 blob = (uchar_t *)blobhdr; 733 blobhdr->header = htolel(0x00000101); 734 gethrestime(&now); 735 smb_time_local2NT(&now, 0, ×tamp); 736 blobhdr->timestamp = htoleq(timestamp); 737 blobhdr->client_nonce = client_nonce; 738 blobnames = blob + sizeof (struct ntlmv2_blobhdr); 739 blobnames = add_name_to_blob(blobnames, vcp, (uchar_t *)vcp->vc_domain, 740 domainlen, NAMETYPE_DOMAIN_NB, 1); 741 blobnames = add_name_to_blob(blobnames, vcp, (uchar_t *)vcp->vc_srvname, 742 srvlen, NAMETYPE_MACHINE_NB, 1); 743 blobnames = add_name_to_blob(blobnames, vcp, NULL, 0, NAMETYPE_EOL, 0); 744 diff = (intptr_t)blobnames - (intptr_t)blob; 745 ASSERT(diff == (ptrdiff_t)((size_t)diff)); 746 *bloblen = (size_t)diff; 747 return (blob); 748 } 749 750 /* 751 * When not doing Kerberos, we can try, in order: 752 * 753 * NTLMv2 754 * NTLM (and maybe LM) 755 * 756 * if the server supports encrypted passwords, or 757 * 758 * plain-text with the ASCII password not upper-cased 759 * plain-text with the ASCII password upper-cased 760 * 761 * if it doesn't. 762 */ 763 typedef enum { 764 ClearUC, /* Cleartext p/w, upper case */ 765 ClearMC, /* Cleartext p/w, mixed case */ 766 NTLMv1, 767 NTLMv2, 768 ExtSec, /* Extended Security (Kerberos) */ 769 NullSes /* Null session (keep last) */ 770 } authtype_t; 771 772 int 773 smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred) 774 { 775 struct smb_rq *rqp; 776 struct mbchain *mbp; 777 struct mdchain *mdp; 778 u_int8_t wc; 779 int minauth; 780 smb_uniptr unipp = NULL, ntencpass = NULL; 781 char *pp = NULL, *up = NULL, *ucup = NULL; 782 char *ucdp = vcp->vc_domain; /* already upper case */ 783 char *encpass = NULL; 784 int error = 0; 785 size_t plen = 0, plen_alloc = 0; 786 size_t uniplen = 0, uniplen_alloc = 0; 787 size_t ucup_sl = 0; 788 authtype_t authtype; 789 size_t ntlmv2_bloblen, ntlmv2_blob_allocsz; 790 uchar_t *ntlmv2_blob; 791 u_int64_t client_nonce; 792 u_int32_t caps; 793 u_int16_t bl; /* BLOB length */ 794 u_int16_t bc; /* byte count */ 795 u_int16_t action; 796 u_int16_t rpflags2; 797 int declinedguest = 0; 798 uchar_t v2hash[16]; 799 static const char NativeOS[] = "Solaris"; 800 static const char LanMan[] = "NETSMB"; 801 /* 802 * Most of the "capability" bits we offer should be copied 803 * from those offered by the server, with a mask applied. 804 * This is the mask of capabilies copied from the server. 805 * Some others get special handling below. 806 */ 807 static const uint32_t caps_mask = 808 SMB_CAP_UNICODE | 809 SMB_CAP_LARGE_FILES | 810 SMB_CAP_NT_SMBS | 811 SMB_CAP_STATUS32; 812 813 caps = vcp->vc_sopt.sv_caps & caps_mask; 814 minauth = vcp->vc_vopt & SMBVOPT_MINAUTH; 815 816 /* 817 * This function tries authentication types in a 818 * sequence going stronger to weaker, until it 819 * succeeds or runs into "minauth" and fails. 820 * 821 * Extended security is a special case because 822 * fall-back requires a return to user-level and 823 * a new connection, new SMB negotiate, etc. 824 * Null session is also special - no fall-back. 825 * 826 * Otherwise if the server supports encryption, 827 * try NTLMv2, then NTLM, etc. 828 */ 829 if (vcp->vc_intok) 830 authtype = ExtSec; 831 else if (vcp->vc_username[0] == '\0') 832 authtype = NullSes; 833 else if ((vcp->vc_sopt.sv_sm & SMB_SM_USER) == 0) { 834 /* Share-level security. */ 835 authtype = NullSes; 836 } else { 837 /* Have SMB_SM_USER. Encryption? */ 838 if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) { 839 if (nsmb_enable_ntlmv2) 840 authtype = NTLMv2; 841 else 842 authtype = NTLMv1; 843 } else { 844 /* 845 * This is normally disallowed 846 * by the minauth check below. 847 */ 848 authtype = ClearMC; 849 } 850 } 851 852 /* 853 * If server does not support encryption, 854 * disable unicode too. (Spec. for this?) 855 */ 856 if ((vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) == 0) { 857 if (vcp->vc_flags & SMBV_UNICODE) { 858 vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE; 859 vcp->vc_toserver = 0; 860 } 861 } 862 863 again: 864 SMBSDEBUG("authtype = %d\n", authtype); 865 866 /* 867 * Now disallow auth. types that fall below 868 * the minimum strength configured. 869 * We hold no kmem here. 870 */ 871 switch (minauth) { 872 873 case SMBVOPT_MINAUTH_NONE: 874 break; 875 876 case SMBVOPT_MINAUTH_LM: 877 case SMBVOPT_MINAUTH_NTLM: 878 if (authtype < NTLMv1) { 879 error = EAUTH; 880 goto ssn_exit; 881 } 882 break; 883 884 case SMBVOPT_MINAUTH_NTLMV2: 885 if (authtype < NTLMv2) { 886 error = EAUTH; 887 goto ssn_exit; 888 } 889 break; 890 891 case SMBVOPT_MINAUTH_KERBEROS: 892 if (authtype < ExtSec) { 893 error = EAUTH; 894 goto ssn_exit; 895 } 896 break; 897 898 default: 899 SMBSDEBUG("bad minauth 0x%x\n", minauth); 900 error = EAUTH; 901 goto ssn_exit; 902 } 903 904 /* 905 * See comment in smb_iod_sendrq() 906 * about vc_smbuid initialization. 907 */ 908 vcp->vc_smbuid = SMB_UID_UNKNOWN; 909 910 /* 911 * Within this switch, we may allocate either or both: 912 * encpass, ntencpass (len: plen_alloc, uniplen_alloc) 913 * and will free these below (see the label "bad") 914 */ 915 switch (authtype) { 916 917 case ExtSec: 918 /* 919 * With extended security, the whole blob is 920 * passed in from user-level (vc_intok) 921 */ 922 ASSERT(vcp->vc_intok != NULL); 923 caps |= SMB_CAP_EXT_SECURITY; 924 /* XXX Need Session Key */ 925 if (vcp->vc_intoklen > 65536 || 926 !(vcp->vc_hflags2 & SMB_FLAGS2_EXT_SEC) || 927 SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) { 928 /* We hold no kmem here. */ 929 error = EINVAL; 930 goto ssn_exit; 931 } 932 vcp->vc_smbuid = 0; 933 break; 934 935 case NullSes: 936 pp = ""; 937 plen = 1; 938 unipp = &smb_unieol; 939 uniplen = sizeof (smb_unieol); 940 break; 941 942 case NTLMv2: 943 /* 944 * Compute the LMv2 and NTLMv2 responses, 945 * derived from the challenge, the user name, 946 * the domain/workgroup into which we're 947 * logging, and the Unicode password. 948 */ 949 950 /* 951 * Construct the client nonce by getting 952 * a bunch of random data. 953 */ 954 (void) random_get_pseudo_bytes((void *) 955 &client_nonce, sizeof (client_nonce)); 956 957 /* 958 * Convert the user name to upper-case, as 959 * that's what's used when computing LMv2 960 * and NTLMv2 responses. 961 */ 962 ucup_sl = strlen(vcp->vc_username); 963 ucup = kmem_alloc(ucup_sl + 1, KM_SLEEP); 964 smb_toupper((const char *)vcp->vc_username, 965 ucup, ucup_sl); 966 ucup[ucup_sl] = '\0'; 967 968 /* 969 * Compute the NTLMv2 hash, which is 970 * derived from the NTLMv1 hash and 971 * the upper-case user + domain. 972 */ 973 smb_ntlmv2hash(vcp->vc_nthash, 974 ucup, ucdp, v2hash); 975 976 /* 977 * Compute the LMv2 response, derived from 978 * the v2hash, the server challenge, and 979 * the client nonce (random bits). 980 * Note: kmem_alloc encpass (plen) 981 */ 982 smb_ntlmv2response(v2hash, 983 vcp->vc_challenge, 984 (uchar_t *)&client_nonce, 8, 985 (uchar_t **)&encpass, &plen); 986 plen_alloc = plen; 987 pp = encpass; 988 989 /* 990 * Construct the blob. 991 * Note: kmem_alloc ntlmv2_blob 992 */ 993 ntlmv2_blob = make_ntlmv2_blob(vcp, 994 client_nonce, &ntlmv2_bloblen, 995 &ntlmv2_blob_allocsz); 996 997 /* 998 * Compute the NTLMv2 response, derived 999 * from the server challenge, the 1000 * user name, the domain/workgroup 1001 * into which we're logging, the 1002 * blob, and the v2 hash. 1003 * Note: kmem_alloc ntencpass (uniplen) 1004 */ 1005 smb_ntlmv2response(v2hash, 1006 vcp->vc_challenge, 1007 ntlmv2_blob, ntlmv2_bloblen, 1008 (uchar_t **)&ntencpass, &uniplen); 1009 uniplen_alloc = uniplen; 1010 unipp = ntencpass; 1011 1012 /* 1013 * If we negotiated signing, compute the MAC key 1014 * and start signing messages, but only on the 1015 * first non-null session login. 1016 */ 1017 if ((vcp->vc_flags & SMBV_WILL_SIGN) && 1018 !(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)) { 1019 vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE; 1020 smb_calcv2mackey(vcp, v2hash, 1021 (uchar_t *)ntencpass, uniplen); 1022 } 1023 kmem_free(ucup, ucup_sl + 1); 1024 kmem_free(ntlmv2_blob, ntlmv2_blob_allocsz); 1025 break; 1026 1027 case NTLMv1: 1028 /* 1029 * Compute the LM response, derived 1030 * from the challenge and the ASCII 1031 * password. (If minauth allows it.) 1032 */ 1033 plen_alloc = plen = 24; 1034 encpass = kmem_zalloc(plen, KM_SLEEP); 1035 if (minauth < SMBVOPT_MINAUTH_NTLM) { 1036 smb_lmresponse(vcp->vc_lmhash, 1037 vcp->vc_challenge, 1038 (uchar_t *)encpass); 1039 } 1040 pp = encpass; 1041 1042 /* 1043 * Compute the NTLM response, derived from 1044 * the challenge and the NT hash. 1045 */ 1046 uniplen_alloc = uniplen = 24; 1047 ntencpass = kmem_alloc(uniplen, KM_SLEEP); 1048 smb_lmresponse(vcp->vc_nthash, 1049 vcp->vc_challenge, 1050 (uchar_t *)ntencpass); 1051 unipp = ntencpass; 1052 1053 /* 1054 * If we negotiated signing, compute the MAC key 1055 * and start signing messages, but only on the 1056 * first non-null session login. 1057 */ 1058 if ((vcp->vc_flags & SMBV_WILL_SIGN) && 1059 !(vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)) { 1060 vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE; 1061 smb_calcmackey(vcp, vcp->vc_nthash, 1062 (uchar_t *)ntencpass, uniplen); 1063 } 1064 break; 1065 1066 case ClearMC: 1067 case ClearUC: 1068 /* 1069 * We try w/o uppercasing first so Samba mixed case 1070 * passwords work. If that fails, we come back and 1071 * try uppercasing to satisfy OS/2 and Windows for 1072 * Workgroups. 1073 */ 1074 plen_alloc = plen = SMB_MAXPASSWORDLEN + 1; 1075 encpass = kmem_zalloc(plen, KM_SLEEP); 1076 get_ascii_password(vcp, (authtype == ClearUC), encpass); 1077 plen = strlen(encpass) + 1; 1078 pp = encpass; 1079 uniplen_alloc = uniplen = plen * 2; 1080 ntencpass = kmem_alloc(uniplen, KM_SLEEP); 1081 (void) smb_strtouni(ntencpass, smb_vc_getpass(vcp), 0, 0); 1082 plen--; 1083 /* 1084 * The uniplen is zeroed because Samba cannot deal 1085 * with this 2nd cleartext password. This Samba 1086 * "bug" is actually a workaround for problems in 1087 * Microsoft clients. 1088 */ 1089 uniplen = 0; /* -= 2 */ 1090 unipp = ntencpass; 1091 break; 1092 1093 default: 1094 ASSERT(0); 1095 error = EAUTH; 1096 goto ssn_exit; 1097 1098 } /* switch authtype */ 1099 1100 1101 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX, 1102 scred, &rqp); 1103 if (error) 1104 goto bad; 1105 1106 /* 1107 * Build the request. 1108 */ 1109 smb_rq_wstart(rqp); 1110 mbp = &rqp->sr_rq; 1111 up = vcp->vc_username; 1112 /* 1113 * If userid is null we are attempting anonymous browse login 1114 * so passwords must be zero length. 1115 */ 1116 if (*up == '\0') { 1117 plen = uniplen = 0; 1118 } 1119 mb_put_uint8(mbp, 0xff); 1120 mb_put_uint8(mbp, 0); 1121 mb_put_uint16le(mbp, 0); 1122 mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxtx); 1123 mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxmux); 1124 mb_put_uint16le(mbp, vcp->vc_number); 1125 mb_put_uint32le(mbp, vcp->vc_sopt.sv_skey); 1126 if ((SMB_DIALECT(vcp)) < SMB_DIALECT_NTLM0_12) { 1127 mb_put_uint16le(mbp, plen); 1128 mb_put_uint32le(mbp, 0); 1129 smb_rq_wend(rqp); 1130 smb_rq_bstart(rqp); 1131 mb_put_mem(mbp, pp, plen, MB_MSYSTEM); 1132 smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* user */ 1133 smb_put_dstring(mbp, vcp, ucdp, SMB_CS_NONE); /* domain */ 1134 } else { 1135 if (vcp->vc_intok) { 1136 mb_put_uint16le(mbp, vcp->vc_intoklen); 1137 mb_put_uint32le(mbp, 0); /* reserved */ 1138 mb_put_uint32le(mbp, caps); /* my caps */ 1139 smb_rq_wend(rqp); 1140 smb_rq_bstart(rqp); 1141 mb_put_mem(mbp, vcp->vc_intok, vcp->vc_intoklen, 1142 MB_MSYSTEM); /* security blob */ 1143 } else { 1144 mb_put_uint16le(mbp, plen); 1145 mb_put_uint16le(mbp, uniplen); 1146 mb_put_uint32le(mbp, 0); /* reserved */ 1147 mb_put_uint32le(mbp, caps); /* my caps */ 1148 smb_rq_wend(rqp); 1149 smb_rq_bstart(rqp); 1150 mb_put_mem(mbp, pp, plen, MB_MSYSTEM); /* password */ 1151 mb_put_mem(mbp, (caddr_t)unipp, uniplen, MB_MSYSTEM); 1152 smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* user */ 1153 smb_put_dstring(mbp, vcp, ucdp, SMB_CS_NONE); /* dom */ 1154 } 1155 } 1156 smb_put_dstring(mbp, vcp, NativeOS, SMB_CS_NONE); /* OS */ 1157 smb_put_dstring(mbp, vcp, LanMan, SMB_CS_NONE); /* LAN Mgr */ 1158 smb_rq_bend(rqp); 1159 1160 /* 1161 * This request should not wait for 1162 * connection state changes, etc. 1163 */ 1164 rqp->sr_flags |= SMBR_INTERNAL; 1165 error = smb_rq_simple_timed(rqp, SMBSSNSETUPTIMO); 1166 SMBSDEBUG("%d\n", error); 1167 if (error) { 1168 if (rqp->sr_errclass == ERRDOS && 1169 rqp->sr_serror == ERRnoaccess) 1170 error = EAUTH; 1171 if (!(rqp->sr_errclass == ERRDOS && 1172 rqp->sr_serror == ERRmoredata)) 1173 goto bad; 1174 } 1175 1176 /* 1177 * Parse the reply 1178 */ 1179 rpflags2 = rqp->sr_rpflags2; 1180 vcp->vc_smbuid = rqp->sr_rpuid; 1181 smb_rq_getreply(rqp, &mdp); 1182 error = md_get_uint8(mdp, &wc); 1183 if (error) 1184 goto bad; 1185 error = EBADRPC; 1186 if (vcp->vc_intok) { 1187 if (wc != 4) 1188 goto bad; 1189 } else if (wc != 3) 1190 goto bad; 1191 md_get_uint8(mdp, NULL); /* secondary cmd */ 1192 md_get_uint8(mdp, NULL); /* mbz */ 1193 md_get_uint16le(mdp, NULL); /* andxoffset */ 1194 md_get_uint16le(mdp, &action); /* action */ 1195 if (vcp->vc_intok) 1196 md_get_uint16le(mdp, &bl); /* ext security */ 1197 md_get_uint16le(mdp, &bc); /* byte count */ 1198 if (vcp->vc_intok) { 1199 vcp->vc_outtoklen = bl; 1200 vcp->vc_outtok = kmem_alloc(bl, KM_SLEEP); 1201 error = md_get_mem(mdp, vcp->vc_outtok, bl, MB_MSYSTEM); 1202 if (error) 1203 goto bad; 1204 } 1205 1206 /* 1207 * Server OS, LANMGR, & Domain follow here. 1208 * XXX: Should store these strings (later). 1209 * 1210 * Windows systems do not suport CAP_LARGE_... 1211 * when signing is enabled, so adjust sv_caps. 1212 * Match first 8 characters of server's OS 1213 * with the UCS-2LE string: "Windows " 1214 */ 1215 if (bc > 16) { 1216 static const char WindowsU[16] = 1217 "W\0i\0n\0d\0o\0w\0s\0 "; 1218 char osbuf[16]; 1219 1220 /* align(2) */ 1221 if (((uintptr_t)mdp->md_pos) & 1) 1222 md_get_uint8(mdp, NULL); 1223 1224 bzero(osbuf, sizeof (osbuf)); 1225 md_get_mem(mdp, osbuf, sizeof (osbuf), MB_MSYSTEM); 1226 if (0 == bcmp(WindowsU, osbuf, sizeof (osbuf))) { 1227 SMBSDEBUG("Server is Windows\n"); 1228 if (vcp->vc_flags & SMBV_WILL_SIGN) { 1229 SMBSDEBUG("disable CAP_LARGE_(r/w)\n"); 1230 vcp->vc_sopt.sv_caps &= 1231 ~(SMB_CAP_LARGE_READX 1232 | SMB_CAP_LARGE_WRITEX); 1233 } 1234 } 1235 } 1236 1237 /* success! */ 1238 error = 0; 1239 1240 bad: 1241 1242 /* 1243 * When authentication fails and we're (possibly) doing 1244 * fall-back to another method, we have to reset things. 1245 */ 1246 if (error && vcp->vc_mackey) { 1247 vcp->vc_hflags2 &= ~SMB_FLAGS2_SECURITY_SIGNATURE; 1248 kmem_free(vcp->vc_mackey, vcp->vc_mackeylen); 1249 vcp->vc_mackey = NULL; 1250 vcp->vc_mackeylen = 0; 1251 vcp->vc_seqno = 0; 1252 } 1253 1254 if (rqp) { 1255 smb_rq_done(rqp); 1256 rqp = NULL; 1257 } 1258 if (encpass) { 1259 kmem_free(encpass, plen_alloc); 1260 encpass = NULL; 1261 } 1262 if (ntencpass) { 1263 kmem_free(ntencpass, uniplen_alloc); 1264 ntencpass = NULL; 1265 } 1266 1267 /* 1268 * Shall we try again with another auth type? 1269 * Note: We hold no kmem here. 1270 */ 1271 switch (authtype) { 1272 1273 case NullSes: 1274 case ExtSec: 1275 /* Error or not, we're done. (no fallback) */ 1276 break; 1277 1278 case NTLMv2: 1279 /* 1280 * We're doing user-level authentication (so we are actually 1281 * sending authentication stuff over the wire), and we're 1282 * not doing extended security, and the stuff we tried 1283 * failed (or we we're trying to login a real user but 1284 * got granted guest access instead.) 1285 * 1286 * See radar 4134676. This check works around the way a 1287 * certain old server grants limited Guest access when we 1288 * try NTLMv2, but works fine with NTLM. The fingerprint 1289 * we are looking for is DOS error codes and no-Unicode. 1290 * Note XP grants Guest access but uses Unicode and 1291 * NT error codes. 1292 */ 1293 if (error == 0 && (action & SMB_ACT_GUEST) && 1294 !(rpflags2 & SMB_FLAGS2_ERR_STATUS) && 1295 !(rpflags2 & SMB_FLAGS2_UNICODE)) { 1296 /* force fallback */ 1297 declinedguest = 1; 1298 error = EAUTH; 1299 } 1300 /* FALLTHROUGH */ 1301 case NTLMv1: 1302 case ClearMC: 1303 if (error) { 1304 authtype = authtype - 1; 1305 goto again; 1306 } 1307 break; 1308 1309 case ClearUC: 1310 default: 1311 /* no more fallbacks */ 1312 break; 1313 } 1314 1315 ssn_exit: 1316 if (error && declinedguest) 1317 SMBERROR("we declined ntlmv2 guest access. errno will be %d\n", 1318 error); 1319 1320 return (error); 1321 } 1322 1323 int 1324 smb_smb_ssnclose(struct smb_vc *vcp, struct smb_cred *scred) 1325 { 1326 struct smb_rq *rqp; 1327 struct mbchain *mbp; 1328 int error; 1329 1330 if (vcp->vc_smbuid == SMB_UID_UNKNOWN) 1331 return (0); 1332 1333 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp); 1334 if (error) 1335 return (error); 1336 mbp = &rqp->sr_rq; 1337 smb_rq_wstart(rqp); 1338 mb_put_uint8(mbp, 0xff); 1339 mb_put_uint8(mbp, 0); 1340 mb_put_uint16le(mbp, 0); 1341 smb_rq_wend(rqp); 1342 smb_rq_bstart(rqp); 1343 smb_rq_bend(rqp); 1344 /* 1345 * Run this with a relatively short timeout. 1346 * We don't really care about the result, 1347 * as we're just trying to play nice and 1348 * "say goodbye" before we hangup. 1349 * XXX: Add SMBLOGOFFTIMO somewhere? 1350 */ 1351 error = smb_rq_simple_timed(rqp, 5); 1352 SMBSDEBUG("%d\n", error); 1353 smb_rq_done(rqp); 1354 return (error); 1355 } 1356 1357 static char smb_any_share[] = "?????"; 1358 1359 static char * 1360 smb_share_typename(int stype) 1361 { 1362 char *pp; 1363 1364 switch (stype) { 1365 case STYPE_DISKTREE: 1366 pp = "A:"; 1367 break; 1368 case STYPE_PRINTQ: 1369 pp = smb_any_share; /* can't use LPT: here... */ 1370 break; 1371 case STYPE_DEVICE: 1372 pp = "COMM"; 1373 break; 1374 case STYPE_IPC: 1375 pp = "IPC"; 1376 break; 1377 default: 1378 pp = smb_any_share; 1379 break; 1380 } 1381 return (pp); 1382 } 1383 1384 int 1385 smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred) 1386 { 1387 struct smb_vc *vcp; 1388 struct smb_rq rq, *rqp = &rq; 1389 struct mbchain *mbp; 1390 char *pp, *pbuf, *encpass; 1391 const char *pw; 1392 uchar_t hash[SMB_PWH_MAX]; 1393 int error, plen, caseopt; 1394 int upper = 0; 1395 1396 again: 1397 vcp = SSTOVC(ssp); 1398 1399 /* 1400 * Make this a "VC-level" request, so it will have 1401 * rqp->sr_share == NULL, and smb_iod_sendrq() 1402 * will send it with TID = SMB_TID_UNKNOWN 1403 * 1404 * This also serves to bypass the wait for 1405 * share state changes, which this call is 1406 * trying to carry out. 1407 * 1408 * No longer need to set ssp->ss_tid 1409 * here, but it's harmless enough. 1410 */ 1411 ssp->ss_tid = SMB_TID_UNKNOWN; 1412 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_CONNECT_ANDX, 1413 scred, &rqp); 1414 if (error) 1415 return (error); 1416 caseopt = SMB_CS_NONE; 1417 if (vcp->vc_sopt.sv_sm & SMB_SM_USER) { 1418 plen = 1; 1419 pp = ""; 1420 pbuf = NULL; 1421 encpass = NULL; 1422 } else { 1423 pbuf = kmem_alloc(SMB_MAXPASSWORDLEN + 1, KM_SLEEP); 1424 encpass = kmem_alloc(24, KM_SLEEP); 1425 pw = smb_share_getpass(ssp); 1426 /* 1427 * We try w/o uppercasing first so Samba mixed case 1428 * passwords work. If that fails we come back and try 1429 * uppercasing to satisfy OS/2 and Windows for Workgroups. 1430 */ 1431 if (upper++) { 1432 smb_toupper(pw, pbuf, SMB_MAXPASSWORDLEN); 1433 smb_oldlm_hash(pw, hash); 1434 } else { 1435 strncpy(pbuf, pw, SMB_MAXPASSWORDLEN); 1436 smb_ntlmv1hash(pw, hash); 1437 } 1438 pbuf[SMB_MAXPASSWORDLEN] = '\0'; 1439 1440 #ifdef NOICONVSUPPORT 1441 /* 1442 * We need to convert here to the server codeset. 1443 * Initially we will send the same stuff and see what happens 1444 * witout the conversion. REVISIT. 1445 */ 1446 iconv_convstr(vcp->vc_toserver, pbuf, pbuf, SMB_MAXPASSWORDLEN); 1447 #endif 1448 if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) { 1449 plen = 24; 1450 smb_lmresponse(hash, 1451 vcp->vc_challenge, 1452 (uchar_t *)encpass); 1453 pp = encpass; 1454 } else { 1455 plen = strlen(pbuf) + 1; 1456 pp = pbuf; 1457 } 1458 } 1459 mbp = &rqp->sr_rq; 1460 smb_rq_wstart(rqp); 1461 mb_put_uint8(mbp, 0xff); 1462 mb_put_uint8(mbp, 0); 1463 mb_put_uint16le(mbp, 0); 1464 mb_put_uint16le(mbp, 0); /* Flags */ 1465 mb_put_uint16le(mbp, plen); 1466 smb_rq_wend(rqp); 1467 smb_rq_bstart(rqp); 1468 error = mb_put_mem(mbp, pp, plen, MB_MSYSTEM); 1469 if (error) { 1470 SMBSDEBUG("error %d from mb_put_mem for pp\n", error); 1471 goto bad; 1472 } 1473 smb_put_dmem(mbp, vcp, "\\\\", 2, caseopt, NULL); 1474 pp = vcp->vc_srvname; 1475 error = smb_put_dmem(mbp, vcp, pp, strlen(pp), caseopt, NULL); 1476 if (error) { 1477 SMBSDEBUG("error %d from smb_put_dmem for srvname\n", error); 1478 goto bad; 1479 } 1480 smb_put_dmem(mbp, vcp, "\\", 1, caseopt, NULL); 1481 pp = ssp->ss_name; 1482 error = smb_put_dstring(mbp, vcp, pp, caseopt); 1483 if (error) { 1484 SMBSDEBUG("error %d from smb_put_dstring for ss_name\n", error); 1485 goto bad; 1486 } 1487 /* The type name is always ASCII */ 1488 pp = smb_share_typename(ssp->ss_type); 1489 error = mb_put_mem(mbp, pp, strlen(pp) + 1, MB_MSYSTEM); 1490 if (error) { 1491 SMBSDEBUG("error %d from mb_put_mem for ss_type\n", error); 1492 goto bad; 1493 } 1494 smb_rq_bend(rqp); 1495 /* 1496 * Don't want to risk missing a successful 1497 * tree connect response. 1498 */ 1499 rqp->sr_flags |= SMBR_NOINTR_RECV; 1500 error = smb_rq_simple(rqp); 1501 SMBSDEBUG("%d\n", error); 1502 if (error) 1503 goto bad; 1504 1505 /* Success! */ 1506 SMB_SS_LOCK(ssp); 1507 ssp->ss_tid = rqp->sr_rptid; 1508 ssp->ss_vcgenid = vcp->vc_genid; 1509 ssp->ss_flags |= SMBS_CONNECTED; 1510 SMB_SS_UNLOCK(ssp); 1511 1512 bad: 1513 if (encpass) 1514 kmem_free(encpass, 24); 1515 if (pbuf) 1516 kmem_free(pbuf, SMB_MAXPASSWORDLEN + 1); 1517 smb_rq_done(rqp); 1518 if (error && upper == 1) 1519 goto again; 1520 return (error); 1521 } 1522 1523 int 1524 smb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred) 1525 { 1526 struct smb_vc *vcp; 1527 struct smb_rq *rqp; 1528 struct mbchain *mbp; 1529 int error; 1530 1531 if (ssp->ss_tid == SMB_TID_UNKNOWN) 1532 return (0); 1533 1534 /* 1535 * Build this as a "VC-level" request, so it will 1536 * avoid testing the _GONE flag on the share, 1537 * which has already been set at this point. 1538 * Add the share pointer "by hand" below, so 1539 * smb_iod_sendrq will plug in the TID. 1540 */ 1541 vcp = SSTOVC(ssp); 1542 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_DISCONNECT, scred, &rqp); 1543 if (error) 1544 return (error); 1545 rqp->sr_share = ssp; /* by hand */ 1546 mbp = &rqp->sr_rq; 1547 #ifdef lint 1548 mbp = mbp; 1549 #endif 1550 smb_rq_wstart(rqp); 1551 smb_rq_wend(rqp); 1552 smb_rq_bstart(rqp); 1553 smb_rq_bend(rqp); 1554 1555 /* 1556 * Run this with a relatively short timeout. (5 sec.) 1557 * We don't really care about the result here, but we 1558 * do need to make sure we send this out, or we could 1559 * "leak" active tree IDs on interrupt or timeout. 1560 * The NOINTR_SEND flag makes this request immune to 1561 * interrupt or timeout until the send is done. 1562 */ 1563 rqp->sr_flags |= SMBR_NOINTR_SEND; 1564 error = smb_rq_simple_timed(rqp, 5); 1565 SMBSDEBUG("%d\n", error); 1566 smb_rq_done(rqp); 1567 ssp->ss_tid = SMB_TID_UNKNOWN; 1568 return (error); 1569 } 1570 1571 /* 1572 * Common function for read/write with UIO. 1573 * Called by netsmb smb_usr_rw, 1574 * smbfs_readvnode, smbfs_writevnode 1575 */ 1576 int 1577 smb_rwuio(struct smb_share *ssp, uint16_t fid, uio_rw_t rw, 1578 uio_t *uiop, smb_cred_t *scred, int timo) 1579 { 1580 struct smb_vc *vcp = SSTOVC(ssp); 1581 ssize_t save_resid; 1582 uint32_t len, rlen, maxlen; 1583 int error = 0; 1584 int (*iofun)(struct smb_share *, uint16_t, uint32_t *, 1585 uio_t *, smb_cred_t *, int); 1586 1587 /* 1588 * Determine which function to use, 1589 * and the transfer size per call. 1590 */ 1591 if (SMB_DIALECT(vcp) >= SMB_DIALECT_NTLM0_12) { 1592 /* 1593 * Using NT LM 0.12, so readx, writex. 1594 * Make sure we can represent the offset. 1595 */ 1596 if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0 && 1597 (uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX) 1598 return (EFBIG); 1599 1600 if (rw == UIO_READ) { 1601 iofun = smb_smb_readx; 1602 if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX) 1603 maxlen = SMB_MAX_LARGE_RW_SIZE; 1604 else 1605 maxlen = vcp->vc_rxmax; 1606 } else { /* UIO_WRITE */ 1607 iofun = smb_smb_writex; 1608 if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX) 1609 maxlen = SMB_MAX_LARGE_RW_SIZE; 1610 else 1611 maxlen = vcp->vc_wxmax; 1612 } 1613 } else { 1614 /* 1615 * Using the old SMB_READ and SMB_WRITE so 1616 * we're limited to 32-bit offsets, etc. 1617 * XXX: Someday, punt the old dialects. 1618 */ 1619 if ((uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX) 1620 return (EFBIG); 1621 1622 if (rw == UIO_READ) { 1623 iofun = smb_smb_read; 1624 maxlen = vcp->vc_rxmax; 1625 } else { /* UIO_WRITE */ 1626 iofun = smb_smb_write; 1627 maxlen = vcp->vc_wxmax; 1628 } 1629 } 1630 1631 save_resid = uiop->uio_resid; 1632 while (uiop->uio_resid > 0) { 1633 /* Lint: uio_resid may be 64-bits */ 1634 rlen = len = (uint32_t)min(maxlen, uiop->uio_resid); 1635 1636 SMBSDEBUG("rw=%d, off %lld, len %d\n", 1637 rw, uiop->uio_loffset, len); 1638 1639 error = (*iofun)(ssp, fid, &rlen, uiop, scred, timo); 1640 1641 /* 1642 * Note: the iofun called uio_update, so 1643 * not doing that here as one might expect. 1644 * 1645 * Quit the loop either on error, or if we 1646 * transferred less then requested. 1647 */ 1648 if (error || (rlen < len)) 1649 break; 1650 1651 timo = 0; /* only first I/O should wait */ 1652 } 1653 if (error && (save_resid != uiop->uio_resid)) { 1654 /* 1655 * Stopped on an error after having 1656 * successfully transferred data. 1657 * Suppress this error. 1658 */ 1659 SMBSDEBUG("error %d suppressed\n", error); 1660 error = 0; 1661 } 1662 1663 return (error); 1664 } 1665 1666 static int 1667 smb_smb_readx(struct smb_share *ssp, uint16_t fid, uint32_t *lenp, 1668 uio_t *uiop, smb_cred_t *scred, int timo) 1669 { 1670 struct smb_rq *rqp; 1671 struct mbchain *mbp; 1672 struct mdchain *mdp; 1673 int error; 1674 uint32_t offlo, offhi, rlen; 1675 uint16_t lenhi, lenlo, off, doff; 1676 uint8_t wc; 1677 1678 lenhi = (uint16_t)(*lenp >> 16); 1679 lenlo = (uint16_t)*lenp; 1680 offhi = (uint32_t)(uiop->uio_loffset >> 32); 1681 offlo = (uint32_t)uiop->uio_loffset; 1682 1683 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp); 1684 if (error) 1685 return (error); 1686 smb_rq_getrequest(rqp, &mbp); 1687 smb_rq_wstart(rqp); 1688 mb_put_uint8(mbp, 0xff); /* no secondary command */ 1689 mb_put_uint8(mbp, 0); /* MBZ */ 1690 mb_put_uint16le(mbp, 0); /* offset to secondary */ 1691 mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM); 1692 mb_put_uint32le(mbp, offlo); /* offset (low part) */ 1693 mb_put_uint16le(mbp, lenlo); /* MaxCount */ 1694 mb_put_uint16le(mbp, 1); /* MinCount */ 1695 /* (only indicates blocking) */ 1696 mb_put_uint32le(mbp, lenhi); /* MaxCountHigh */ 1697 mb_put_uint16le(mbp, lenlo); /* Remaining ("obsolete") */ 1698 mb_put_uint32le(mbp, offhi); /* offset (high part) */ 1699 smb_rq_wend(rqp); 1700 smb_rq_bstart(rqp); 1701 smb_rq_bend(rqp); 1702 do { 1703 if (timo == 0) 1704 timo = smb_timo_read; 1705 error = smb_rq_simple_timed(rqp, timo); 1706 if (error) 1707 break; 1708 smb_rq_getreply(rqp, &mdp); 1709 md_get_uint8(mdp, &wc); 1710 if (wc != 12) { 1711 error = EBADRPC; 1712 break; 1713 } 1714 md_get_uint8(mdp, NULL); 1715 md_get_uint8(mdp, NULL); 1716 md_get_uint16le(mdp, NULL); 1717 md_get_uint16le(mdp, NULL); 1718 md_get_uint16le(mdp, NULL); /* data compaction mode */ 1719 md_get_uint16le(mdp, NULL); 1720 md_get_uint16le(mdp, &lenlo); /* data len ret. */ 1721 md_get_uint16le(mdp, &doff); /* data offset */ 1722 md_get_uint16le(mdp, &lenhi); 1723 rlen = (lenhi << 16) | lenlo; 1724 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); 1725 md_get_uint16le(mdp, NULL); /* ByteCount */ 1726 /* 1727 * Does the data offset indicate padding? 1728 * Add up the gets above, we have: 1729 */ 1730 off = SMB_HDRLEN + 3 + (12 * 2); /* =59 */ 1731 if (doff > off) /* pad byte(s)? */ 1732 md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM); 1733 if (rlen == 0) { 1734 *lenp = rlen; 1735 break; 1736 } 1737 /* paranoid */ 1738 if (rlen > *lenp) { 1739 SMBSDEBUG("bad server! rlen %d, len %d\n", 1740 rlen, *lenp); 1741 rlen = *lenp; 1742 } 1743 error = md_get_uio(mdp, uiop, rlen); 1744 if (error) 1745 break; 1746 *lenp = rlen; 1747 /*LINTED*/ 1748 } while (0); 1749 smb_rq_done(rqp); 1750 return (error); 1751 } 1752 1753 static int 1754 smb_smb_writex(struct smb_share *ssp, uint16_t fid, uint32_t *lenp, 1755 uio_t *uiop, smb_cred_t *scred, int timo) 1756 { 1757 struct smb_rq *rqp; 1758 struct mbchain *mbp; 1759 struct mdchain *mdp; 1760 int error; 1761 uint32_t offlo, offhi, rlen; 1762 uint16_t lenhi, lenlo; 1763 uint8_t wc; 1764 1765 lenhi = (uint16_t)(*lenp >> 16); 1766 lenlo = (uint16_t)*lenp; 1767 offhi = (uint32_t)(uiop->uio_loffset >> 32); 1768 offlo = (uint32_t)uiop->uio_loffset; 1769 1770 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp); 1771 if (error) 1772 return (error); 1773 smb_rq_getrequest(rqp, &mbp); 1774 smb_rq_wstart(rqp); 1775 mb_put_uint8(mbp, 0xff); /* no secondary command */ 1776 mb_put_uint8(mbp, 0); /* MBZ */ 1777 mb_put_uint16le(mbp, 0); /* offset to secondary */ 1778 mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM); 1779 mb_put_uint32le(mbp, offlo); /* offset (low part) */ 1780 mb_put_uint32le(mbp, 0); /* MBZ (timeout) */ 1781 mb_put_uint16le(mbp, 0); /* !write-thru */ 1782 mb_put_uint16le(mbp, 0); 1783 mb_put_uint16le(mbp, lenhi); 1784 mb_put_uint16le(mbp, lenlo); 1785 mb_put_uint16le(mbp, 64); /* data offset from header start */ 1786 mb_put_uint32le(mbp, offhi); /* offset (high part) */ 1787 smb_rq_wend(rqp); 1788 smb_rq_bstart(rqp); 1789 do { 1790 mb_put_uint8(mbp, 0); /* pad byte */ 1791 error = mb_put_uio(mbp, uiop, *lenp); 1792 if (error) 1793 break; 1794 smb_rq_bend(rqp); 1795 if (timo == 0) 1796 timo = smb_timo_write; 1797 error = smb_rq_simple_timed(rqp, timo); 1798 if (error) 1799 break; 1800 smb_rq_getreply(rqp, &mdp); 1801 md_get_uint8(mdp, &wc); 1802 if (wc != 6) { 1803 error = EBADRPC; 1804 break; 1805 } 1806 md_get_uint8(mdp, NULL); /* andx cmd */ 1807 md_get_uint8(mdp, NULL); /* reserved */ 1808 md_get_uint16le(mdp, NULL); /* andx offset */ 1809 md_get_uint16le(mdp, &lenlo); /* data len ret. */ 1810 md_get_uint16le(mdp, NULL); /* remaining */ 1811 md_get_uint16le(mdp, &lenhi); 1812 rlen = (lenhi << 16) | lenlo; 1813 *lenp = rlen; 1814 /*LINTED*/ 1815 } while (0); 1816 1817 smb_rq_done(rqp); 1818 return (error); 1819 } 1820 1821 static int 1822 smb_smb_read(struct smb_share *ssp, uint16_t fid, uint32_t *lenp, 1823 uio_t *uiop, smb_cred_t *scred, int timo) 1824 { 1825 struct smb_rq *rqp; 1826 struct mbchain *mbp; 1827 struct mdchain *mdp; 1828 int error; 1829 uint32_t off32; 1830 uint16_t bc, cnt, dlen, rcnt, todo; 1831 uint8_t wc; 1832 1833 ASSERT(uiop->uio_loffset <= UINT32_MAX); 1834 off32 = (uint32_t)uiop->uio_loffset; 1835 ASSERT(*lenp <= UINT16_MAX); 1836 cnt = (uint16_t)*lenp; 1837 /* This next is an "estimate" of planned reads. */ 1838 todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX); 1839 1840 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp); 1841 if (error) 1842 return (error); 1843 smb_rq_getrequest(rqp, &mbp); 1844 smb_rq_wstart(rqp); 1845 mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM); 1846 mb_put_uint16le(mbp, cnt); 1847 mb_put_uint32le(mbp, off32); 1848 mb_put_uint16le(mbp, todo); 1849 smb_rq_wend(rqp); 1850 smb_rq_bstart(rqp); 1851 smb_rq_bend(rqp); 1852 do { 1853 if (timo == 0) 1854 timo = smb_timo_read; 1855 error = smb_rq_simple_timed(rqp, timo); 1856 if (error) 1857 break; 1858 smb_rq_getreply(rqp, &mdp); 1859 md_get_uint8(mdp, &wc); 1860 if (wc != 5) { 1861 error = EBADRPC; 1862 break; 1863 } 1864 md_get_uint16le(mdp, &rcnt); /* ret. count */ 1865 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); /* res. */ 1866 md_get_uint16le(mdp, &bc); /* byte count */ 1867 md_get_uint8(mdp, NULL); /* buffer format */ 1868 md_get_uint16le(mdp, &dlen); /* data len */ 1869 if (dlen < rcnt) { 1870 SMBSDEBUG("oops: dlen=%d rcnt=%d\n", 1871 (int)dlen, (int)rcnt); 1872 rcnt = dlen; 1873 } 1874 if (rcnt == 0) { 1875 *lenp = 0; 1876 break; 1877 } 1878 /* paranoid */ 1879 if (rcnt > cnt) { 1880 SMBSDEBUG("bad server! rcnt %d, cnt %d\n", 1881 (int)rcnt, (int)cnt); 1882 rcnt = cnt; 1883 } 1884 error = md_get_uio(mdp, uiop, (int)rcnt); 1885 if (error) 1886 break; 1887 *lenp = (int)rcnt; 1888 /*LINTED*/ 1889 } while (0); 1890 smb_rq_done(rqp); 1891 return (error); 1892 } 1893 1894 static int 1895 smb_smb_write(struct smb_share *ssp, uint16_t fid, uint32_t *lenp, 1896 uio_t *uiop, smb_cred_t *scred, int timo) 1897 { 1898 struct smb_rq *rqp; 1899 struct mbchain *mbp; 1900 struct mdchain *mdp; 1901 int error; 1902 uint32_t off32; 1903 uint16_t cnt, rcnt, todo; 1904 uint8_t wc; 1905 1906 ASSERT(uiop->uio_loffset <= UINT32_MAX); 1907 off32 = (uint32_t)uiop->uio_loffset; 1908 ASSERT(*lenp <= UINT16_MAX); 1909 cnt = (uint16_t)*lenp; 1910 /* This next is an "estimate" of planned writes. */ 1911 todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX); 1912 1913 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); 1914 if (error) 1915 return (error); 1916 smb_rq_getrequest(rqp, &mbp); 1917 smb_rq_wstart(rqp); 1918 mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM); 1919 mb_put_uint16le(mbp, cnt); 1920 mb_put_uint32le(mbp, off32); 1921 mb_put_uint16le(mbp, todo); 1922 smb_rq_wend(rqp); 1923 smb_rq_bstart(rqp); 1924 mb_put_uint8(mbp, SMB_DT_DATA); 1925 mb_put_uint16le(mbp, cnt); 1926 do { 1927 error = mb_put_uio(mbp, uiop, *lenp); 1928 if (error) 1929 break; 1930 smb_rq_bend(rqp); 1931 if (timo == 0) 1932 timo = smb_timo_write; 1933 error = smb_rq_simple_timed(rqp, timo); 1934 if (error) 1935 break; 1936 smb_rq_getreply(rqp, &mdp); 1937 md_get_uint8(mdp, &wc); 1938 if (wc != 1) { 1939 error = EBADRPC; 1940 break; 1941 } 1942 md_get_uint16le(mdp, &rcnt); 1943 *lenp = rcnt; 1944 /*LINTED*/ 1945 } while (0); 1946 smb_rq_done(rqp); 1947 return (error); 1948 } 1949 1950 1951 static u_int32_t smbechoes = 0; 1952 1953 int 1954 smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo) 1955 { 1956 struct smb_rq *rqp; 1957 struct mbchain *mbp; 1958 int error; 1959 1960 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp); 1961 if (error) 1962 return (error); 1963 mbp = &rqp->sr_rq; 1964 smb_rq_wstart(rqp); 1965 mb_put_uint16le(mbp, 1); /* echo count */ 1966 smb_rq_wend(rqp); 1967 smb_rq_bstart(rqp); 1968 mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes)); 1969 smb_rq_bend(rqp); 1970 /* 1971 * Note: the IOD calls this, so 1972 * this request must not wait for 1973 * connection state changes, etc. 1974 */ 1975 rqp->sr_flags |= SMBR_INTERNAL; 1976 error = smb_rq_simple_timed(rqp, timo); 1977 SMBSDEBUG("%d\n", error); 1978 smb_rq_done(rqp); 1979 return (error); 1980 } 1981 1982 #ifdef APPLE 1983 int 1984 smb_smb_checkdir(struct smb_share *ssp, void *dnp, char *name, 1985 int nmlen, struct smb_cred *scred) 1986 { 1987 struct smb_rq *rqp; 1988 struct mbchain *mbp; 1989 int error; 1990 1991 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CHECK_DIRECTORY, scred, &rqp); 1992 if (error) 1993 return (error); 1994 1995 smb_rq_getrequest(rqp, &mbp); 1996 smb_rq_wstart(rqp); 1997 smb_rq_wend(rqp); 1998 smb_rq_bstart(rqp); 1999 mb_put_uint8(mbp, SMB_DT_ASCII); 2000 /* 2001 * All we need to do is marshall the path: "\\" 2002 * (the root of the share) into this request. 2003 * We essentially in-line smbfs_fullpath() here, 2004 * except no mb_put_padbyte (already aligned). 2005 */ 2006 smb_put_dstring(mbp, SSTOVC(ssp), "\\", SMB_CS_NONE); 2007 smb_rq_bend(rqp); 2008 2009 error = smb_rq_simple(rqp); 2010 SMBSDEBUG("%d\n", error); 2011 smb_rq_done(rqp); 2012 2013 return (error); 2014 } 2015 #endif /* APPLE */ 2016