1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2000-2001 Boris Popov 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * various SMB requests. Most of the routines merely packs data into mbufs. 31 */ 32 33 #include <sys/cdefs.h> 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/malloc.h> 38 #include <sys/proc.h> 39 #include <sys/lock.h> 40 #include <sys/sysctl.h> 41 #include <sys/socket.h> 42 #include <sys/uio.h> 43 44 #include <sys/iconv.h> 45 46 #include <netsmb/smb.h> 47 #include <netsmb/smb_subr.h> 48 #include <netsmb/smb_rq.h> 49 #include <netsmb/smb_conn.h> 50 #include <netsmb/smb_tran.h> 51 52 #include "opt_netsmb.h" 53 54 struct smb_dialect { 55 int d_id; 56 const char * d_name; 57 }; 58 59 static struct smb_dialect smb_dialects[] = { 60 {SMB_DIALECT_CORE, "PC NETWORK PROGRAM 1.0"}, 61 {SMB_DIALECT_COREPLUS, "MICROSOFT NETWORKS 1.03"}, 62 {SMB_DIALECT_LANMAN1_0, "MICROSOFT NETWORKS 3.0"}, 63 {SMB_DIALECT_LANMAN1_0, "LANMAN1.0"}, 64 {SMB_DIALECT_LANMAN2_0, "LM1.2X002"}, 65 {SMB_DIALECT_LANMAN2_0, "Samba"}, 66 {SMB_DIALECT_NTLM0_12, "NT LANMAN 1.0"}, 67 {SMB_DIALECT_NTLM0_12, "NT LM 0.12"}, 68 {-1, NULL} 69 }; 70 71 static u_int32_t 72 smb_vc_maxread(struct smb_vc *vcp) 73 { 74 /* 75 * Specs say up to 64k data bytes, but Windows traffic 76 * uses 60k... no doubt for some good reason. 77 * 78 * Don't exceed the server's buffer size if signatures 79 * are enabled otherwise Windows 2003 chokes. Allow space 80 * for the SMB header & a little bit extra. 81 */ 82 if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX) && 83 (vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) == 0) 84 return (60*1024); 85 else 86 return (vcp->vc_sopt.sv_maxtx - SMB_HDRLEN - 64); 87 } 88 89 static u_int32_t 90 smb_vc_maxwrite(struct smb_vc *vcp) 91 { 92 /* 93 * See comment above. 94 */ 95 if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX) && 96 (vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) == 0) 97 return (60*1024); 98 else 99 return (vcp->vc_sopt.sv_maxtx - SMB_HDRLEN - 64); 100 } 101 102 static int 103 smb_smb_nomux(struct smb_vc *vcp, struct smb_cred *scred, const char *name) 104 { 105 if (scred->scr_td->td_proc == vcp->vc_iod->iod_p) 106 return 0; 107 SMBERROR("wrong function called(%s)\n", name); 108 return EINVAL; 109 } 110 111 int 112 smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred) 113 { 114 struct smb_dialect *dp; 115 struct smb_sopt *sp = NULL; 116 struct smb_rq *rqp; 117 struct mbchain *mbp; 118 struct mdchain *mdp; 119 u_int8_t wc, stime[8], sblen; 120 u_int16_t dindex, tw, tw1, swlen, bc; 121 int error, maxqsz; 122 int unicode = SMB_UNICODE_STRINGS(vcp); 123 void * servercharset = vcp->vc_toserver; 124 void * localcharset = vcp->vc_tolocal; 125 126 if (smb_smb_nomux(vcp, scred, __func__) != 0) 127 return EINVAL; 128 /* Disable Unicode for SMB_COM_NEGOTIATE requests */ 129 if (unicode) { 130 vcp->vc_toserver = vcp->vc_cp_toserver; 131 vcp->vc_tolocal = vcp->vc_cp_tolocal; 132 } 133 vcp->vc_hflags = 0; 134 vcp->vc_hflags2 = 0; 135 vcp->obj.co_flags &= ~(SMBV_ENCRYPT); 136 sp = &vcp->vc_sopt; 137 bzero(sp, sizeof(struct smb_sopt)); 138 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_NEGOTIATE, scred, &rqp); 139 if (error) 140 return error; 141 smb_rq_getrequest(rqp, &mbp); 142 smb_rq_wstart(rqp); 143 smb_rq_wend(rqp); 144 smb_rq_bstart(rqp); 145 for(dp = smb_dialects; dp->d_id != -1; dp++) { 146 mb_put_uint8(mbp, SMB_DT_DIALECT); 147 smb_put_dstring(mbp, vcp, dp->d_name, SMB_CS_NONE); 148 } 149 smb_rq_bend(rqp); 150 error = smb_rq_simple(rqp); 151 SMBSDEBUG("%d\n", error); 152 if (error) 153 goto bad; 154 smb_rq_getreply(rqp, &mdp); 155 do { 156 error = md_get_uint8(mdp, &wc); 157 if (error) 158 break; 159 error = md_get_uint16le(mdp, &dindex); 160 if (error) 161 break; 162 if (dindex > 7) { 163 SMBERROR("Don't know how to talk with server %s (%d)\n", "xxx", dindex); 164 error = EBADRPC; 165 break; 166 } 167 dp = smb_dialects + dindex; 168 sp->sv_proto = dp->d_id; 169 SMBSDEBUG("Dialect %s (%d, %d)\n", dp->d_name, dindex, wc); 170 error = EBADRPC; 171 if (dp->d_id >= SMB_DIALECT_NTLM0_12) { 172 if (wc != 17) 173 break; 174 md_get_uint8(mdp, &sp->sv_sm); 175 md_get_uint16le(mdp, &sp->sv_maxmux); 176 md_get_uint16le(mdp, &sp->sv_maxvcs); 177 md_get_uint32le(mdp, &sp->sv_maxtx); 178 md_get_uint32le(mdp, &sp->sv_maxraw); 179 md_get_uint32le(mdp, &sp->sv_skey); 180 md_get_uint32le(mdp, &sp->sv_caps); 181 md_get_mem(mdp, stime, 8, MB_MSYSTEM); 182 md_get_uint16le(mdp, (u_int16_t*)&sp->sv_tz); 183 md_get_uint8(mdp, &sblen); 184 if (sblen && (sp->sv_sm & SMB_SM_ENCRYPT)) { 185 if (sblen != SMB_MAXCHALLENGELEN) { 186 SMBERROR("Unexpected length of security blob (%d)\n", sblen); 187 break; 188 } 189 error = md_get_uint16le(mdp, &bc); 190 if (error) 191 break; 192 if (sp->sv_caps & SMB_CAP_EXT_SECURITY) 193 md_get_mem(mdp, NULL, 16, MB_MSYSTEM); 194 error = md_get_mem(mdp, vcp->vc_ch, sblen, MB_MSYSTEM); 195 if (error) 196 break; 197 vcp->vc_chlen = sblen; 198 vcp->obj.co_flags |= SMBV_ENCRYPT; 199 } 200 if (sp->sv_sm & SMB_SM_SIGS_REQUIRE) 201 vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE; 202 if (vcp->vc_ucs_toserver && 203 sp->sv_caps & SMB_CAP_UNICODE) { 204 /* 205 * They do Unicode. 206 */ 207 vcp->obj.co_flags |= SMBV_UNICODE; 208 } 209 vcp->vc_hflags2 |= SMB_FLAGS2_KNOWS_LONG_NAMES; 210 if (dp->d_id == SMB_DIALECT_NTLM0_12 && 211 sp->sv_maxtx < 4096 && 212 (sp->sv_caps & SMB_CAP_NT_SMBS) == 0) { 213 vcp->obj.co_flags |= SMBV_WIN95; 214 SMBSDEBUG("Win95 detected\n"); 215 } 216 error = 0; 217 break; 218 } 219 vcp->vc_hflags2 &= ~(SMB_FLAGS2_EXT_SEC|SMB_FLAGS2_DFS| 220 SMB_FLAGS2_ERR_STATUS|SMB_FLAGS2_UNICODE); 221 unicode = 0; 222 if (dp->d_id > SMB_DIALECT_CORE) { 223 md_get_uint16le(mdp, &tw); 224 sp->sv_sm = tw; 225 md_get_uint16le(mdp, &tw); 226 sp->sv_maxtx = tw; 227 md_get_uint16le(mdp, &sp->sv_maxmux); 228 md_get_uint16le(mdp, &sp->sv_maxvcs); 229 md_get_uint16le(mdp, &tw); /* rawmode */ 230 md_get_uint32le(mdp, &sp->sv_skey); 231 if (wc == 13) { /* >= LANMAN1 */ 232 md_get_uint16(mdp, &tw); /* time */ 233 md_get_uint16(mdp, &tw1); /* date */ 234 md_get_uint16le(mdp, (u_int16_t*)&sp->sv_tz); 235 md_get_uint16le(mdp, &swlen); 236 if (swlen > SMB_MAXCHALLENGELEN) 237 break; 238 md_get_uint16(mdp, NULL); /* mbz */ 239 if (md_get_uint16le(mdp, &bc) != 0) 240 break; 241 if (bc < swlen) 242 break; 243 if (swlen && (sp->sv_sm & SMB_SM_ENCRYPT)) { 244 error = md_get_mem(mdp, vcp->vc_ch, swlen, MB_MSYSTEM); 245 if (error) 246 break; 247 vcp->vc_chlen = swlen; 248 vcp->obj.co_flags |= SMBV_ENCRYPT; 249 } 250 } 251 vcp->vc_hflags2 |= SMB_FLAGS2_KNOWS_LONG_NAMES; 252 } else { /* an old CORE protocol */ 253 sp->sv_maxmux = 1; 254 } 255 error = 0; 256 } while (0); 257 if (error == 0) { 258 vcp->vc_maxvcs = sp->sv_maxvcs; 259 if (vcp->vc_maxvcs <= 1) { 260 if (vcp->vc_maxvcs == 0) 261 vcp->vc_maxvcs = 1; 262 } 263 if (sp->sv_maxtx <= 0 || sp->sv_maxtx > 0xffff) 264 sp->sv_maxtx = 1024; 265 else 266 sp->sv_maxtx = min(sp->sv_maxtx, 267 63*1024 + SMB_HDRLEN + 16); 268 SMB_TRAN_GETPARAM(vcp, SMBTP_RCVSZ, &maxqsz); 269 vcp->vc_rxmax = min(smb_vc_maxread(vcp), maxqsz - 1024); 270 SMB_TRAN_GETPARAM(vcp, SMBTP_SNDSZ, &maxqsz); 271 vcp->vc_wxmax = min(smb_vc_maxwrite(vcp), maxqsz - 1024); 272 vcp->vc_txmax = min(sp->sv_maxtx, maxqsz); 273 SMBSDEBUG("TZ = %d\n", sp->sv_tz); 274 SMBSDEBUG("CAPS = %x\n", sp->sv_caps); 275 SMBSDEBUG("MAXMUX = %d\n", sp->sv_maxmux); 276 SMBSDEBUG("MAXVCS = %d\n", sp->sv_maxvcs); 277 SMBSDEBUG("MAXRAW = %d\n", sp->sv_maxraw); 278 SMBSDEBUG("MAXTX = %d\n", sp->sv_maxtx); 279 } 280 bad: 281 /* Restore Unicode conversion state */ 282 if (unicode) { 283 vcp->vc_toserver = servercharset; 284 vcp->vc_tolocal = localcharset; 285 vcp->vc_hflags2 |= SMB_FLAGS2_UNICODE; 286 } 287 smb_rq_done(rqp); 288 return error; 289 } 290 291 int 292 smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred) 293 { 294 struct smb_rq *rqp; 295 struct mbchain *mbp; 296 /* u_int8_t wc; 297 u_int16_t tw, tw1;*/ 298 smb_uniptr unipp, ntencpass = NULL; 299 char *pp, *up, *pbuf, *encpass; 300 int error, plen, uniplen, ulen, upper; 301 u_int32_t caps = 0; 302 303 upper = 0; 304 305 if (vcp->obj.co_flags & SMBV_UNICODE) 306 caps |= SMB_CAP_UNICODE; 307 308 again: 309 310 vcp->vc_smbuid = SMB_UID_UNKNOWN; 311 312 if (smb_smb_nomux(vcp, scred, __func__) != 0) 313 return EINVAL; 314 315 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX, scred, &rqp); 316 if (error) 317 return error; 318 pbuf = malloc(SMB_MAXPASSWORDLEN + 1, M_SMBTEMP, M_WAITOK); 319 encpass = malloc(24, M_SMBTEMP, M_WAITOK); 320 if (vcp->vc_sopt.sv_sm & SMB_SM_USER) { 321 /* 322 * We try w/o uppercasing first so Samba mixed case 323 * passwords work. If that fails we come back and try 324 * uppercasing to satisfy OS/2 and Windows for Workgroups. 325 */ 326 if (upper++) { 327 iconv_convstr(vcp->vc_toupper, pbuf, 328 smb_vc_getpass(vcp)/*, SMB_MAXPASSWORDLEN*/); 329 } else { 330 strncpy(pbuf, smb_vc_getpass(vcp), SMB_MAXPASSWORDLEN); 331 pbuf[SMB_MAXPASSWORDLEN] = '\0'; 332 } 333 if (!SMB_UNICODE_STRINGS(vcp)) 334 iconv_convstr(vcp->vc_toserver, pbuf, pbuf/*, 335 SMB_MAXPASSWORDLEN*/); 336 337 if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) { 338 uniplen = plen = 24; 339 smb_encrypt(pbuf, vcp->vc_ch, encpass); 340 ntencpass = malloc(uniplen, M_SMBTEMP, M_WAITOK); 341 if (SMB_UNICODE_STRINGS(vcp)) { 342 strncpy(pbuf, smb_vc_getpass(vcp), 343 SMB_MAXPASSWORDLEN); 344 pbuf[SMB_MAXPASSWORDLEN] = '\0'; 345 } else 346 iconv_convstr(vcp->vc_toserver, pbuf, 347 smb_vc_getpass(vcp)/*, 348 SMB_MAXPASSWORDLEN*/); 349 smb_ntencrypt(pbuf, vcp->vc_ch, (u_char*)ntencpass); 350 pp = encpass; 351 unipp = ntencpass; 352 } else { 353 plen = strlen(pbuf) + 1; 354 pp = pbuf; 355 uniplen = plen * 2; 356 ntencpass = malloc(uniplen, M_SMBTEMP, M_WAITOK); 357 smb_strtouni(ntencpass, smb_vc_getpass(vcp)); 358 plen--; 359 360 /* 361 * The uniplen is zeroed because Samba cannot deal 362 * with this 2nd cleartext password. This Samba 363 * "bug" is actually a workaround for problems in 364 * Microsoft clients. 365 */ 366 uniplen = 0/*-= 2*/; 367 unipp = ntencpass; 368 } 369 } else { 370 /* 371 * In the share security mode password will be used 372 * only in the tree authentication 373 */ 374 pp = ""; 375 plen = 1; 376 unipp = &smb_unieol; 377 uniplen = 0 /* sizeof(smb_unieol) */; 378 } 379 smb_rq_wstart(rqp); 380 mbp = &rqp->sr_rq; 381 up = vcp->vc_username; 382 ulen = strlen(up) + 1; 383 /* 384 * If userid is null we are attempting anonymous browse login 385 * so passwords must be zero length. 386 */ 387 if (ulen == 1) 388 plen = uniplen = 0; 389 mb_put_uint8(mbp, 0xff); 390 mb_put_uint8(mbp, 0); 391 mb_put_uint16le(mbp, 0); 392 mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxtx); 393 mb_put_uint16le(mbp, vcp->vc_sopt.sv_maxmux); 394 mb_put_uint16le(mbp, vcp->vc_number); 395 mb_put_uint32le(mbp, vcp->vc_sopt.sv_skey); 396 mb_put_uint16le(mbp, plen); 397 if (SMB_DIALECT(vcp) < SMB_DIALECT_NTLM0_12) { 398 mb_put_uint32le(mbp, 0); 399 smb_rq_wend(rqp); 400 smb_rq_bstart(rqp); 401 mb_put_mem(mbp, pp, plen, MB_MSYSTEM); 402 smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); 403 } else { 404 mb_put_uint16le(mbp, uniplen); 405 mb_put_uint32le(mbp, 0); /* reserved */ 406 mb_put_uint32le(mbp, caps); 407 smb_rq_wend(rqp); 408 smb_rq_bstart(rqp); 409 mb_put_mem(mbp, pp, plen, MB_MSYSTEM); 410 mb_put_mem(mbp, (caddr_t)unipp, uniplen, MB_MSYSTEM); 411 smb_put_dstring(mbp, vcp, up, SMB_CS_NONE); /* AccountName */ 412 smb_put_dstring(mbp, vcp, vcp->vc_domain, SMB_CS_NONE); /* PrimaryDomain */ 413 smb_put_dstring(mbp, vcp, "FreeBSD", SMB_CS_NONE); /* Client's OS */ 414 smb_put_dstring(mbp, vcp, "NETSMB", SMB_CS_NONE); /* Client name */ 415 } 416 smb_rq_bend(rqp); 417 if (ntencpass) 418 free(ntencpass, M_SMBTEMP); 419 if (vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) 420 smb_calcmackey(vcp); 421 error = smb_rq_simple(rqp); 422 SMBSDEBUG("%d\n", error); 423 if (error) { 424 if (rqp->sr_errclass == ERRDOS && rqp->sr_serror == ERRnoaccess) 425 error = EAUTH; 426 goto bad; 427 } 428 vcp->vc_smbuid = rqp->sr_rpuid; 429 bad: 430 free(encpass, M_SMBTEMP); 431 free(pbuf, M_SMBTEMP); 432 smb_rq_done(rqp); 433 if (error && upper == 1 && vcp->vc_sopt.sv_sm & SMB_SM_USER) 434 goto again; 435 return error; 436 } 437 438 int 439 smb_smb_ssnclose(struct smb_vc *vcp, struct smb_cred *scred) 440 { 441 struct smb_rq *rqp; 442 struct mbchain *mbp; 443 int error; 444 445 if (vcp->vc_smbuid == SMB_UID_UNKNOWN) 446 return 0; 447 448 if (smb_smb_nomux(vcp, scred, __func__) != 0) 449 return EINVAL; 450 451 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp); 452 if (error) 453 return error; 454 mbp = &rqp->sr_rq; 455 smb_rq_wstart(rqp); 456 mb_put_uint8(mbp, 0xff); 457 mb_put_uint8(mbp, 0); 458 mb_put_uint16le(mbp, 0); 459 smb_rq_wend(rqp); 460 smb_rq_bstart(rqp); 461 smb_rq_bend(rqp); 462 error = smb_rq_simple(rqp); 463 SMBSDEBUG("%d\n", error); 464 smb_rq_done(rqp); 465 return error; 466 } 467 468 static char smb_any_share[] = "?????"; 469 470 static char * 471 smb_share_typename(int stype) 472 { 473 char *pp; 474 475 switch (stype) { 476 case SMB_ST_DISK: 477 pp = "A:"; 478 break; 479 case SMB_ST_PRINTER: 480 pp = smb_any_share; /* can't use LPT: here... */ 481 break; 482 case SMB_ST_PIPE: 483 pp = "IPC"; 484 break; 485 case SMB_ST_COMM: 486 pp = "COMM"; 487 break; 488 case SMB_ST_ANY: 489 default: 490 pp = smb_any_share; 491 break; 492 } 493 return pp; 494 } 495 496 int 497 smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred) 498 { 499 struct smb_vc *vcp; 500 struct smb_rq rq, *rqp = &rq; 501 struct mbchain *mbp; 502 char *pp, *pbuf, *encpass; 503 int error, plen, caseopt, upper; 504 505 upper = 0; 506 507 again: 508 /* Disable Unicode for SMB_COM_TREE_CONNECT_ANDX requests */ 509 if (SSTOVC(ssp)->vc_hflags2 & SMB_FLAGS2_UNICODE) { 510 vcp = SSTOVC(ssp); 511 vcp->vc_toserver = vcp->vc_cp_toserver; 512 vcp->vc_tolocal = vcp->vc_cp_tolocal; 513 vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE; 514 } 515 516 ssp->ss_tid = SMB_TID_UNKNOWN; 517 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_TREE_CONNECT_ANDX, scred, &rqp); 518 if (error) 519 return error; 520 vcp = rqp->sr_vc; 521 caseopt = SMB_CS_NONE; 522 if (vcp->vc_sopt.sv_sm & SMB_SM_USER) { 523 plen = 1; 524 pp = ""; 525 pbuf = NULL; 526 encpass = NULL; 527 } else { 528 pbuf = malloc(SMB_MAXPASSWORDLEN + 1, M_SMBTEMP, M_WAITOK); 529 encpass = malloc(24, M_SMBTEMP, M_WAITOK); 530 /* 531 * We try w/o uppercasing first so Samba mixed case 532 * passwords work. If that fails we come back and try 533 * uppercasing to satisfy OS/2 and Windows for Workgroups. 534 */ 535 if (upper++) { 536 iconv_convstr(vcp->vc_toupper, pbuf, 537 smb_share_getpass(ssp)/*, 538 SMB_MAXPASSWORDLEN*/); 539 } else { 540 strncpy(pbuf, smb_share_getpass(ssp), 541 SMB_MAXPASSWORDLEN); 542 pbuf[SMB_MAXPASSWORDLEN] = '\0'; 543 } 544 if (vcp->vc_sopt.sv_sm & SMB_SM_ENCRYPT) { 545 plen = 24; 546 smb_encrypt(pbuf, vcp->vc_ch, encpass); 547 pp = encpass; 548 } else { 549 plen = strlen(pbuf) + 1; 550 pp = pbuf; 551 } 552 } 553 mbp = &rqp->sr_rq; 554 smb_rq_wstart(rqp); 555 mb_put_uint8(mbp, 0xff); 556 mb_put_uint8(mbp, 0); 557 mb_put_uint16le(mbp, 0); 558 mb_put_uint16le(mbp, 0); /* Flags */ 559 mb_put_uint16le(mbp, plen); 560 smb_rq_wend(rqp); 561 smb_rq_bstart(rqp); 562 mb_put_mem(mbp, pp, plen, MB_MSYSTEM); 563 smb_put_dmem(mbp, vcp, "\\\\", 2, caseopt); 564 pp = vcp->vc_srvname; 565 smb_put_dmem(mbp, vcp, pp, strlen(pp), caseopt); 566 smb_put_dmem(mbp, vcp, "\\", 1, caseopt); 567 pp = ssp->ss_name; 568 smb_put_dstring(mbp, vcp, pp, caseopt); 569 pp = smb_share_typename(ssp->ss_type); 570 smb_put_dstring(mbp, vcp, pp, caseopt); 571 smb_rq_bend(rqp); 572 error = smb_rq_simple(rqp); 573 SMBSDEBUG("%d\n", error); 574 if (error) 575 goto bad; 576 ssp->ss_tid = rqp->sr_rptid; 577 ssp->ss_vcgenid = vcp->vc_genid; 578 ssp->ss_flags |= SMBS_CONNECTED; 579 /* 580 * If the server can speak Unicode then switch 581 * our converters to do Unicode <--> Local 582 */ 583 if (vcp->obj.co_flags & SMBV_UNICODE) { 584 vcp->vc_toserver = vcp->vc_ucs_toserver; 585 vcp->vc_tolocal = vcp->vc_ucs_tolocal; 586 vcp->vc_hflags2 |= SMB_FLAGS2_UNICODE; 587 } 588 bad: 589 if (encpass) 590 free(encpass, M_SMBTEMP); 591 if (pbuf) 592 free(pbuf, M_SMBTEMP); 593 smb_rq_done(rqp); 594 if (error && upper == 1) 595 goto again; 596 return error; 597 } 598 599 int 600 smb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred) 601 { 602 struct smb_rq *rqp; 603 int error; 604 605 if (ssp->ss_tid == SMB_TID_UNKNOWN) 606 return 0; 607 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_TREE_DISCONNECT, scred, &rqp); 608 if (error) 609 return error; 610 smb_rq_wstart(rqp); 611 smb_rq_wend(rqp); 612 smb_rq_bstart(rqp); 613 smb_rq_bend(rqp); 614 error = smb_rq_simple(rqp); 615 SMBSDEBUG("%d\n", error); 616 smb_rq_done(rqp); 617 ssp->ss_tid = SMB_TID_UNKNOWN; 618 return error; 619 } 620 621 static __inline int 622 smb_smb_readx(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid, 623 struct uio *uio, struct smb_cred *scred) 624 { 625 struct smb_rq *rqp; 626 struct mbchain *mbp; 627 struct mdchain *mdp; 628 u_int8_t wc; 629 int error; 630 u_int16_t residhi, residlo, off, doff; 631 u_int32_t resid; 632 633 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp); 634 if (error) 635 return error; 636 smb_rq_getrequest(rqp, &mbp); 637 smb_rq_wstart(rqp); 638 mb_put_uint8(mbp, 0xff); /* no secondary command */ 639 mb_put_uint8(mbp, 0); /* MBZ */ 640 mb_put_uint16le(mbp, 0); /* offset to secondary */ 641 mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM); 642 mb_put_uint32le(mbp, uio->uio_offset); 643 *len = min(SSTOVC(ssp)->vc_rxmax, *len); 644 mb_put_uint16le(mbp, *len); /* MaxCount */ 645 mb_put_uint16le(mbp, *len); /* MinCount (only indicates blocking) */ 646 mb_put_uint32le(mbp, (unsigned)*len >> 16); /* MaxCountHigh */ 647 mb_put_uint16le(mbp, *len); /* Remaining ("obsolete") */ 648 mb_put_uint32le(mbp, uio->uio_offset >> 32); /* OffsetHigh */ 649 smb_rq_wend(rqp); 650 smb_rq_bstart(rqp); 651 smb_rq_bend(rqp); 652 do { 653 error = smb_rq_simple(rqp); 654 if (error) 655 break; 656 smb_rq_getreply(rqp, &mdp); 657 off = SMB_HDRLEN; 658 md_get_uint8(mdp, &wc); 659 off++; 660 if (wc != 12) { 661 error = EBADRPC; 662 break; 663 } 664 md_get_uint8(mdp, NULL); 665 off++; 666 md_get_uint8(mdp, NULL); 667 off++; 668 md_get_uint16le(mdp, NULL); 669 off += 2; 670 md_get_uint16le(mdp, NULL); 671 off += 2; 672 md_get_uint16le(mdp, NULL); /* data compaction mode */ 673 off += 2; 674 md_get_uint16le(mdp, NULL); 675 off += 2; 676 md_get_uint16le(mdp, &residlo); 677 off += 2; 678 md_get_uint16le(mdp, &doff); /* data offset */ 679 off += 2; 680 md_get_uint16le(mdp, &residhi); 681 off += 2; 682 resid = (residhi << 16) | residlo; 683 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); 684 off += 4*2; 685 md_get_uint16le(mdp, NULL); /* ByteCount */ 686 off += 2; 687 if (doff > off) /* pad byte(s)? */ 688 md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM); 689 if (resid == 0) { 690 *rresid = resid; 691 break; 692 } 693 error = md_get_uio(mdp, uio, resid); 694 if (error) 695 break; 696 *rresid = resid; 697 } while(0); 698 smb_rq_done(rqp); 699 return (error); 700 } 701 702 static __inline int 703 smb_smb_writex(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid, 704 struct uio *uio, struct smb_cred *scred) 705 { 706 struct smb_rq *rqp; 707 struct mbchain *mbp; 708 struct mdchain *mdp; 709 int error; 710 u_int8_t wc; 711 u_int16_t resid; 712 713 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp); 714 if (error) 715 return (error); 716 smb_rq_getrequest(rqp, &mbp); 717 smb_rq_wstart(rqp); 718 mb_put_uint8(mbp, 0xff); /* no secondary command */ 719 mb_put_uint8(mbp, 0); /* MBZ */ 720 mb_put_uint16le(mbp, 0); /* offset to secondary */ 721 mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM); 722 mb_put_uint32le(mbp, uio->uio_offset); 723 mb_put_uint32le(mbp, 0); /* MBZ (timeout) */ 724 mb_put_uint16le(mbp, 0); /* !write-thru */ 725 mb_put_uint16le(mbp, 0); 726 *len = min(SSTOVC(ssp)->vc_wxmax, *len); 727 mb_put_uint16le(mbp, (unsigned)*len >> 16); 728 mb_put_uint16le(mbp, *len); 729 mb_put_uint16le(mbp, 64); /* data offset from header start */ 730 mb_put_uint32le(mbp, uio->uio_offset >> 32); /* OffsetHigh */ 731 smb_rq_wend(rqp); 732 smb_rq_bstart(rqp); 733 do { 734 mb_put_uint8(mbp, 0xee); /* mimic xp pad byte! */ 735 error = mb_put_uio(mbp, uio, *len); 736 if (error) 737 break; 738 smb_rq_bend(rqp); 739 error = smb_rq_simple(rqp); 740 if (error) 741 break; 742 smb_rq_getreply(rqp, &mdp); 743 md_get_uint8(mdp, &wc); 744 if (wc != 6) { 745 error = EBADRPC; 746 break; 747 } 748 md_get_uint8(mdp, NULL); 749 md_get_uint8(mdp, NULL); 750 md_get_uint16le(mdp, NULL); 751 md_get_uint16le(mdp, &resid); 752 *rresid = resid; 753 } while(0); 754 755 smb_rq_done(rqp); 756 return (error); 757 } 758 759 static __inline int 760 smb_smb_read(struct smb_share *ssp, u_int16_t fid, 761 int *len, int *rresid, struct uio *uio, struct smb_cred *scred) 762 { 763 struct smb_rq *rqp; 764 struct mbchain *mbp; 765 struct mdchain *mdp; 766 u_int16_t resid, bc; 767 u_int8_t wc; 768 int error, rlen, blksz; 769 770 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_READX) 771 return (smb_smb_readx(ssp, fid, len, rresid, uio, scred)); 772 773 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp); 774 if (error) 775 return error; 776 777 blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 16; 778 rlen = *len = min(blksz, *len); 779 780 smb_rq_getrequest(rqp, &mbp); 781 smb_rq_wstart(rqp); 782 mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM); 783 mb_put_uint16le(mbp, rlen); 784 mb_put_uint32le(mbp, uio->uio_offset); 785 mb_put_uint16le(mbp, min(uio->uio_resid, 0xffff)); 786 smb_rq_wend(rqp); 787 smb_rq_bstart(rqp); 788 smb_rq_bend(rqp); 789 do { 790 error = smb_rq_simple(rqp); 791 if (error) 792 break; 793 smb_rq_getreply(rqp, &mdp); 794 md_get_uint8(mdp, &wc); 795 if (wc != 5) { 796 error = EBADRPC; 797 break; 798 } 799 md_get_uint16le(mdp, &resid); 800 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); 801 md_get_uint16le(mdp, &bc); 802 md_get_uint8(mdp, NULL); /* ignore buffer type */ 803 md_get_uint16le(mdp, &resid); 804 if (resid == 0) { 805 *rresid = resid; 806 break; 807 } 808 error = md_get_uio(mdp, uio, resid); 809 if (error) 810 break; 811 *rresid = resid; 812 } while(0); 813 smb_rq_done(rqp); 814 return error; 815 } 816 817 int 818 smb_read(struct smb_share *ssp, u_int16_t fid, struct uio *uio, 819 struct smb_cred *scred) 820 { 821 int tsize, len, resid; 822 int error = 0; 823 824 tsize = uio->uio_resid; 825 while (tsize > 0) { 826 resid = 0; 827 len = tsize; 828 error = smb_smb_read(ssp, fid, &len, &resid, uio, scred); 829 if (error) 830 break; 831 tsize -= resid; 832 if (resid < len) 833 break; 834 } 835 return error; 836 } 837 838 static __inline int 839 smb_smb_write(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid, 840 struct uio *uio, struct smb_cred *scred) 841 { 842 struct smb_rq *rqp; 843 struct mbchain *mbp; 844 struct mdchain *mdp; 845 u_int16_t resid; 846 u_int8_t wc; 847 int error, blksz; 848 849 if (*len && SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX) 850 return (smb_smb_writex(ssp, fid, len, rresid, uio, scred)); 851 852 blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 16; 853 if (blksz > 0xffff) 854 blksz = 0xffff; 855 856 resid = *len = min(blksz, *len); 857 858 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); 859 if (error) 860 return error; 861 smb_rq_getrequest(rqp, &mbp); 862 smb_rq_wstart(rqp); 863 mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM); 864 mb_put_uint16le(mbp, resid); 865 mb_put_uint32le(mbp, uio->uio_offset); 866 mb_put_uint16le(mbp, min(uio->uio_resid, 0xffff)); 867 smb_rq_wend(rqp); 868 smb_rq_bstart(rqp); 869 mb_put_uint8(mbp, SMB_DT_DATA); 870 mb_put_uint16le(mbp, resid); 871 do { 872 error = mb_put_uio(mbp, uio, resid); 873 if (error) 874 break; 875 smb_rq_bend(rqp); 876 error = smb_rq_simple(rqp); 877 if (error) 878 break; 879 smb_rq_getreply(rqp, &mdp); 880 md_get_uint8(mdp, &wc); 881 if (wc != 1) { 882 error = EBADRPC; 883 break; 884 } 885 md_get_uint16le(mdp, &resid); 886 *rresid = resid; 887 } while(0); 888 smb_rq_done(rqp); 889 return error; 890 } 891 892 int 893 smb_write(struct smb_share *ssp, u_int16_t fid, struct uio *uio, 894 struct smb_cred *scred) 895 { 896 int error = 0, len, tsize, resid; 897 struct uio olduio; 898 899 tsize = uio->uio_resid; 900 olduio = *uio; 901 while (tsize > 0) { 902 resid = 0; 903 len = tsize; 904 error = smb_smb_write(ssp, fid, &len, &resid, uio, scred); 905 if (error) 906 break; 907 if (resid < len) { 908 error = EIO; 909 break; 910 } 911 tsize -= resid; 912 } 913 if (error) { 914 /* 915 * Errors can happen on the copyin, the rpc, etc. So they 916 * imply resid is unreliable. The only safe thing is 917 * to pretend zero bytes made it. We needn't restore the 918 * iovs because callers don't depend on them in error 919 * paths - uio_resid and uio_offset are what matter. 920 */ 921 *uio = olduio; 922 } 923 return error; 924 } 925 926 int 927 smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred) 928 { 929 struct smb_rq *rqp; 930 struct mbchain *mbp; 931 int error; 932 933 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp); 934 if (error) 935 return error; 936 mbp = &rqp->sr_rq; 937 smb_rq_wstart(rqp); 938 mb_put_uint16le(mbp, 1); 939 smb_rq_wend(rqp); 940 smb_rq_bstart(rqp); 941 mb_put_uint32le(mbp, 0); 942 smb_rq_bend(rqp); 943 error = smb_rq_simple(rqp); 944 SMBSDEBUG("%d\n", error); 945 smb_rq_done(rqp); 946 return error; 947 } 948