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