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