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 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 /* 43 * various SMB requests. Most of the routines merely packs data into mbufs. 44 */ 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kmem.h> 48 #include <sys/proc.h> 49 #include <sys/lock.h> 50 #include <sys/socket.h> 51 #include <sys/uio.h> 52 #include <sys/random.h> 53 #include <sys/note.h> 54 #include <sys/cmn_err.h> 55 56 #ifdef APPLE 57 #include <sys/smb_apple.h> 58 #include <sys/utfconv.h> 59 #else 60 #include <netsmb/smb_osdep.h> 61 #endif 62 63 #include <netsmb/smb.h> 64 #include <netsmb/smb_conn.h> 65 #include <netsmb/smb_rq.h> 66 #include <netsmb/smb_subr.h> 67 #include <netsmb/smb_tran.h> 68 69 /* 70 * Largest size to use with LARGE_READ/LARGE_WRITE. 71 * Specs say up to 64k data bytes, but Windows traffic 72 * uses 60k... no doubt for some good reason. 73 * (Probably to keep 4k block alignment.) 74 * XXX: Move to smb.h maybe? 75 */ 76 #define SMB_MAX_LARGE_RW_SIZE (60*1024) 77 78 /* 79 * Default timeout values, all in seconds. 80 * Make these tunable (only via mdb for now). 81 */ 82 int smb_timo_notice = 15; 83 int smb_timo_default = 30; /* was SMB_DEFRQTIMO */ 84 int smb_timo_open = 45; 85 int smb_timo_read = 45; 86 int smb_timo_write = 60; /* was SMBWRTTIMO */ 87 int smb_timo_append = 90; 88 89 static int smb_smb_read(struct smb_share *ssp, u_int16_t fid, 90 int *len, int *rresid, uio_t *uiop, struct smb_cred *scred, int timo); 91 static int smb_smb_write(struct smb_share *ssp, u_int16_t fid, 92 int *len, int *rresid, uio_t *uiop, struct smb_cred *scred, int timo); 93 94 struct smb_dialect { 95 int d_id; 96 const char *d_name; 97 }; 98 99 smb_unichar smb_unieol = 0; 100 101 static struct smb_dialect smb_dialects[] = { 102 {SMB_DIALECT_CORE, "PC NETWORK PROGRAM 1.0"}, 103 {SMB_DIALECT_LANMAN1_0, "LANMAN1.0"}, 104 {SMB_DIALECT_LANMAN2_0, "LM1.2X002"}, 105 {SMB_DIALECT_LANMAN2_1, "LANMAN2.1"}, 106 {SMB_DIALECT_NTLM0_12, "NT LM 0.12"}, 107 {-1, NULL} 108 }; 109 110 #define SMB_DIALECT_MAX \ 111 (sizeof (smb_dialects) / sizeof (struct smb_dialect) - 2) 112 113 /* 114 * Number of seconds between 1970 and 1601 year 115 */ 116 const u_int64_t DIFF1970TO1601 = 11644473600ULL; 117 118 void 119 smb_time_local2server(struct timespec *tsp, int tzoff, long *seconds) 120 { 121 /* 122 * XXX - what if we connected to the server when it was in 123 * daylight savings/summer time and we've subsequently switched 124 * to standard time, or vice versa, so that the time zone 125 * offset we got from the server is now wrong? 126 */ 127 *seconds = tsp->tv_sec - tzoff * 60; 128 /* - tz.tz_minuteswest * 60 - (wall_cmos_clock ? adjkerntz : 0) */ 129 } 130 131 void 132 smb_time_server2local(ulong_t seconds, int tzoff, struct timespec *tsp) 133 { 134 /* 135 * XXX - what if we connected to the server when it was in 136 * daylight savings/summer time and we've subsequently switched 137 * to standard time, or vice versa, so that the time zone 138 * offset we got from the server is now wrong? 139 */ 140 tsp->tv_sec = seconds + tzoff * 60; 141 /* + tz.tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0); */ 142 tsp->tv_nsec = 0; 143 } 144 145 /* 146 * Time from server comes as UTC, so no need to use tz 147 */ 148 /*ARGSUSED*/ 149 void 150 smb_time_NT2local(u_int64_t nsec, int tzoff, struct timespec *tsp) 151 { 152 smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp); 153 } 154 155 /*ARGSUSED*/ 156 void 157 smb_time_local2NT(struct timespec *tsp, int tzoff, u_int64_t *nsec) 158 { 159 long seconds; 160 161 smb_time_local2server(tsp, 0, &seconds); 162 *nsec = (((u_int64_t)(seconds) & ~1) + DIFF1970TO1601) * 163 (u_int64_t)10000000; 164 } 165 166 #if defined(NOICONVSUPPORT) || defined(lint) 167 extern int iconv_open(const char *to, const char *from, void **handle); 168 extern int iconv_close(void *handle); 169 #endif 170 171 int 172 smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred) 173 { 174 struct smb_dialect *dp; 175 struct smb_sopt *sp = NULL; 176 struct smb_rq *rqp; 177 struct mbchain *mbp; 178 struct mdchain *mdp; 179 u_int8_t wc, stime[8], sblen; 180 u_int16_t dindex, tw, tw1, swlen, bc; 181 int error; 182 int unicode = 0; 183 char *servercs; 184 void *servercshandle = NULL; 185 void *localcshandle = NULL; 186 u_int16_t toklen; 187 188 vcp->vc_hflags = SMB_FLAGS_CASELESS; /* XXX on Unix? */ 189 /* 190 * Make sure SMB_FLAGS2_UNICODE is "off" so mb_put_dstring 191 * marshalls the dialect strings in plain ascii. 192 */ 193 vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE; 194 vcp->vc_hflags2 |= SMB_FLAGS2_ERR_STATUS; 195 196 SMB_VC_LOCK(vcp); 197 vcp->vc_flags &= ~(SMBV_ENCRYPT); 198 SMB_VC_UNLOCK(vcp); 199 200 sp = &vcp->vc_sopt; 201 bzero(sp, sizeof (struct smb_sopt)); 202 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_NEGOTIATE, scred, &rqp); 203 if (error) 204 return (error); 205 smb_rq_getrequest(rqp, &mbp); 206 smb_rq_wstart(rqp); 207 smb_rq_wend(rqp); 208 smb_rq_bstart(rqp); 209 for (dp = smb_dialects; dp->d_id != -1; dp++) { 210 mb_put_uint8(mbp, SMB_DT_DIALECT); 211 smb_put_dstring(mbp, vcp, dp->d_name, SMB_CS_NONE); 212 } 213 smb_rq_bend(rqp); 214 215 /* 216 * This request should not wait for 217 * connection state changes, etc. 218 */ 219 rqp->sr_flags |= SMBR_INTERNAL; 220 error = smb_rq_simple(rqp); 221 SMBSDEBUG("%d\n", error); 222 if (error) 223 goto bad; 224 225 smb_rq_getreply(rqp, &mdp); 226 do { 227 error = md_get_uint8(mdp, &wc); 228 if (error) 229 break; 230 error = md_get_uint16le(mdp, &dindex); 231 if (error) 232 break; 233 error = EBADRPC; 234 if (dindex > SMB_DIALECT_MAX) { 235 SMBERROR( 236 "Don't know how to talk with server %s (%d)\n", 237 vcp->vc_srvname, dindex); 238 break; 239 } 240 dp = smb_dialects + dindex; 241 if (dindex < SMB_DIALECT_MAX) { 242 SMBERROR( 243 "Server %s negotiated old dialect (%s)\n", 244 vcp->vc_srvname, dp->d_name); 245 } 246 sp->sv_proto = dp->d_id; 247 SMBSDEBUG("Dialect %s (%d, %d)\n", dp->d_name, dindex, wc); 248 if (dp->d_id >= SMB_DIALECT_NTLM0_12) { 249 if (wc != 17) 250 break; 251 md_get_uint8(mdp, &sp->sv_sm); 252 md_get_uint16le(mdp, &sp->sv_maxmux); 253 md_get_uint16le(mdp, &sp->sv_maxvcs); 254 md_get_uint32le(mdp, &sp->sv_maxtx); 255 md_get_uint32le(mdp, &sp->sv_maxraw); 256 md_get_uint32le(mdp, &sp->sv_skey); 257 md_get_uint32le(mdp, &sp->sv_caps); 258 md_get_mem(mdp, (char *)stime, 8, MB_MSYSTEM); 259 md_get_uint16le(mdp, (u_int16_t *)&sp->sv_tz); 260 md_get_uint8(mdp, &sblen); 261 error = md_get_uint16le(mdp, &bc); 262 if (error) 263 break; 264 if (sp->sv_sm & SMB_SM_SIGS_REQUIRE) 265 SMBERROR("server configuration requires " 266 "packet signing, which we dont support: " 267 "sp->sv_sm %d\n", sp->sv_sm); 268 if (sp->sv_caps & SMB_CAP_UNICODE) { 269 SMB_VC_LOCK(vcp); 270 vcp->vc_flags |= SMBV_UNICODE; 271 SMB_VC_UNLOCK(vcp); 272 unicode = 1; 273 } 274 if (!(sp->sv_caps & SMB_CAP_STATUS32)) { 275 /* 276 * They don't do NT error codes. 277 * 278 * If we send requests with 279 * SMB_FLAGS2_ERR_STATUS set in 280 * Flags2, Windows 98, at least, 281 * appears to send replies with that 282 * bit set even though it sends back 283 * DOS error codes. (They probably 284 * just use the request header as 285 * a template for the reply header, 286 * and don't bother clearing that bit.) 287 * 288 * Therefore, we clear that bit in 289 * our vc_hflags2 field. 290 */ 291 vcp->vc_hflags2 &= ~SMB_FLAGS2_ERR_STATUS; 292 } 293 if (dp->d_id == SMB_DIALECT_NTLM0_12 && 294 sp->sv_maxtx < 4096 && 295 (sp->sv_caps & SMB_CAP_NT_SMBS) == 0) { 296 SMB_VC_LOCK(vcp); 297 vcp->vc_flags |= SMBV_WIN95; 298 SMB_VC_UNLOCK(vcp); 299 SMBSDEBUG("Win95 detected\n"); 300 } 301 302 /* 303 * 3 cases here: 304 * 305 * 1) Extended security. 306 * Read bc bytes below for security blob. 307 * Note that we DON'T put the Caps flag in outtok. 308 * outtoklen = bc 309 * 310 * 2) No extended security, have challenge data and 311 * possibly a domain name (which might be zero 312 * bytes long, meaning "missing"). 313 * Copy challenge stuff to vcp->vc_ch (sblen bytes), 314 * then copy Cap flags and domain name (bc-sblen 315 * bytes) to outtok. 316 * outtoklen = bc-sblen+4, where the 4 is for the 317 * Caps flag. 318 * 319 * 3) No extended security, no challenge data, just 320 * possibly a domain name. 321 * Copy Capsflags and domain name (bc) to outtok. 322 * outtoklen = bc+4, where 4 is for the Caps flag 323 */ 324 325 /* 326 * Sanity check: make sure the challenge length 327 * isn't bigger than the byte count. 328 */ 329 if (sblen > bc) { 330 error = EBADRPC; 331 break; 332 } 333 toklen = bc; 334 335 if (sblen && sblen <= SMB_MAXCHALLENGELEN && 336 sp->sv_sm & SMB_SM_ENCRYPT) { 337 error = md_get_mem(mdp, 338 (char *)vcp->vc_challenge, 339 sblen, MB_MSYSTEM); 340 if (error) 341 break; 342 vcp->vc_chlen = sblen; 343 toklen -= sblen; 344 345 SMB_VC_LOCK(vcp); 346 vcp->vc_flags |= SMBV_ENCRYPT; 347 SMB_VC_UNLOCK(vcp); 348 } 349 350 /* 351 * For servers that don't support unicode 352 * there are 2 things we could do: 353 * 1) Pass the server Caps flags up to the 354 * user level so the logic up there will 355 * know whether the domain name is unicode 356 * (this is what I did). 357 * 2) Try to convert the non-unicode string 358 * to unicode. This doubles the length of 359 * the outtok buffer and would be guessing that 360 * the string was single-byte ascii, and that 361 * might be wrong. Why ask for trouble? 362 */ 363 364 /* Warning: NetApp may omit the GUID */ 365 366 if (!(sp->sv_caps & SMB_CAP_EXT_SECURITY)) { 367 /* 368 * No extended security. 369 * Stick domain name, if present, 370 * and caps in outtok. 371 */ 372 toklen = toklen + 4; /* space for Caps flags */ 373 vcp->vc_outtoklen = toklen; 374 vcp->vc_outtok = kmem_alloc(toklen, KM_SLEEP); 375 /* first store server capability bits */ 376 /*LINTED*/ 377 ASSERT(vcp->vc_outtok == 378 (caddr_t)(((u_int32_t *)vcp->vc_outtok))); 379 /*LINTED*/ 380 *(u_int32_t *)(vcp->vc_outtok) = sp->sv_caps; 381 382 /* 383 * Then store the domain name if present; 384 * be sure to subtract 4 from the length 385 * for the Caps flag. 386 */ 387 if (toklen > 4) { 388 error = md_get_mem(mdp, 389 vcp->vc_outtok+4, toklen-4, 390 MB_MSYSTEM); 391 } 392 } else { 393 /* 394 * Extended security. 395 * Stick the rest of the buffer in outtok. 396 */ 397 vcp->vc_outtoklen = toklen; 398 vcp->vc_outtok = kmem_alloc(toklen, KM_SLEEP); 399 error = md_get_mem(mdp, vcp->vc_outtok, toklen, 400 MB_MSYSTEM); 401 } 402 break; 403 } 404 vcp->vc_hflags2 &= ~(SMB_FLAGS2_EXT_SEC|SMB_FLAGS2_DFS| 405 SMB_FLAGS2_ERR_STATUS|SMB_FLAGS2_UNICODE); 406 if (dp->d_id > SMB_DIALECT_CORE) { 407 md_get_uint16le(mdp, &tw); 408 sp->sv_sm = (uchar_t)tw; 409 md_get_uint16le(mdp, &tw); 410 sp->sv_maxtx = tw; 411 md_get_uint16le(mdp, &sp->sv_maxmux); 412 md_get_uint16le(mdp, &sp->sv_maxvcs); 413 md_get_uint16le(mdp, &tw); /* rawmode */ 414 md_get_uint32le(mdp, &sp->sv_skey); 415 if (wc == 13) { /* >= LANMAN1 */ 416 md_get_uint16(mdp, &tw); /* time */ 417 md_get_uint16(mdp, &tw1); /* date */ 418 md_get_uint16le(mdp, (u_int16_t *)&sp->sv_tz); 419 md_get_uint16le(mdp, &swlen); 420 if (swlen > SMB_MAXCHALLENGELEN) 421 break; 422 md_get_uint16(mdp, NULL); /* mbz */ 423 if (md_get_uint16le(mdp, &bc) != 0) 424 break; 425 if (bc < swlen) 426 break; 427 if (swlen && (sp->sv_sm & SMB_SM_ENCRYPT)) { 428 error = md_get_mem(mdp, 429 (char *)vcp->vc_challenge, 430 swlen, MB_MSYSTEM); 431 if (error) 432 break; 433 vcp->vc_chlen = swlen; 434 435 SMB_VC_LOCK(vcp); 436 vcp->vc_flags |= SMBV_ENCRYPT; 437 SMB_VC_UNLOCK(vcp); 438 } 439 } 440 } else { /* an old CORE protocol */ 441 vcp->vc_hflags2 &= ~SMB_FLAGS2_KNOWS_LONG_NAMES; 442 sp->sv_maxmux = 1; 443 } 444 error = 0; 445 /*LINTED*/ 446 } while (0); 447 if (error == 0) { 448 uint32_t x; 449 450 /* 451 * Maximum outstanding requests. 452 */ 453 if (vcp->vc_maxmux < 1) 454 vcp->vc_maxmux = 1; 455 456 /* 457 * Max VCs between server and client. 458 * We only use one. 459 */ 460 vcp->vc_maxvcs = sp->sv_maxvcs; 461 if (vcp->vc_maxvcs < 1) 462 vcp->vc_maxvcs = 1; 463 464 /* 465 * Maximum transfer size. 466 * Sanity checks: 467 * 468 * Spec. says lower limit is 1024. OK. 469 * 470 * Let's be conservative about an upper limit here. 471 * Win2k uses 16644 (and others) so 32k should be a 472 * reasonable sanity limit for this value. 473 * 474 * Note that this limit does NOT affect READX/WRITEX 475 * with CAP_LARGE_xxx, which we nearly always use. 476 */ 477 vcp->vc_txmax = sp->sv_maxtx; 478 if (vcp->vc_txmax < 1024) 479 vcp->vc_txmax = 1024; 480 if (vcp->vc_txmax > 0x8000) 481 vcp->vc_txmax = 0x8000; 482 483 /* 484 * Max read/write sizes, WITHOUT overhead. 485 * This is just the payload size, so we must 486 * leave room for the SMB headers, etc. 487 * 488 * With CAP_LARGE_xxx, always use 60k. 489 * Otherwise use the vc_txmax value, but 490 * reduced and rounded down. Tricky bit: 491 * 492 * Servers typically give us a value that's 493 * some nice "round" number, i.e 0x4000 plus 494 * some overhead, i.e. Win2k: 16644==0x4104 495 * Subtract for the SMB header (32) and the 496 * SMB command word and byte vectors (34?), 497 * then round down to a 512 byte multiple. 498 */ 499 x = (vcp->vc_txmax - 68) & 0xFE00; 500 if (sp->sv_caps & SMB_CAP_LARGE_READX) 501 vcp->vc_rxmax = SMB_MAX_LARGE_RW_SIZE; 502 else 503 vcp->vc_rxmax = x; 504 if (sp->sv_caps & SMB_CAP_LARGE_WRITEX) 505 vcp->vc_wxmax = SMB_MAX_LARGE_RW_SIZE; 506 else 507 vcp->vc_wxmax = x; 508 509 SMBSDEBUG("TZ = %d\n", sp->sv_tz); 510 SMBSDEBUG("CAPS = %x\n", sp->sv_caps); 511 512 SMBSDEBUG("maxmux = %d\n", vcp->vc_maxmux); 513 SMBSDEBUG("maxvcs = %d\n", vcp->vc_maxvcs); 514 SMBSDEBUG("txmax = %d\n", vcp->vc_txmax); 515 SMBSDEBUG("rxmax = %d\n", vcp->vc_rxmax); 516 SMBSDEBUG("wxmax = %d\n", vcp->vc_wxmax); 517 } 518 519 /* 520 * If the server supports Unicode, set up to use Unicode 521 * when talking to them. Othewise, use code page 437. 522 */ 523 if (unicode) 524 servercs = "ucs-2"; 525 else { 526 /* 527 * todo: if we can't determine the server's encoding, we 528 * need to try a best-guess here. 529 */ 530 servercs = "cp437"; 531 } 532 #if defined(NOICONVSUPPORT) || defined(lint) 533 /* 534 * REVISIT 535 */ 536 error = iconv_open(servercs, "utf-8", &servercshandle); 537 if (error != 0) 538 goto bad; 539 error = iconv_open("utf-8", servercs, &localcshandle); 540 if (error != 0) { 541 iconv_close(servercshandle); 542 goto bad; 543 } 544 if (vcp->vc_toserver) 545 iconv_close(vcp->vc_toserver); 546 if (vcp->vc_tolocal) 547 iconv_close(vcp->vc_tolocal); 548 vcp->vc_toserver = servercshandle; 549 vcp->vc_tolocal = localcshandle; 550 #endif 551 if (unicode) 552 vcp->vc_hflags2 |= SMB_FLAGS2_UNICODE; 553 bad: 554 smb_rq_done(rqp); 555 return (error); 556 } 557 558 static void 559 get_ascii_password(struct smb_vc *vcp, int upper, char *pbuf) 560 { 561 const char *pw = smb_vc_getpass(vcp); 562 if (upper) 563 smb_toupper(pw, pbuf, SMB_MAXPASSWORDLEN); 564 else 565 strncpy(pbuf, pw, SMB_MAXPASSWORDLEN); 566 pbuf[SMB_MAXPASSWORDLEN] = '\0'; 567 } 568 569 #ifdef APPLE 570 static void 571 get_unicode_password(struct smb_vc *vcp, char *pbuf) 572 { 573 strncpy(pbuf, smb_vc_getpass(vcp), SMB_MAXPASSWORDLEN); 574 pbuf[SMB_MAXPASSWORDLEN] = '\0'; 575 } 576 #endif 577 578 /*ARGSUSED*/ 579 static uchar_t * 580 add_name_to_blob(uchar_t *blobnames, struct smb_vc *vcp, const uchar_t *name, 581 size_t namelen, int nametype, int uppercase) 582 { 583 struct ntlmv2_namehdr namehdr; 584 char *namebuf; 585 u_int16_t *uninamebuf; 586 size_t uninamelen; 587 588 if (name != NULL) { 589 uninamebuf = kmem_alloc(2 * namelen, KM_SLEEP); 590 if (uppercase) { 591 namebuf = kmem_alloc(namelen + 1, KM_SLEEP); 592 smb_toupper((const char *)name, namebuf, namelen); 593 namebuf[namelen] = '\0'; 594 uninamelen = smb_strtouni(uninamebuf, namebuf, namelen, 595 UCONV_IGNORE_NULL); 596 kmem_free(namebuf, namelen + 1); 597 } else { 598 uninamelen = smb_strtouni(uninamebuf, (char *)name, 599 namelen, UCONV_IGNORE_NULL); 600 } 601 } else { 602 uninamelen = 0; 603 uninamebuf = NULL; 604 } 605 namehdr.type = htoles(nametype); 606 namehdr.len = htoles(uninamelen); 607 bcopy(&namehdr, blobnames, sizeof (namehdr)); 608 blobnames += sizeof (namehdr); 609 if (uninamebuf != NULL) { 610 bcopy(uninamebuf, blobnames, uninamelen); 611 blobnames += uninamelen; 612 kmem_free(uninamebuf, namelen * 2); 613 } 614 return (blobnames); 615 } 616 617 static uchar_t * 618 make_ntlmv2_blob(struct smb_vc *vcp, u_int64_t client_nonce, size_t *bloblen) 619 { 620 uchar_t *blob; 621 size_t blobsize; 622 size_t domainlen, srvlen; 623 struct ntlmv2_blobhdr *blobhdr; 624 struct timespec now; 625 u_int64_t timestamp; 626 uchar_t *blobnames; 627 ptrdiff_t diff; 628 629 /* 630 * XXX - the information at 631 * 632 * http://davenport.sourceforge.net/ntlm.html#theNtlmv2Response 633 * 634 * says that the "target information" comes from the Type 2 message, 635 * but, as we're not doing NTLMSSP, we don't have that. 636 * 637 * Should we use the names from the NegProt response? Can we trust 638 * the NegProt response? (I've seen captures where the primary 639 * domain name has an extra byte in front of it.) 640 * 641 * For now, we don't trust it - we use vcp->vc_domain and 642 * vcp->vc_srvname, instead. We upper-case them and convert 643 * them to Unicode, as that's what's supposed to be in the blob. 644 */ 645 domainlen = strlen(vcp->vc_domain); 646 srvlen = strlen(vcp->vc_srvname); 647 blobsize = sizeof (struct ntlmv2_blobhdr) 648 + 3*sizeof (struct ntlmv2_namehdr) + 4 + 2*domainlen + 2*srvlen; 649 blob = kmem_zalloc(blobsize, KM_SLEEP); 650 /*LINTED*/ 651 ASSERT(blob == (uchar_t *)((struct ntlmv2_blobhdr *)blob)); 652 /*LINTED*/ 653 blobhdr = (struct ntlmv2_blobhdr *)blob; 654 blobhdr->header = htolel(0x00000101); 655 gethrestime(&now); 656 smb_time_local2NT(&now, 0, ×tamp); 657 blobhdr->timestamp = htoleq(timestamp); 658 blobhdr->client_nonce = client_nonce; 659 blobnames = blob + sizeof (struct ntlmv2_blobhdr); 660 blobnames = add_name_to_blob(blobnames, vcp, (uchar_t *)vcp->vc_domain, 661 domainlen, NAMETYPE_DOMAIN_NB, 1); 662 blobnames = add_name_to_blob(blobnames, vcp, (uchar_t *)vcp->vc_srvname, 663 srvlen, NAMETYPE_MACHINE_NB, 1); 664 blobnames = add_name_to_blob(blobnames, vcp, NULL, 0, NAMETYPE_EOL, 0); 665 diff = (intptr_t)blobnames - (intptr_t)blob; 666 ASSERT(diff == (ptrdiff_t)((size_t)diff)); 667 *bloblen = (size_t)diff; 668 return (blob); 669 } 670 671 /* 672 * See radar 4134676. This define helps us avoid how a certain old server 673 * grants limited Guest access when we try NTLMv2, but works fine with NTLM. 674 * The fingerprint we are looking for here is DOS error codes and no-Unicode. 675 * Note XP grants Guest access but uses Unicode and NT error codes. 676 */ 677 #define smb_antique(rqp) (!((rqp)->sr_rpflags2 & SMB_FLAGS2_ERR_STATUS) && \ 678 !((rqp)->sr_rpflags2 & SMB_FLAGS2_UNICODE)) 679 680 /* 681 * When not doing Kerberos, we can try, in order: 682 * 683 * NTLMv2 684 * NTLM with the ASCII password not upper-cased 685 * NTLM with the ASCII password upper-cased 686 * 687 * if the server supports encrypted passwords, or 688 * 689 * plain-text with the ASCII password not upper-cased 690 * plain-text with the ASCII password upper-cased 691 * 692 * if it doesn't. 693 */ 694 #define STATE_NTLMV2 0 695 #define STATE_NOUCPW 1 696 #define STATE_UCPW 2 697 698 int 699 smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred) 700 { 701 struct smb_rq *rqp; 702 struct mbchain *mbp; 703 struct mdchain *mdp; 704 u_int8_t wc; 705 int minauth; 706 smb_uniptr unipp = NULL, ntencpass = NULL; 707 char *pp = NULL, *up = NULL, *ucup = NULL, *ucdp = NULL; 708 char *pbuf = NULL; 709 char *encpass = NULL; 710 int error = 0; 711 size_t plen = 0, uniplen = 0, uniplen2 = 0, tmplen; 712 size_t ucup_sl = 0, ucdp_sl = 0; 713 int state; 714 size_t ntlmv2_bloblen; 715 uchar_t *ntlmv2_blob; 716 u_int64_t client_nonce; 717 u_int32_t caps; 718 u_int16_t bl; /* BLOB length */ 719 u_int16_t saveflags2 = vcp->vc_hflags2; 720 void * savetoserver = vcp->vc_toserver; 721 u_int16_t action; 722 int declinedguest = 0; 723 static const char NativeOS[] = "Solaris"; 724 static const char LanMan[] = "NETSMB"; 725 /* 726 * Most of the "capability" bits we offer should be copied 727 * from those offered by the server, with a mask applied. 728 * This is the mask of capabilies copied from the server. 729 * Some others get special handling below. 730 */ 731 static const uint32_t caps_mask = 732 SMB_CAP_UNICODE | 733 SMB_CAP_LARGE_FILES | 734 SMB_CAP_NT_SMBS | 735 SMB_CAP_STATUS32 | 736 SMB_CAP_LARGE_READX | 737 SMB_CAP_LARGE_WRITEX; 738 739 caps = vcp->vc_sopt.sv_caps & caps_mask; 740 741 /* No unicode unless server supports and encryption on */ 742 if (!((vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) && 743 (vcp->vc_flags & SMBV_UNICODE))) { 744 vcp->vc_hflags2 &= 0xffff - SMB_FLAGS2_UNICODE; 745 vcp->vc_toserver = 0; 746 } 747 748 minauth = vcp->vc_vopt & SMBVOPT_MINAUTH; 749 if (vcp->vc_intok) { 750 if (vcp->vc_intoklen > 65536 || 751 !(vcp->vc_hflags2 & SMB_FLAGS2_EXT_SEC) || 752 SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) { 753 error = EINVAL; 754 goto ssn_exit; 755 } 756 vcp->vc_smbuid = 0; 757 } 758 759 /* 760 * Try only plain text passwords. 761 */ 762 if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) { 763 state = STATE_NTLMV2; /* try NTLMv2 first */ 764 } else { 765 state = STATE_NOUCPW; /* try plain-text mixed-case first */ 766 } 767 again: 768 769 if (!vcp->vc_intok) 770 vcp->vc_smbuid = SMB_UID_UNKNOWN; 771 772 if (!vcp->vc_intok) { 773 /* 774 * We're not doing extended security, which, for 775 * now, means we're not doing Kerberos. 776 * Fail if the minimum authentication level is 777 * Kerberos. 778 */ 779 if (minauth >= SMBVOPT_MINAUTH_KERBEROS) { 780 error = EAUTH; 781 goto ssn_exit; 782 } 783 if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) { 784 /* 785 * Server wants encrypted passwords. 786 */ 787 if (state > STATE_NTLMV2) { 788 /* 789 * We tried NTLMv2 in STATE_NTLMV2. 790 * Shall we allow fallback? (to NTLM) 791 */ 792 if (minauth >= SMBVOPT_MINAUTH_NTLMV2) { 793 error = EAUTH; 794 goto ssn_exit; 795 } 796 } 797 if (state > STATE_NOUCPW) { 798 /* 799 * We tried NTLM in STATE_NOUCPW. 800 * No need to try it again. 801 */ 802 error = EAUTH; 803 goto ssn_exit; 804 } 805 } else { 806 /* 807 * Plain-text passwords. 808 * Fail if the minimum authentication level is 809 * LM or better. 810 */ 811 if (minauth > SMBVOPT_MINAUTH_NTLM) { 812 error = EAUTH; 813 goto ssn_exit; 814 } 815 } 816 } 817 818 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX, 819 scred, &rqp); 820 if (error) 821 goto ssn_exit; 822 823 /* 824 * Domain name must be upper-case, as that's what's used 825 * when computing LMv2 and NTLMv2 responses - and, for NTLMv2, 826 * the domain name in the request has to be upper-cased as well. 827 * (That appears not to be the case for the user name. Go 828 * figure.) 829 * 830 * don't need to uppercase domain string. It's already uppercase UTF-8. 831 */ 832 833 ucdp_sl = strlen(vcp->vc_domain); 834 ucdp = kmem_zalloc(ucdp_sl + 1, KM_SLEEP); 835 memcpy(ucdp, vcp->vc_domain, ucdp_sl + 1); 836 837 if (vcp->vc_intok) { 838 caps |= SMB_CAP_EXT_SECURITY; 839 } else if (!(vcp->vc_sopt.sv_sm & SMB_SM_USER)) { 840 /* 841 * In the share security mode password will be used 842 * only in the tree authentication 843 */ 844 pp = ""; 845 plen = 1; 846 unipp = &smb_unieol; 847 uniplen = sizeof (smb_unieol); 848 } else { 849 pbuf = kmem_alloc(SMB_MAXPASSWORDLEN + 1, KM_SLEEP); 850 if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) { 851 if (state == STATE_NTLMV2) { 852 /* 853 * Compute the LMv2 and NTLMv2 responses, 854 * derived from the challenge, the user name, 855 * the domain/workgroup into which we're 856 * logging, and the Unicode password. 857 */ 858 859 /* 860 * Construct the client nonce by getting 861 * a bunch of random data. 862 */ 863 (void) random_get_pseudo_bytes((void *) 864 &client_nonce, sizeof (client_nonce)); 865 866 /* 867 * Convert the user name to upper-case, as 868 * that's what's used when computing LMv2 869 * and NTLMv2 responses. 870 */ 871 ucup_sl = strlen(vcp->vc_username); 872 ucup = kmem_alloc(ucup_sl + 1, KM_SLEEP); 873 smb_toupper((const char *)vcp->vc_username, 874 ucup, ucup_sl); 875 ucup[ucup_sl] = '\0'; 876 877 /* 878 * Compute the LMv2 response, derived 879 * from the server challenge, the 880 * user name, the domain/workgroup 881 * into which we're logging, the 882 * client nonce, and the NT hash. 883 */ 884 smb_ntlmv2response(vcp->vc_nthash, 885 (uchar_t *)ucup, (uchar_t *)ucdp, 886 vcp->vc_challenge, 887 (uchar_t *)&client_nonce, 8, 888 (uchar_t **)&encpass, &plen); 889 pp = encpass; 890 891 /* 892 * Construct the blob. 893 */ 894 ntlmv2_blob = make_ntlmv2_blob(vcp, 895 client_nonce, &ntlmv2_bloblen); 896 897 /* 898 * Compute the NTLMv2 response, derived 899 * from the server challenge, the 900 * user name, the domain/workgroup 901 * into which we're logging, the 902 * blob, and the NT hash. 903 */ 904 smb_ntlmv2response(vcp->vc_nthash, 905 (uchar_t *)ucup, (uchar_t *)ucdp, 906 vcp->vc_challenge, 907 ntlmv2_blob, ntlmv2_bloblen, 908 (uchar_t **)&ntencpass, &uniplen); 909 uniplen2 = uniplen; 910 unipp = ntencpass; 911 tmplen = plen; 912 913 kmem_free(ucup, ucup_sl + 1); 914 kmem_free((char *)ntlmv2_blob, 915 sizeof (struct ntlmv2_blobhdr) + 916 3 * sizeof (struct ntlmv2_namehdr) + 917 4 + 918 2 * strlen(vcp->vc_domain) + 919 2 * strlen(vcp->vc_srvname)); 920 } else { 921 plen = 24; 922 encpass = kmem_zalloc(plen, KM_SLEEP); 923 /* 924 * Compute the LM response, derived 925 * from the challenge and the ASCII 926 * password. 927 */ 928 if (minauth < SMBVOPT_MINAUTH_NTLM) { 929 smb_lmresponse(vcp->vc_lmhash, 930 vcp->vc_challenge, 931 (uchar_t *)encpass); 932 } 933 pp = encpass; 934 935 /* 936 * Compute the NTLM response, derived from 937 * the challenge and the NT hash. 938 */ 939 uniplen = 24; 940 uniplen2 = uniplen; 941 ntencpass = kmem_alloc(uniplen, KM_SLEEP); 942 smb_lmresponse(vcp->vc_nthash, 943 vcp->vc_challenge, 944 (uchar_t *)ntencpass); 945 unipp = ntencpass; 946 } 947 } else { 948 /* 949 * We try w/o uppercasing first so Samba mixed case 950 * passwords work. If that fails, we come back and 951 * try uppercasing to satisfy OS/2 and Windows for 952 * Workgroups. 953 */ 954 get_ascii_password(vcp, (state == STATE_UCPW), pbuf); 955 plen = strlen(pbuf) + 1; 956 pp = pbuf; 957 uniplen = plen * 2; 958 uniplen2 = uniplen; 959 ntencpass = kmem_alloc(uniplen, KM_SLEEP); 960 (void) smb_strtouni(ntencpass, smb_vc_getpass(vcp), 961 0, 0); 962 plen--; 963 /* 964 * The uniplen is zeroed because Samba cannot deal 965 * with this 2nd cleartext password. This Samba 966 * "bug" is actually a workaround for problems in 967 * Microsoft clients. 968 */ 969 uniplen = 0; /* -= 2 */ 970 unipp = ntencpass; 971 } 972 } 973 smb_rq_wstart(rqp); 974 mbp = &rqp->sr_rq; 975 up = vcp->vc_username; 976 /* 977 * If userid is null we are attempting anonymous browse login 978 * so passwords must be zero length. 979 */ 980 if (*up == '\0') { 981 plen = uniplen = 0; 982 } 983 mb_put_uint8(mbp, 0xff); 984 mb_put_uint8(mbp, 0); 985 mb_put_uint16le(mbp, 0); 986 mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxtx); 987 mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxmux); 988 mb_put_uint16le(mbp, vcp->vc_number); 989 mb_put_uint32le(mbp, vcp->vc_sopt.sv_skey); 990 if ((SMB_DIALECT(vcp)) < SMB_DIALECT_NTLM0_12) { 991 mb_put_uint16le(mbp, plen); 992 mb_put_uint32le(mbp, 0); 993 smb_rq_wend(rqp); 994 smb_rq_bstart(rqp); 995 mb_put_mem(mbp, pp, plen, MB_MSYSTEM); 996 smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* user */ 997 smb_put_dstring(mbp, vcp, ucdp, SMB_CS_NONE); /* domain */ 998 } else { 999 if (vcp->vc_intok) { 1000 mb_put_uint16le(mbp, vcp->vc_intoklen); 1001 mb_put_uint32le(mbp, 0); /* reserved */ 1002 mb_put_uint32le(mbp, caps); /* my caps */ 1003 smb_rq_wend(rqp); 1004 smb_rq_bstart(rqp); 1005 mb_put_mem(mbp, vcp->vc_intok, vcp->vc_intoklen, 1006 MB_MSYSTEM); /* security blob */ 1007 } else { 1008 mb_put_uint16le(mbp, plen); 1009 mb_put_uint16le(mbp, uniplen); 1010 mb_put_uint32le(mbp, 0); /* reserved */ 1011 mb_put_uint32le(mbp, caps); /* my caps */ 1012 smb_rq_wend(rqp); 1013 smb_rq_bstart(rqp); 1014 mb_put_mem(mbp, pp, plen, MB_MSYSTEM); /* password */ 1015 mb_put_mem(mbp, (caddr_t)unipp, uniplen, MB_MSYSTEM); 1016 smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* user */ 1017 smb_put_dstring(mbp, vcp, ucdp, SMB_CS_NONE); /* dom */ 1018 } 1019 } 1020 smb_put_dstring(mbp, vcp, NativeOS, SMB_CS_NONE); /* OS */ 1021 smb_put_dstring(mbp, vcp, LanMan, SMB_CS_NONE); /* LAN Mgr */ 1022 smb_rq_bend(rqp); 1023 if (ntencpass) { 1024 kmem_free(ntencpass, uniplen2); 1025 ntencpass = NULL; 1026 } 1027 if (encpass) { 1028 kmem_free(encpass, 24); 1029 encpass = NULL; 1030 } 1031 if (ucdp) { 1032 kmem_free(ucdp, ucdp_sl + 1); 1033 ucdp = NULL; 1034 } 1035 1036 /* 1037 * This request should not wait for 1038 * connection state changes, etc. 1039 */ 1040 rqp->sr_flags |= SMBR_INTERNAL; 1041 error = smb_rq_simple_timed(rqp, SMBSSNSETUPTIMO); 1042 SMBSDEBUG("%d\n", error); 1043 if (error) { 1044 if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnoaccess) 1045 error = EAUTH; 1046 if (!(rqp->sr_errclass == ERRDOS && 1047 rqp->sr_serror == ERRmoredata)) 1048 goto bad; 1049 } 1050 vcp->vc_smbuid = rqp->sr_rpuid; 1051 smb_rq_getreply(rqp, &mdp); 1052 do { 1053 error = md_get_uint8(mdp, &wc); 1054 if (error) 1055 break; 1056 error = EBADRPC; 1057 if (vcp->vc_intok) { 1058 if (wc != 4) 1059 break; 1060 } else if (wc != 3) 1061 break; 1062 md_get_uint8(mdp, NULL); /* secondary cmd */ 1063 md_get_uint8(mdp, NULL); /* mbz */ 1064 md_get_uint16le(mdp, NULL); /* andxoffset */ 1065 md_get_uint16le(mdp, &action); /* action */ 1066 if (vcp->vc_intok) 1067 md_get_uint16le(mdp, &bl); /* ext security */ 1068 md_get_uint16le(mdp, NULL); /* byte count */ 1069 if (vcp->vc_intok) { 1070 vcp->vc_outtoklen = bl; 1071 vcp->vc_outtok = kmem_alloc(bl, KM_SLEEP); 1072 error = md_get_mem(mdp, vcp->vc_outtok, bl, MB_MSYSTEM); 1073 if (error) 1074 break; 1075 } 1076 /* server OS, LANMGR, & Domain here */ 1077 error = 0; 1078 /*LINTED*/ 1079 } while (0); 1080 bad: 1081 if (encpass) { 1082 kmem_free(encpass, tmplen); 1083 encpass = NULL; 1084 } 1085 if (pbuf) { 1086 kmem_free(pbuf, SMB_MAXPASSWORDLEN + 1); 1087 pbuf = NULL; 1088 } 1089 if (vcp->vc_sopt.sv_sm & SMB_SM_USER && !vcp->vc_intok && 1090 (error || (*up != '\0' && action & SMB_ACT_GUEST && 1091 state == STATE_NTLMV2 && smb_antique(rqp)))) { 1092 /* 1093 * We're doing user-level authentication (so we are actually 1094 * sending authentication stuff over the wire), and we're 1095 * not doing extended security, and the stuff we tried 1096 * failed (or we we're trying to login a real user but 1097 * got granted guest access instead.) 1098 */ 1099 if (!error) 1100 declinedguest = 1; 1101 /* 1102 * Should we try the next type of authentication? 1103 */ 1104 if (state < STATE_UCPW) { 1105 /* 1106 * Yes, we still have more to try. 1107 */ 1108 state++; 1109 smb_rq_done(rqp); 1110 goto again; 1111 } 1112 } 1113 smb_rq_done(rqp); 1114 1115 ssn_exit: 1116 if (error && declinedguest) 1117 SMBERROR("we declined ntlmv2 guest access. errno will be %d\n", 1118 error); 1119 /* Restore things we changed and return */ 1120 vcp->vc_hflags2 = saveflags2; 1121 vcp->vc_toserver = savetoserver; 1122 return (error); 1123 } 1124 1125 int 1126 smb_smb_ssnclose(struct smb_vc *vcp, struct smb_cred *scred) 1127 { 1128 struct smb_rq *rqp; 1129 struct mbchain *mbp; 1130 int error; 1131 1132 if (vcp->vc_smbuid == SMB_UID_UNKNOWN) 1133 return (0); 1134 1135 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp); 1136 if (error) 1137 return (error); 1138 mbp = &rqp->sr_rq; 1139 smb_rq_wstart(rqp); 1140 mb_put_uint8(mbp, 0xff); 1141 mb_put_uint8(mbp, 0); 1142 mb_put_uint16le(mbp, 0); 1143 smb_rq_wend(rqp); 1144 smb_rq_bstart(rqp); 1145 smb_rq_bend(rqp); 1146 /* 1147 * Run this with a relatively short timeout. 1148 * We don't really care about the result, 1149 * as we're just trying to play nice and 1150 * "say goodbye" before we hangup. 1151 * XXX: Add SMBLOGOFFTIMO somewhere? 1152 */ 1153 error = smb_rq_simple_timed(rqp, 5); 1154 SMBSDEBUG("%d\n", error); 1155 smb_rq_done(rqp); 1156 return (error); 1157 } 1158 1159 static char smb_any_share[] = "?????"; 1160 1161 static char * 1162 smb_share_typename(int stype) 1163 { 1164 char *pp; 1165 1166 switch (stype) { 1167 case STYPE_DISKTREE: 1168 pp = "A:"; 1169 break; 1170 case STYPE_PRINTQ: 1171 pp = smb_any_share; /* can't use LPT: here... */ 1172 break; 1173 case STYPE_DEVICE: 1174 pp = "COMM"; 1175 break; 1176 case STYPE_IPC: 1177 pp = "IPC"; 1178 break; 1179 default: 1180 pp = smb_any_share; 1181 break; 1182 } 1183 return (pp); 1184 } 1185 1186 int 1187 smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred) 1188 { 1189 struct smb_vc *vcp; 1190 struct smb_rq rq, *rqp = &rq; 1191 struct mbchain *mbp; 1192 char *pp, *pbuf, *encpass; 1193 const char *pw; 1194 uchar_t hash[SMB_PWH_MAX]; 1195 int error, plen, caseopt; 1196 int upper = 0; 1197 1198 again: 1199 vcp = SSTOVC(ssp); 1200 1201 /* 1202 * Make this a "VC-level" request, so it will have 1203 * rqp->sr_share == NULL, and smb_iod_sendrq() 1204 * will send it with TID = SMB_TID_UNKNOWN 1205 * 1206 * This also serves to bypass the wait for 1207 * share state changes, which this call is 1208 * trying to carry out. 1209 * 1210 * No longer need to set ssp->ss_tid 1211 * here, but it's harmless enough. 1212 */ 1213 ssp->ss_tid = SMB_TID_UNKNOWN; 1214 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_CONNECT_ANDX, 1215 scred, &rqp); 1216 if (error) 1217 return (error); 1218 caseopt = SMB_CS_NONE; 1219 if (vcp->vc_sopt.sv_sm & SMB_SM_USER) { 1220 plen = 1; 1221 pp = ""; 1222 pbuf = NULL; 1223 encpass = NULL; 1224 } else { 1225 pbuf = kmem_alloc(SMB_MAXPASSWORDLEN + 1, KM_SLEEP); 1226 encpass = kmem_alloc(24, KM_SLEEP); 1227 pw = smb_share_getpass(ssp); 1228 /* 1229 * We try w/o uppercasing first so Samba mixed case 1230 * passwords work. If that fails we come back and try 1231 * uppercasing to satisfy OS/2 and Windows for Workgroups. 1232 */ 1233 if (upper++) { 1234 smb_toupper(pw, pbuf, SMB_MAXPASSWORDLEN); 1235 smb_oldlm_hash(pw, hash); 1236 } else { 1237 strncpy(pbuf, pw, SMB_MAXPASSWORDLEN); 1238 smb_ntlmv1hash(pw, hash); 1239 } 1240 pbuf[SMB_MAXPASSWORDLEN] = '\0'; 1241 1242 #ifdef NOICONVSUPPORT 1243 /* 1244 * We need to convert here to the server codeset. 1245 * Initially we will send the same stuff and see what happens 1246 * witout the conversion. REVISIT. 1247 */ 1248 iconv_convstr(vcp->vc_toserver, pbuf, pbuf, SMB_MAXPASSWORDLEN); 1249 #endif 1250 if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) { 1251 plen = 24; 1252 smb_lmresponse(hash, 1253 vcp->vc_challenge, 1254 (uchar_t *)encpass); 1255 pp = encpass; 1256 } else { 1257 plen = strlen(pbuf) + 1; 1258 pp = pbuf; 1259 } 1260 } 1261 mbp = &rqp->sr_rq; 1262 smb_rq_wstart(rqp); 1263 mb_put_uint8(mbp, 0xff); 1264 mb_put_uint8(mbp, 0); 1265 mb_put_uint16le(mbp, 0); 1266 mb_put_uint16le(mbp, 0); /* Flags */ 1267 mb_put_uint16le(mbp, plen); 1268 smb_rq_wend(rqp); 1269 smb_rq_bstart(rqp); 1270 error = mb_put_mem(mbp, pp, plen, MB_MSYSTEM); 1271 if (error) { 1272 SMBSDEBUG("error %d from mb_put_mem for pp\n", error); 1273 goto bad; 1274 } 1275 smb_put_dmem(mbp, vcp, "\\\\", 2, caseopt, NULL); 1276 pp = vcp->vc_srvname; 1277 error = smb_put_dmem(mbp, vcp, pp, strlen(pp), caseopt, NULL); 1278 if (error) { 1279 SMBSDEBUG("error %d from smb_put_dmem for srvname\n", error); 1280 goto bad; 1281 } 1282 smb_put_dmem(mbp, vcp, "\\", 1, caseopt, NULL); 1283 pp = ssp->ss_name; 1284 error = smb_put_dstring(mbp, vcp, pp, caseopt); 1285 if (error) { 1286 SMBSDEBUG("error %d from smb_put_dstring for ss_name\n", error); 1287 goto bad; 1288 } 1289 /* The type name is always ASCII */ 1290 pp = smb_share_typename(ssp->ss_type); 1291 error = mb_put_mem(mbp, pp, strlen(pp) + 1, MB_MSYSTEM); 1292 if (error) { 1293 SMBSDEBUG("error %d from mb_put_mem for ss_type\n", error); 1294 goto bad; 1295 } 1296 smb_rq_bend(rqp); 1297 /* 1298 * Don't want to risk missing a successful 1299 * tree connect response. 1300 */ 1301 rqp->sr_flags |= SMBR_NOINTR_RECV; 1302 error = smb_rq_simple(rqp); 1303 SMBSDEBUG("%d\n", error); 1304 if (error) 1305 goto bad; 1306 1307 /* Success! */ 1308 SMB_SS_LOCK(ssp); 1309 ssp->ss_tid = rqp->sr_rptid; 1310 ssp->ss_vcgenid = vcp->vc_genid; 1311 ssp->ss_flags |= SMBS_CONNECTED; 1312 SMB_SS_UNLOCK(ssp); 1313 1314 bad: 1315 if (encpass) 1316 kmem_free(encpass, 24); 1317 if (pbuf) 1318 kmem_free(pbuf, SMB_MAXPASSWORDLEN + 1); 1319 smb_rq_done(rqp); 1320 if (error && upper == 1) 1321 goto again; 1322 return (error); 1323 } 1324 1325 int 1326 smb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred) 1327 { 1328 struct smb_vc *vcp; 1329 struct smb_rq *rqp; 1330 struct mbchain *mbp; 1331 int error; 1332 1333 if (ssp->ss_tid == SMB_TID_UNKNOWN) 1334 return (0); 1335 1336 /* 1337 * Build this as a "VC-level" request, so it will 1338 * avoid testing the _GONE flag on the share, 1339 * which has already been set at this point. 1340 * Add the share pointer "by hand" below, so 1341 * smb_iod_sendrq will plug in the TID. 1342 */ 1343 vcp = SSTOVC(ssp); 1344 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_DISCONNECT, scred, &rqp); 1345 if (error) 1346 return (error); 1347 rqp->sr_share = ssp; /* by hand */ 1348 mbp = &rqp->sr_rq; 1349 #ifdef lint 1350 mbp = mbp; 1351 #endif 1352 smb_rq_wstart(rqp); 1353 smb_rq_wend(rqp); 1354 smb_rq_bstart(rqp); 1355 smb_rq_bend(rqp); 1356 1357 /* 1358 * Run this with a relatively short timeout. (5 sec.) 1359 * We don't really care about the result here, but we 1360 * do need to make sure we send this out, or we could 1361 * "leak" active tree IDs on interrupt or timeout. 1362 * The NOINTR_SEND flag makes this request immune to 1363 * interrupt or timeout until the send is done. 1364 */ 1365 rqp->sr_flags |= SMBR_NOINTR_SEND; 1366 error = smb_rq_simple_timed(rqp, 5); 1367 SMBSDEBUG("%d\n", error); 1368 smb_rq_done(rqp); 1369 ssp->ss_tid = SMB_TID_UNKNOWN; 1370 return (error); 1371 } 1372 1373 static int 1374 smb_smb_readx(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid, 1375 uio_t *uiop, struct smb_cred *scred, int timo) 1376 { 1377 struct smb_vc *vcp = SSTOVC(ssp); 1378 struct smb_rq *rqp; 1379 struct mbchain *mbp; 1380 struct mdchain *mdp; 1381 u_int8_t wc; 1382 int error; 1383 u_int16_t residhi, residlo, off, doff; 1384 u_int32_t resid; 1385 1386 if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX) == 0) { 1387 /* Fall back to the old cmd. */ 1388 return (smb_smb_read(ssp, fid, len, rresid, uiop, 1389 scred, timo)); 1390 } 1391 if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0) { 1392 /* Have ReadX but not large files? */ 1393 if ((uiop->uio_loffset + *len) > UINT32_MAX) 1394 return (EFBIG); 1395 } 1396 *len = min(*len, vcp->vc_rxmax); 1397 1398 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp); 1399 if (error) 1400 return (error); 1401 smb_rq_getrequest(rqp, &mbp); 1402 smb_rq_wstart(rqp); 1403 mb_put_uint8(mbp, 0xff); /* no secondary command */ 1404 mb_put_uint8(mbp, 0); /* MBZ */ 1405 mb_put_uint16le(mbp, 0); /* offset to secondary */ 1406 mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM); 1407 mb_put_uint32le(mbp, (u_int32_t)(uiop->uio_offset)); 1408 mb_put_uint16le(mbp, (u_int16_t)*len); /* MaxCount */ 1409 mb_put_uint16le(mbp, (u_int16_t)*len); /* MinCount */ 1410 /* (only indicates blocking) */ 1411 mb_put_uint32le(mbp, (unsigned)*len >> 16); /* MaxCountHigh */ 1412 mb_put_uint16le(mbp, (u_int16_t)*len); /* Remaining ("obsolete") */ 1413 mb_put_uint32le(mbp, (u_int32_t)((uiop->uio_loffset) >> 32)); 1414 smb_rq_wend(rqp); 1415 smb_rq_bstart(rqp); 1416 smb_rq_bend(rqp); 1417 do { 1418 if (timo == 0) 1419 timo = smb_timo_read; 1420 error = smb_rq_simple_timed(rqp, timo); 1421 if (error) 1422 break; 1423 smb_rq_getreply(rqp, &mdp); 1424 off = SMB_HDRLEN; 1425 md_get_uint8(mdp, &wc); 1426 off++; 1427 if (wc != 12) { 1428 error = EBADRPC; 1429 break; 1430 } 1431 md_get_uint8(mdp, NULL); 1432 off++; 1433 md_get_uint8(mdp, NULL); 1434 off++; 1435 md_get_uint16le(mdp, NULL); 1436 off += 2; 1437 md_get_uint16le(mdp, NULL); 1438 off += 2; 1439 md_get_uint16le(mdp, NULL); /* data compaction mode */ 1440 off += 2; 1441 md_get_uint16le(mdp, NULL); 1442 off += 2; 1443 md_get_uint16le(mdp, &residlo); 1444 off += 2; 1445 md_get_uint16le(mdp, &doff); /* data offset */ 1446 off += 2; 1447 md_get_uint16le(mdp, &residhi); 1448 off += 2; 1449 resid = (residhi << 16) | residlo; 1450 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); 1451 off += 4*2; 1452 md_get_uint16le(mdp, NULL); /* ByteCount */ 1453 off += 2; 1454 if (doff > off) /* pad byte(s)? */ 1455 md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM); 1456 if (resid == 0) { 1457 *rresid = resid; 1458 break; 1459 } 1460 error = md_get_uio(mdp, uiop, resid); 1461 if (error) 1462 break; 1463 *rresid = resid; 1464 /*LINTED*/ 1465 } while (0); 1466 smb_rq_done(rqp); 1467 return (error); 1468 } 1469 1470 static int 1471 smb_smb_writex(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid, 1472 uio_t *uiop, struct smb_cred *scred, int timo) 1473 { 1474 struct smb_vc *vcp = SSTOVC(ssp); 1475 struct smb_rq *rqp; 1476 struct mbchain *mbp; 1477 struct mdchain *mdp; 1478 int error; 1479 u_int8_t wc; 1480 u_int16_t resid; 1481 1482 if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX) == 0) { 1483 /* Fall back to the old cmd. */ 1484 return (smb_smb_write(ssp, fid, len, rresid, uiop, 1485 scred, timo)); 1486 } 1487 if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0) { 1488 /* Have WriteX but not large files? */ 1489 if ((uiop->uio_loffset + *len) > UINT32_MAX) 1490 return (EFBIG); 1491 } 1492 *len = min(*len, vcp->vc_wxmax); 1493 1494 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp); 1495 if (error) 1496 return (error); 1497 smb_rq_getrequest(rqp, &mbp); 1498 smb_rq_wstart(rqp); 1499 mb_put_uint8(mbp, 0xff); /* no secondary command */ 1500 mb_put_uint8(mbp, 0); /* MBZ */ 1501 mb_put_uint16le(mbp, 0); /* offset to secondary */ 1502 mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM); 1503 mb_put_uint32le(mbp, (u_int32_t)(uiop->uio_offset)); 1504 mb_put_uint32le(mbp, 0); /* MBZ (timeout) */ 1505 mb_put_uint16le(mbp, 0); /* !write-thru */ 1506 mb_put_uint16le(mbp, 0); 1507 mb_put_uint16le(mbp, (u_int16_t)((unsigned)*len >> 16)); 1508 mb_put_uint16le(mbp, (u_int16_t)*len); 1509 mb_put_uint16le(mbp, 64); /* data offset from header start */ 1510 mb_put_uint32le(mbp, (u_int32_t)((uiop->uio_loffset) >> 32)); 1511 smb_rq_wend(rqp); 1512 smb_rq_bstart(rqp); 1513 do { 1514 mb_put_uint8(mbp, 0xee); /* mimic xp pad byte! */ 1515 error = mb_put_uio(mbp, uiop, *len); 1516 if (error) 1517 break; 1518 smb_rq_bend(rqp); 1519 if (timo == 0) 1520 timo = smb_timo_write; 1521 error = smb_rq_simple_timed(rqp, timo); 1522 if (error) 1523 break; 1524 smb_rq_getreply(rqp, &mdp); 1525 md_get_uint8(mdp, &wc); 1526 if (wc != 6) { 1527 error = EBADRPC; 1528 break; 1529 } 1530 md_get_uint8(mdp, NULL); 1531 md_get_uint8(mdp, NULL); 1532 md_get_uint16le(mdp, NULL); 1533 md_get_uint16le(mdp, &resid); /* actually is # written */ 1534 *rresid = resid; 1535 /* 1536 * if LARGE_WRITEX then there's one more bit of # written 1537 */ 1538 if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)) { 1539 md_get_uint16le(mdp, NULL); 1540 md_get_uint16le(mdp, &resid); 1541 *rresid |= (int)(resid & 1) << 16; 1542 } 1543 /*LINTED*/ 1544 } while (0); 1545 1546 smb_rq_done(rqp); 1547 return (error); 1548 } 1549 1550 static int 1551 smb_smb_read(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid, 1552 uio_t *uiop, struct smb_cred *scred, int timo) 1553 { 1554 struct smb_rq *rqp; 1555 struct mbchain *mbp; 1556 struct mdchain *mdp; 1557 u_int16_t resid, bc; 1558 u_int8_t wc; 1559 int error, rlen; 1560 1561 /* This cmd is limited to 32-bit offsets. */ 1562 if ((uiop->uio_loffset + *len) > UINT32_MAX) 1563 return (EFBIG); 1564 *len = rlen = min(*len, SSTOVC(ssp)->vc_rxmax); 1565 1566 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp); 1567 if (error) 1568 return (error); 1569 smb_rq_getrequest(rqp, &mbp); 1570 smb_rq_wstart(rqp); 1571 mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM); 1572 mb_put_uint16le(mbp, (u_int16_t)rlen); 1573 mb_put_uint32le(mbp, (u_int32_t)uiop->uio_offset); 1574 mb_put_uint16le(mbp, (u_int16_t)min(uiop->uio_resid, 0xffff)); 1575 smb_rq_wend(rqp); 1576 smb_rq_bstart(rqp); 1577 smb_rq_bend(rqp); 1578 do { 1579 if (timo == 0) 1580 timo = smb_timo_read; 1581 error = smb_rq_simple_timed(rqp, timo); 1582 if (error) 1583 break; 1584 smb_rq_getreply(rqp, &mdp); 1585 md_get_uint8(mdp, &wc); 1586 if (wc != 5) { 1587 error = EBADRPC; 1588 break; 1589 } 1590 md_get_uint16le(mdp, &resid); 1591 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); 1592 md_get_uint16le(mdp, &bc); 1593 md_get_uint8(mdp, NULL); /* ignore buffer type */ 1594 md_get_uint16le(mdp, &resid); 1595 if (resid == 0) { 1596 *rresid = resid; 1597 break; 1598 } 1599 error = md_get_uio(mdp, uiop, resid); 1600 if (error) 1601 break; 1602 *rresid = resid; 1603 /*LINTED*/ 1604 } while (0); 1605 smb_rq_done(rqp); 1606 return (error); 1607 } 1608 1609 static int 1610 smb_smb_write(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid, 1611 uio_t *uiop, struct smb_cred *scred, int timo) 1612 { 1613 struct smb_rq *rqp; 1614 struct mbchain *mbp; 1615 struct mdchain *mdp; 1616 u_int16_t resid; 1617 u_int8_t wc; 1618 int error; 1619 1620 /* This cmd is limited to 32-bit offsets. */ 1621 if ((uiop->uio_loffset + *len) > UINT32_MAX) 1622 return (EFBIG); 1623 *len = resid = min(*len, SSTOVC(ssp)->vc_wxmax); 1624 1625 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); 1626 if (error) 1627 return (error); 1628 smb_rq_getrequest(rqp, &mbp); 1629 smb_rq_wstart(rqp); 1630 mb_put_mem(mbp, (caddr_t)&fid, sizeof (fid), MB_MSYSTEM); 1631 mb_put_uint16le(mbp, resid); 1632 mb_put_uint32le(mbp, (u_int32_t)uiop->uio_offset); 1633 mb_put_uint16le(mbp, (u_int16_t)min(uiop->uio_resid, 0xffff)); 1634 smb_rq_wend(rqp); 1635 smb_rq_bstart(rqp); 1636 mb_put_uint8(mbp, SMB_DT_DATA); 1637 mb_put_uint16le(mbp, resid); 1638 do { 1639 error = mb_put_uio(mbp, uiop, resid); 1640 if (error) 1641 break; 1642 smb_rq_bend(rqp); 1643 if (timo == 0) 1644 timo = smb_timo_write; 1645 error = smb_rq_simple_timed(rqp, timo); 1646 if (error) 1647 break; 1648 smb_rq_getreply(rqp, &mdp); 1649 md_get_uint8(mdp, &wc); 1650 if (wc != 1) { 1651 error = EBADRPC; 1652 break; 1653 } 1654 md_get_uint16le(mdp, &resid); 1655 *rresid = resid; 1656 /*LINTED*/ 1657 } while (0); 1658 smb_rq_done(rqp); 1659 return (error); 1660 } 1661 1662 /* 1663 * Common function for read/write with UIO. 1664 * Called by netsmb smb_usr_rw, 1665 * smbfs_readvnode, smbfs_writevnode 1666 */ 1667 int 1668 smb_rwuio(struct smb_share *ssp, u_int16_t fid, uio_rw_t rw, 1669 uio_t *uiop, struct smb_cred *scred, int timo) 1670 { 1671 ssize_t old_resid, tsize; 1672 offset_t old_offset; 1673 int len, resid; 1674 int error = 0; 1675 1676 old_offset = uiop->uio_loffset; 1677 old_resid = tsize = uiop->uio_resid; 1678 1679 while (tsize > 0) { 1680 /* Lint: tsize may be 64-bits */ 1681 len = SMB_MAX_LARGE_RW_SIZE; 1682 if (len > tsize) 1683 len = (int)tsize; 1684 1685 if (rw == UIO_READ) 1686 error = smb_smb_readx(ssp, fid, &len, &resid, uiop, 1687 scred, timo); 1688 else 1689 error = smb_smb_writex(ssp, fid, &len, &resid, uiop, 1690 scred, timo); 1691 if (error) 1692 break; 1693 1694 if (resid < len) { 1695 error = EIO; 1696 break; 1697 } 1698 1699 tsize -= resid; 1700 timo = 0; /* only first write is special */ 1701 } 1702 1703 if (error) { 1704 /* 1705 * Errors can happen in copyin/copyout, the rpc, etc. so 1706 * they imply resid is unreliable. The only safe thing is 1707 * to pretend zero bytes made it. We needn't restore the 1708 * iovs because callers don't depend on them in error 1709 * paths - uio_resid and uio_offset are what matter. 1710 */ 1711 uiop->uio_loffset = old_offset; 1712 uiop->uio_resid = old_resid; 1713 } 1714 1715 return (error); 1716 } 1717 1718 1719 static u_int32_t smbechoes = 0; 1720 1721 int 1722 smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo) 1723 { 1724 struct smb_rq *rqp; 1725 struct mbchain *mbp; 1726 int error; 1727 1728 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp); 1729 if (error) 1730 return (error); 1731 mbp = &rqp->sr_rq; 1732 smb_rq_wstart(rqp); 1733 mb_put_uint16le(mbp, 1); /* echo count */ 1734 smb_rq_wend(rqp); 1735 smb_rq_bstart(rqp); 1736 mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes)); 1737 smb_rq_bend(rqp); 1738 /* 1739 * Note: the IOD calls this, so 1740 * this request must not wait for 1741 * connection state changes, etc. 1742 */ 1743 rqp->sr_flags |= SMBR_INTERNAL; 1744 error = smb_rq_simple_timed(rqp, timo); 1745 SMBSDEBUG("%d\n", error); 1746 smb_rq_done(rqp); 1747 return (error); 1748 } 1749 1750 #ifdef APPLE 1751 int 1752 smb_smb_checkdir(struct smb_share *ssp, void *dnp, char *name, 1753 int nmlen, struct smb_cred *scred) 1754 { 1755 struct smb_rq *rqp; 1756 struct mbchain *mbp; 1757 int error; 1758 1759 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CHECK_DIRECTORY, scred, &rqp); 1760 if (error) 1761 return (error); 1762 1763 smb_rq_getrequest(rqp, &mbp); 1764 smb_rq_wstart(rqp); 1765 smb_rq_wend(rqp); 1766 smb_rq_bstart(rqp); 1767 mb_put_uint8(mbp, SMB_DT_ASCII); 1768 /* 1769 * All we need to do is marshall the path: "\\" 1770 * (the root of the share) into this request. 1771 * We essentially in-line smbfs_fullpath() here, 1772 * except no mb_put_padbyte (already aligned). 1773 */ 1774 smb_put_dstring(mbp, SSTOVC(ssp), "\\", SMB_CS_NONE); 1775 smb_rq_bend(rqp); 1776 1777 error = smb_rq_simple(rqp); 1778 SMBSDEBUG("%d\n", error); 1779 smb_rq_done(rqp); 1780 1781 return (error); 1782 } 1783 #endif /* APPLE */ 1784