1 17 package org.alfresco.filesys.smb.server; 18 19 import java.io.IOException ; 20 21 import org.alfresco.filesys.netbios.RFCNetBIOSProtocol; 22 import org.alfresco.filesys.server.filesys.TreeConnection; 23 import org.alfresco.filesys.smb.DataType; 24 import org.alfresco.filesys.smb.PacketType; 25 import org.alfresco.filesys.smb.SMBStatus; 26 import org.alfresco.filesys.smb.TransactBuffer; 27 import org.alfresco.filesys.smb.dcerpc.DCEBuffer; 28 import org.alfresco.filesys.smb.dcerpc.DCEBufferException; 29 import org.alfresco.filesys.smb.dcerpc.DCECommand; 30 import org.alfresco.filesys.smb.dcerpc.DCEDataPacker; 31 import org.alfresco.filesys.smb.dcerpc.DCEPipeType; 32 import org.alfresco.filesys.smb.dcerpc.UUID; 33 import org.alfresco.filesys.smb.dcerpc.server.DCEPipeFile; 34 import org.alfresco.filesys.smb.dcerpc.server.DCESrvPacket; 35 import org.alfresco.filesys.util.DataBuffer; 36 import org.alfresco.filesys.util.DataPacker; 37 import org.apache.commons.logging.Log; 38 import org.apache.commons.logging.LogFactory; 39 40 43 public class DCERPCHandler 44 { 45 private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol"); 46 47 56 public static final void processDCERPCRequest(SMBSrvSession sess, SMBSrvTransPacket srvTrans, SMBSrvPacket outPkt) 57 throws IOException , SMBSrvException 58 { 59 60 63 int treeId = srvTrans.getTreeId(); 64 TreeConnection conn = sess.findConnection(treeId); 65 66 if (conn == null) 67 { 68 sess.sendErrorResponseSMB(SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos); 69 return; 70 } 71 72 74 int fid = srvTrans.getSetupParameter(1); 75 int maxData = srvTrans.getParameter(3) - DCEBuffer.OPERATIONDATA; 76 77 79 DCEPipeFile pipeFile = (DCEPipeFile) conn.findFile(fid); 80 if (pipeFile == null) 81 { 82 sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos); 83 return; 84 } 85 86 88 DCEBuffer dceBuf = new DCEBuffer(srvTrans.getBuffer(), srvTrans.getParameter(10) 89 + RFCNetBIOSProtocol.HEADER_LEN); 90 91 93 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC)) 94 logger.debug("TransactNmPipe pipeFile=" + pipeFile.getName() + ", fid=" + fid + ", dceCmd=0x" 95 + Integer.toHexString(dceBuf.getHeaderValue(DCEBuffer.HDR_PDUTYPE))); 96 97 99 processDCEBuffer(sess, dceBuf, pipeFile); 100 101 103 if (pipeFile.hasBufferedData() == false) 104 return; 105 106 DCEBuffer txBuf = pipeFile.getBufferedData(); 107 108 110 DCESrvPacket dcePkt = new DCESrvPacket(outPkt.getBuffer()); 111 112 115 int flags = DCESrvPacket.FLG_ONLYFRAG; 116 117 dcePkt.initializeDCEReply(); 118 txBuf.setHeaderValue(DCEBuffer.HDR_FLAGS, flags); 119 120 122 byte[] buf = dcePkt.getBuffer(); 123 int pos = DCEDataPacker.longwordAlign(dcePkt.getByteOffset()); 124 125 127 int dataLen = txBuf.getLength(); 128 txBuf.setHeaderValue(DCEBuffer.HDR_FRAGLEN, dataLen); 129 130 132 int len = txBuf.getLength(); 133 int sts = SMBStatus.NTSuccess; 134 135 if (len > maxData) 136 { 137 138 140 len = maxData + DCEBuffer.OPERATIONDATA; 141 dataLen = maxData + DCEBuffer.OPERATIONDATA; 142 143 145 sts = SMBStatus.NTBufferOverflow; 146 } 147 else 148 { 149 150 153 pipeFile.setBufferedData(null); 154 } 155 156 158 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC)) 159 logger.debug("Reply DCEbuf flags=0x" + Integer.toHexString(flags) + ", len=" + len + ", status=0x" 160 + Integer.toHexString(sts)); 161 162 164 try 165 { 166 pos += txBuf.copyData(buf, pos, len); 167 } 168 catch (DCEBufferException ex) 169 { 170 sess.sendErrorResponseSMB(SMBStatus.SRVNotSupported, SMBStatus.ErrSrv); 171 return; 172 } 173 174 176 int byteLen = pos - dcePkt.getByteOffset(); 177 dcePkt.setParameter(1, dataLen); 178 dcePkt.setParameter(6, dataLen); 179 dcePkt.setByteCount(byteLen); 180 dcePkt.setFlags2(SMBPacket.FLG2_LONGERRORCODE); 181 dcePkt.setLongErrorCode(sts); 182 183 sess.sendResponseSMB(dcePkt); 184 } 185 186 195 public static final void processDCERPCRequest(SMBSrvSession sess, TransactBuffer tbuf, SMBSrvPacket outPkt) 196 throws IOException , SMBSrvException 197 { 198 199 201 if (tbuf.hasSetupBuffer() == false || tbuf.hasDataBuffer() == false) 202 { 203 sess.sendErrorResponseSMB(SMBStatus.SRVUnrecognizedCommand, SMBStatus.ErrSrv); 204 return; 205 } 206 207 210 int treeId = tbuf.getTreeId(); 211 TreeConnection conn = sess.findConnection(treeId); 212 213 if (conn == null) 214 { 215 sess.sendErrorResponseSMB(SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos); 216 return; 217 } 218 219 221 DataBuffer setupBuf = tbuf.getSetupBuffer(); 222 223 setupBuf.skipBytes(2); 224 int fid = setupBuf.getShort(); 225 int maxData = tbuf.getReturnDataLimit() - DCEBuffer.OPERATIONDATA; 226 227 229 DCEPipeFile pipeFile = (DCEPipeFile) conn.findFile(fid); 230 if (pipeFile == null) 231 { 232 sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos); 233 return; 234 } 235 236 238 DCEBuffer dceBuf = new DCEBuffer(tbuf); 239 240 242 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC)) 243 logger.debug("TransactNmPipe pipeFile=" + pipeFile.getName() + ", fid=" + fid + ", dceCmd=0x" 244 + Integer.toHexString(dceBuf.getHeaderValue(DCEBuffer.HDR_PDUTYPE))); 245 246 248 processDCEBuffer(sess, dceBuf, pipeFile); 249 250 252 if (pipeFile.hasBufferedData() == false) 253 return; 254 255 DCEBuffer txBuf = pipeFile.getBufferedData(); 256 257 259 DCESrvPacket dcePkt = new DCESrvPacket(outPkt.getBuffer()); 260 261 264 int flags = DCESrvPacket.FLG_ONLYFRAG; 265 266 dcePkt.initializeDCEReply(); 267 txBuf.setHeaderValue(DCEBuffer.HDR_FLAGS, flags); 268 269 271 byte[] buf = dcePkt.getBuffer(); 272 int pos = DCEDataPacker.longwordAlign(dcePkt.getByteOffset()); 273 274 276 int dataLen = txBuf.getLength(); 277 txBuf.setHeaderValue(DCEBuffer.HDR_FRAGLEN, dataLen); 278 279 281 int len = txBuf.getLength(); 282 int sts = SMBStatus.NTSuccess; 283 284 if (len > maxData) 285 { 286 287 289 len = maxData + DCEBuffer.OPERATIONDATA; 290 dataLen = maxData + DCEBuffer.OPERATIONDATA; 291 292 294 sts = SMBStatus.NTBufferOverflow; 295 } 296 else 297 { 298 299 302 pipeFile.setBufferedData(null); 303 } 304 305 307 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC)) 308 logger.debug("Reply DCEbuf flags=0x" + Integer.toHexString(flags) + ", len=" + len + ", status=0x" 309 + Integer.toHexString(sts)); 310 311 313 try 314 { 315 pos += txBuf.copyData(buf, pos, len); 316 } 317 catch (DCEBufferException ex) 318 { 319 sess.sendErrorResponseSMB(SMBStatus.SRVNotSupported, SMBStatus.ErrSrv); 320 return; 321 } 322 323 325 int byteLen = pos - dcePkt.getByteOffset(); 326 dcePkt.setParameter(1, dataLen); 327 dcePkt.setParameter(6, dataLen); 328 dcePkt.setByteCount(byteLen); 329 dcePkt.setFlags2(SMBPacket.FLG2_LONGERRORCODE); 330 dcePkt.setLongErrorCode(sts); 331 332 sess.sendResponseSMB(dcePkt); 333 } 334 335 344 public static final void processDCERPCRequest(SMBSrvSession sess, SMBSrvPacket inPkt, SMBSrvPacket outPkt) 345 throws IOException , SMBSrvException 346 { 347 348 351 int treeId = inPkt.getTreeId(); 352 TreeConnection conn = sess.findConnection(treeId); 353 354 if (conn == null) 355 { 356 sess.sendErrorResponseSMB(SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos); 357 return; 358 } 359 360 362 int cmd = inPkt.getCommand(); 363 364 366 int fid = -1; 367 if (cmd == PacketType.WriteFile) 368 fid = inPkt.getParameter(0); 369 else 370 fid = inPkt.getParameter(2); 371 372 374 DCEPipeFile pipeFile = (DCEPipeFile) conn.findFile(fid); 375 if (pipeFile == null) 376 { 377 sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos); 378 return; 379 } 380 381 383 DCEBuffer dceBuf = null; 384 byte[] buf = inPkt.getBuffer(); 385 int pos = 0; 386 int len = 0; 387 388 if (cmd == PacketType.WriteFile) 389 { 390 391 393 pos = inPkt.getByteOffset(); 394 395 397 if (buf[pos++] != DataType.DataBlock) 398 { 399 sess.sendErrorResponseSMB(SMBStatus.DOSInvalidData, SMBStatus.ErrDos); 400 return; 401 } 402 403 len = DataPacker.getIntelShort(buf, pos); 404 pos += 2; 405 406 } 407 else 408 { 409 410 412 len = inPkt.getParameter(10); 413 pos = inPkt.getParameter(11) + RFCNetBIOSProtocol.HEADER_LEN; 414 } 415 416 418 dceBuf = new DCEBuffer(buf, pos); 419 420 422 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC)) 423 logger.debug("Write pipeFile=" + pipeFile.getName() + ", fid=" + fid + ", dceCmd=0x" 424 + Integer.toHexString(dceBuf.getHeaderValue(DCEBuffer.HDR_PDUTYPE))); 425 426 428 processDCEBuffer(sess, dceBuf, pipeFile); 429 430 432 int bufLen = 0; 433 if (pipeFile.hasBufferedData()) 434 bufLen = pipeFile.getBufferedData().getLength(); 435 436 438 if (cmd == PacketType.WriteFile) 439 { 440 441 443 outPkt.setParameterCount(1); 444 outPkt.setParameter(0, len); 445 outPkt.setByteCount(0); 446 } 447 else 448 { 449 450 452 outPkt.setParameterCount(6); 453 454 outPkt.setAndXCommand(0xFF); 455 outPkt.setParameter(1, 0); 456 outPkt.setParameter(2, len); 457 outPkt.setParameter(3, bufLen); 458 outPkt.setParameter(4, 0); 459 outPkt.setParameter(5, 0); 460 outPkt.setByteCount(0); 461 } 462 463 465 outPkt.setFlags2(SMBPacket.FLG2_LONGERRORCODE); 466 sess.sendResponseSMB(outPkt); 467 } 468 469 478 public static final void processDCERPCRead(SMBSrvSession sess, SMBSrvPacket inPkt, SMBSrvPacket outPkt) 479 throws IOException , SMBSrvException 480 { 481 482 485 int treeId = inPkt.getTreeId(); 486 TreeConnection conn = sess.findConnection(treeId); 487 488 if (conn == null) 489 { 490 sess.sendErrorResponseSMB(SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos); 491 return; 492 } 493 494 496 int cmd = inPkt.getCommand(); 497 498 500 int fid = -1; 501 int rdLen = -1; 502 503 if (cmd == PacketType.ReadFile) 504 { 505 fid = inPkt.getParameter(0); 506 rdLen = inPkt.getParameter(1); 507 } 508 else 509 { 510 fid = inPkt.getParameter(2); 511 rdLen = inPkt.getParameter(5); 512 } 513 514 516 DCEPipeFile pipeFile = (DCEPipeFile) conn.findFile(fid); 517 if (pipeFile == null) 518 { 519 sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos); 520 return; 521 } 522 523 525 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC)) 526 logger.debug("Read pipeFile=" + pipeFile.getName() + ", fid=" + fid + ", rdLen=" + rdLen); 527 528 530 if (pipeFile.hasBufferedData()) 531 { 532 533 535 DCEBuffer bufData = pipeFile.getBufferedData(); 536 int bufLen = bufData.getAvailableLength(); 537 538 540 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC)) 541 logger.debug(" Buffered data available=" + bufLen); 542 543 545 if (rdLen > bufLen) 546 rdLen = bufLen; 547 548 550 if (cmd == PacketType.ReadFile) 551 { 552 553 555 outPkt.setParameterCount(5); 556 outPkt.setParameter(0, rdLen); 557 for (int i = 1; i < 5; i++) 558 outPkt.setParameter(i, 0); 559 outPkt.setByteCount(rdLen + 3); 560 561 563 byte[] buf = outPkt.getBuffer(); 564 int pos = outPkt.getByteOffset(); 565 566 buf[pos++] = (byte) DataType.DataBlock; 567 DataPacker.putIntelShort(rdLen, buf, pos); 568 pos += 2; 569 570 try 571 { 572 bufData.copyData(buf, pos, rdLen); 573 } 574 catch (DCEBufferException ex) 575 { 576 logger.error("DCR/RPC read", ex); 577 } 578 } 579 else 580 { 581 582 584 outPkt.setParameterCount(12); 585 outPkt.setAndXCommand(0xFF); 586 for (int i = 1; i < 12; i++) 587 outPkt.setParameter(i, 0); 588 589 591 byte[] buf = outPkt.getBuffer(); 592 int pos = DCEDataPacker.longwordAlign(outPkt.getByteOffset()); 593 594 outPkt.setParameter(5, rdLen); 595 outPkt.setParameter(6, pos - RFCNetBIOSProtocol.HEADER_LEN); 596 outPkt.setByteCount((pos + rdLen) - outPkt.getByteOffset()); 597 598 try 599 { 600 bufData.copyData(buf, pos, rdLen); 601 } 602 catch (DCEBufferException ex) 603 { 604 logger.error("DCE/RPC error", ex); 605 } 606 } 607 } 608 else 609 { 610 611 613 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC)) 614 logger.debug(" No buffered data available"); 615 616 618 if (cmd == PacketType.ReadFile) 619 { 620 621 623 outPkt.setParameterCount(5); 624 for (int i = 0; i < 5; i++) 625 outPkt.setParameter(i, 0); 626 outPkt.setByteCount(0); 627 } 628 else 629 { 630 631 633 outPkt.setParameterCount(12); 634 635 outPkt.setAndXCommand(0xFF); 636 for (int i = 1; i < 12; i++) 637 outPkt.setParameter(i, 0); 638 outPkt.setByteCount(0); 639 } 640 } 641 642 644 outPkt.setLongErrorCode(SMBStatus.NTSuccess); 645 646 648 outPkt.setFlags2(SMBPacket.FLG2_LONGERRORCODE); 649 sess.sendResponseSMB(outPkt); 650 } 651 652 661 public static final void processDCEBuffer(SMBSrvSession sess, DCEBuffer dceBuf, DCEPipeFile pipeFile) 662 throws IOException , SMBSrvException 663 { 664 665 667 switch (dceBuf.getHeaderValue(DCEBuffer.HDR_PDUTYPE)) 668 { 669 670 672 case DCECommand.BIND: 673 procDCEBind(sess, dceBuf, pipeFile); 674 break; 675 676 678 case DCECommand.REQUEST: 679 procDCERequest(sess, dceBuf, pipeFile); 680 break; 681 682 default: 683 sess.sendErrorResponseSMB(SMBStatus.SRVNoAccessRights, SMBStatus.ErrSrv); 684 break; 685 } 686 } 687 688 697 public static final void procDCEBind(SMBSrvSession sess, DCEBuffer dceBuf, DCEPipeFile pipeFile) 698 throws IOException , SMBSrvException 699 { 700 701 try 702 { 703 704 706 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC)) 707 logger.debug("DCE Bind"); 708 709 711 int callId = dceBuf.getHeaderValue(DCEBuffer.HDR_CALLID); 712 dceBuf.skipBytes(DCEBuffer.DCEDATA); 713 714 716 int maxTxSize = dceBuf.getShort(); 717 int maxRxSize = dceBuf.getShort(); 718 int groupId = dceBuf.getInt(); 719 int ctxElems = dceBuf.getByte(DCEBuffer.ALIGN_INT); 720 int presCtxId = dceBuf.getByte(DCEBuffer.ALIGN_SHORT); 721 int trfSyntax = dceBuf.getByte(DCEBuffer.ALIGN_SHORT); 722 723 UUID uuid1 = dceBuf.getUUID(true); 724 UUID uuid2 = dceBuf.getUUID(true); 725 726 728 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC)) 729 { 730 logger.debug("Bind: maxTx=" + maxTxSize + ", maxRx=" + maxRxSize + ", groupId=" + groupId 731 + ", ctxElems=" + ctxElems + ", presCtxId=" + presCtxId + ", trfSyntax=" + trfSyntax); 732 logger.debug(" uuid1=" + uuid1.toString()); 733 logger.debug(" uuid2=" + uuid2.toString()); 734 } 735 736 738 pipeFile.setMaxTransmitFragmentSize(maxTxSize); 739 pipeFile.setMaxReceiveFragmentSize(maxRxSize); 740 741 743 DCEBuffer txBuf = new DCEBuffer(); 744 txBuf.putBindAckHeader(dceBuf.getHeaderValue(DCEBuffer.HDR_CALLID)); 745 txBuf.setHeaderValue(DCEBuffer.HDR_FLAGS, DCEBuffer.FLG_ONLYFRAG); 746 747 749 txBuf.putShort(maxTxSize); 750 txBuf.putShort(maxRxSize); 751 txBuf.putInt(0x53F0); 752 753 String srvPipeName = DCEPipeType.getServerPipeName(pipeFile.getPipeId()); 754 txBuf.putShort(srvPipeName.length() + 1); 755 txBuf.putASCIIString(srvPipeName, true, DCEBuffer.ALIGN_INT); 756 txBuf.putInt(1); 757 txBuf.putShort(0); 758 txBuf.putShort(0); 759 txBuf.putUUID(uuid2, true); 760 761 txBuf.setHeaderValue(DCEBuffer.HDR_FRAGLEN, txBuf.getLength()); 762 763 765 pipeFile.setBufferedData(txBuf); 766 } 767 catch (DCEBufferException ex) 768 { 769 sess.sendErrorResponseSMB(SMBStatus.SRVNotSupported, SMBStatus.ErrSrv); 770 return; 771 } 772 } 773 774 783 public static final void procDCERequest(SMBSrvSession sess, DCEBuffer inBuf, DCEPipeFile pipeFile) 784 throws IOException , SMBSrvException 785 { 786 787 789 if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_DCERPC)) 790 logger.debug("DCE Request opNum=0x" + Integer.toHexString(inBuf.getHeaderValue(DCEBuffer.HDR_OPCODE))); 791 792 794 if (pipeFile.hasRequestHandler()) 795 pipeFile.getRequestHandler().processRequest(sess, inBuf, pipeFile); 796 else 797 sess.sendErrorResponseSMB(SMBStatus.SRVNoAccessRights, SMBStatus.ErrSrv); 798 } 799 } 800 | Popular Tags |