KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > smb > server > IPCHandler


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.filesys.smb.server;
18
19 import java.io.IOException JavaDoc;
20
21 import org.alfresco.filesys.server.filesys.NetworkFile;
22 import org.alfresco.filesys.server.filesys.TooManyFilesException;
23 import org.alfresco.filesys.server.filesys.TreeConnection;
24 import org.alfresco.filesys.smb.PacketType;
25 import org.alfresco.filesys.smb.SMBStatus;
26 import org.alfresco.filesys.smb.TransactionNames;
27 import org.alfresco.filesys.smb.dcerpc.DCEPipeType;
28 import org.alfresco.filesys.smb.dcerpc.server.DCEPipeFile;
29 import org.alfresco.filesys.smb.dcerpc.server.DCEPipeHandler;
30 import org.alfresco.filesys.util.DataBuffer;
31 import org.alfresco.filesys.util.DataPacker;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35 /**
36  * <p>
37  * The IPCHandler class processes requests made on the IPC$ remote admin pipe. The code is shared
38  * amongst different SMB protocol handlers.
39  */

40 class IPCHandler
41 {
42
43     // Debug logging
44

45     private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol");
46
47     /**
48      * Process a request made on the IPC$ remote admin named pipe.
49      *
50      * @param sess SMBSrvSession
51      * @param outPkt SMBSrvPacket
52      * @exception java.io.IOException If an I/O error occurs
53      * @exception SMBSrvException If an SMB protocol error occurs
54      */

55     public static void processIPCRequest(SMBSrvSession sess, SMBSrvPacket outPkt) throws java.io.IOException JavaDoc,
56             SMBSrvException
57     {
58
59         // Get the received packet from the session and verify that the connection is valid
60

61         SMBSrvPacket smbPkt = sess.getReceivePacket();
62
63         // Get the tree id from the received packet and validate that it is a valid
64
// connection id.
65

66         int treeId = smbPkt.getTreeId();
67         TreeConnection conn = sess.findConnection(treeId);
68
69         if (conn == null)
70         {
71             sess.sendErrorResponseSMB(SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos);
72             return;
73         }
74
75         // Debug
76

77         if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
78             logger.debug("IPC$ Request [" + treeId + "] - cmd = " + smbPkt.getPacketTypeString());
79
80         // Determine the SMB command
81

82         switch (smbPkt.getCommand())
83         {
84
85         // Open file request
86

87         case PacketType.OpenAndX:
88         case PacketType.OpenFile:
89             procIPCFileOpen(sess, smbPkt, outPkt);
90             break;
91
92         // Read file request
93

94         case PacketType.ReadFile:
95             procIPCFileRead(sess, smbPkt, outPkt);
96             break;
97
98         // Read AndX file request
99

100         case PacketType.ReadAndX:
101             procIPCFileReadAndX(sess, smbPkt, outPkt);
102             break;
103
104         // Write file request
105

106         case PacketType.WriteFile:
107             procIPCFileWrite(sess, smbPkt, outPkt);
108             break;
109
110         // Write AndX file request
111

112         case PacketType.WriteAndX:
113             procIPCFileWriteAndX(sess, smbPkt, outPkt);
114             break;
115
116         // Close file request
117

118         case PacketType.CloseFile:
119             procIPCFileClose(sess, smbPkt, outPkt);
120             break;
121
122         // NT create andX request
123

124         case PacketType.NTCreateAndX:
125             procNTCreateAndX(sess, smbPkt, outPkt);
126             break;
127
128         // Default, respond with an unsupported function error.
129

130         default:
131             sess.sendErrorResponseSMB(SMBStatus.SRVUnrecognizedCommand, SMBStatus.ErrSrv);
132             break;
133         }
134     }
135
136     /**
137      * Process an IPC$ transaction request.
138      *
139      * @param tbuf SrvTransactBuffer
140      * @param sess SMBSrvSession
141      * @param outPkt SMBSrvPacket
142      */

143     protected static void procTransaction(SrvTransactBuffer tbuf, SMBSrvSession sess, SMBSrvPacket outPkt)
144             throws IOException JavaDoc, SMBSrvException
145     {
146
147         // Debug
148

149         if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
150             logger.debug("IPC$ Transaction pipe=" + tbuf.getName() + ", subCmd="
151                     + NamedPipeTransaction.getSubCommand(tbuf.getFunction()));
152
153         // Call the required transaction handler
154

155         if (tbuf.getName().compareTo(TransactionNames.PipeLanman) == 0)
156         {
157
158             // Call the \PIPE\LANMAN transaction handler to process the request
159

160             if (PipeLanmanHandler.processRequest(tbuf, sess, outPkt))
161                 return;
162         }
163
164         // Process the pipe command
165

166         switch (tbuf.getFunction())
167         {
168
169         // Set named pipe handle state
170

171         case NamedPipeTransaction.SetNmPHandState:
172             procSetNamedPipeHandleState(sess, tbuf, outPkt);
173             break;
174
175         // Named pipe transation request, pass the request to the DCE/RPC handler
176

177         case NamedPipeTransaction.TransactNmPipe:
178             DCERPCHandler.processDCERPCRequest(sess, tbuf, outPkt);
179             break;
180
181         // Unknown command
182

183         default:
184             sess.sendErrorResponseSMB(SMBStatus.SRVUnrecognizedCommand, SMBStatus.ErrSrv);
185             break;
186         }
187     }
188
189     /**
190      * Process a special IPC$ file open request.
191      *
192      * @param sess SMBSrvSession
193      * @param rxPkt SMBSrvPacket
194      * @param outPkt SMBSrvPacket
195      */

196     protected static void procIPCFileOpen(SMBSrvSession sess, SMBSrvPacket rxPkt, SMBSrvPacket outPkt)
197             throws IOException JavaDoc, SMBSrvException
198     {
199
200         // Get the data bytes position and length
201

202         int dataPos = rxPkt.getByteOffset();
203         int dataLen = rxPkt.getByteCount();
204         byte[] buf = rxPkt.getBuffer();
205
206         // Extract the filename string
207

208         String JavaDoc fileName = DataPacker.getString(buf, dataPos, dataLen);
209
210         // Debug
211

212         if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
213             logger.debug("IPC$ Open file = " + fileName);
214
215         // Check if the requested IPC$ file is valid
216

217         int pipeType = DCEPipeType.getNameAsType(fileName);
218         if (pipeType == -1)
219         {
220             sess.sendErrorResponseSMB(SMBStatus.DOSFileNotFound, SMBStatus.ErrDos);
221             return;
222         }
223
224         // Get the tree connection details
225

226         int treeId = rxPkt.getTreeId();
227         TreeConnection conn = sess.findConnection(treeId);
228
229         if (conn == null)
230         {
231             sess.sendErrorResponseSMB(SMBStatus.SRVInvalidTID, SMBStatus.ErrSrv);
232             return;
233         }
234
235         // Create a network file for the special pipe
236

237         DCEPipeFile pipeFile = new DCEPipeFile(pipeType);
238         pipeFile.setGrantedAccess(NetworkFile.READWRITE);
239
240         // Add the file to the list of open files for this tree connection
241

242         int fid = -1;
243
244         try
245         {
246             fid = conn.addFile(pipeFile, sess);
247         }
248         catch (TooManyFilesException ex)
249         {
250
251             // Too many files are open on this connection, cannot open any more files.
252

253             sess.sendErrorResponseSMB(SMBStatus.DOSTooManyOpenFiles, SMBStatus.ErrDos);
254             return;
255         }
256
257         // Build the open file response
258

259         outPkt.setParameterCount(15);
260
261         outPkt.setAndXCommand(0xFF);
262         outPkt.setParameter(1, 0); // AndX offset
263

264         outPkt.setParameter(2, fid);
265         outPkt.setParameter(3, 0); // file attributes
266
outPkt.setParameter(4, 0); // last write time
267
outPkt.setParameter(5, 0); // last write date
268
outPkt.setParameterLong(6, 0); // file size
269
outPkt.setParameter(8, 0);
270         outPkt.setParameter(9, 0);
271         outPkt.setParameter(10, 0); // named pipe state
272
outPkt.setParameter(11, 0);
273         outPkt.setParameter(12, 0); // server FID (long)
274
outPkt.setParameter(13, 0);
275         outPkt.setParameter(14, 0);
276
277         outPkt.setByteCount(0);
278
279         // Send the response packet
280

281         sess.sendResponseSMB(outPkt);
282     }
283
284     /**
285      * Process an IPC pipe file read request
286      *
287      * @param sess SMBSrvSession
288      * @param rxPkt SMBSrvPacket
289      * @param outPkt SMBSrvPacket
290      */

291     protected static void procIPCFileRead(SMBSrvSession sess, SMBSrvPacket rxPkt, SMBSrvPacket outPkt)
292             throws IOException JavaDoc, SMBSrvException
293     {
294
295         // Check if the received packet is a valid read file request
296

297         if (rxPkt.checkPacketIsValid(5, 0) == false)
298         {
299
300             // Invalid request
301

302             sess.sendErrorResponseSMB(SMBStatus.SRVUnrecognizedCommand, SMBStatus.ErrSrv);
303             return;
304         }
305
306         // Debug
307

308         if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
309             logger.debug("IPC$ File Read");
310
311         // Pass the read request the DCE/RPC handler
312

313         DCERPCHandler.processDCERPCRead(sess, rxPkt, outPkt);
314     }
315
316     /**
317      * Process an IPC pipe file read andX request
318      *
319      * @param sess SMBSrvSession
320      * @param rxPkt SMBSrvPacket
321      * @param outPkt SMBSrvPacket
322      */

323     protected static void procIPCFileReadAndX(SMBSrvSession sess, SMBSrvPacket rxPkt, SMBSrvPacket outPkt)
324             throws IOException JavaDoc, SMBSrvException
325     {
326
327         // Check if the received packet is a valid read andX file request
328

329         if (rxPkt.checkPacketIsValid(10, 0) == false)
330         {
331
332             // Invalid request
333

334             sess.sendErrorResponseSMB(SMBStatus.SRVUnrecognizedCommand, SMBStatus.ErrSrv);
335             return;
336         }
337
338         // Debug
339

340         if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
341             logger.debug("IPC$ File Read AndX");
342
343         // Pass the read request the DCE/RPC handler
344

345         DCERPCHandler.processDCERPCRead(sess, rxPkt, outPkt);
346     }
347
348     /**
349      * Process an IPC pipe file write request
350      *
351      * @param sess SMBSrvSession
352      * @param rxPkt SMBSrvPacket
353      * @param outPkt SMBSrvPacket
354      */

355     protected static void procIPCFileWrite(SMBSrvSession sess, SMBSrvPacket rxPkt, SMBSrvPacket outPkt)
356             throws IOException JavaDoc, SMBSrvException
357     {
358
359         // Check if the received packet is a valid write file request
360

361         if (rxPkt.checkPacketIsValid(5, 0) == false)
362         {
363
364             // Invalid request
365

366             sess.sendErrorResponseSMB(SMBStatus.SRVUnrecognizedCommand, SMBStatus.ErrSrv);
367             return;
368         }
369
370         // Debug
371

372         if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
373             logger.debug("IPC$ File Write");
374
375         // Pass the write request the DCE/RPC handler
376

377         DCERPCHandler.processDCERPCRequest(sess, rxPkt, outPkt);
378     }
379
380     /**
381      * Process an IPC pipe file write andX request
382      *
383      * @param sess SMBSrvSession
384      * @param rxPkt SMBSrvPacket
385      * @param outPkt SMBSrvPacket
386      */

387     protected static void procIPCFileWriteAndX(SMBSrvSession sess, SMBSrvPacket rxPkt, SMBSrvPacket outPkt)
388             throws IOException JavaDoc, SMBSrvException
389     {
390
391         // Check if the received packet is a valid write andX request
392

393         if (rxPkt.checkPacketIsValid(12, 0) == false)
394         {
395
396             // Invalid request
397

398             sess.sendErrorResponseSMB(SMBStatus.SRVUnrecognizedCommand, SMBStatus.ErrSrv);
399             return;
400         }
401
402         // Debug
403

404         if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
405             logger.debug("IPC$ File Write AndX");
406
407         // Pass the write request the DCE/RPC handler
408

409         DCERPCHandler.processDCERPCRequest(sess, rxPkt, outPkt);
410     }
411
412     /**
413      * Process a special IPC$ file close request.
414      *
415      * @param sess SMBSrvSession
416      * @param rxPkt SMBSrvPacket
417      * @param outPkt SMBSrvPacket
418      */

419     protected static void procIPCFileClose(SMBSrvSession sess, SMBSrvPacket rxPkt, SMBSrvPacket outPkt)
420             throws IOException JavaDoc, SMBSrvException
421     {
422
423         // Check that the received packet looks like a valid file close request
424

425         if (rxPkt.checkPacketIsValid(3, 0) == false)
426         {
427             sess.sendErrorResponseSMB(SMBStatus.SRVUnrecognizedCommand, SMBStatus.ErrSrv);
428             return;
429         }
430
431         // Get the tree id from the received packet and validate that it is a valid
432
// connection id.
433

434         int treeId = rxPkt.getTreeId();
435         TreeConnection conn = sess.findConnection(treeId);
436
437         if (conn == null)
438         {
439             sess.sendErrorResponseSMB(SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos);
440             return;
441         }
442
443         // Get the file id from the request
444

445         int fid = rxPkt.getParameter(0);
446         DCEPipeFile netFile = (DCEPipeFile) conn.findFile(fid);
447
448         if (netFile == null)
449         {
450             sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos);
451             return;
452         }
453
454         // Debug
455

456         if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
457             logger.debug("IPC$ File close [" + treeId + "] fid=" + fid);
458
459         // Remove the file from the connections list of open files
460

461         conn.removeFile(fid, sess);
462
463         // Build the close file response
464

465         outPkt.setParameterCount(0);
466         outPkt.setByteCount(0);
467
468         // Send the response packet
469

470         sess.sendResponseSMB(outPkt);
471     }
472
473     /**
474      * Process a set named pipe handle state request
475      *
476      * @param sess SMBSrvSession
477      * @param tbuf SrvTransactBuffer
478      * @param outPkt SMBSrvPacket
479      */

480     protected static void procSetNamedPipeHandleState(SMBSrvSession sess, SrvTransactBuffer tbuf, SMBSrvPacket outPkt)
481             throws IOException JavaDoc, SMBSrvException
482     {
483
484         // Get the request parameters
485

486         DataBuffer setupBuf = tbuf.getSetupBuffer();
487         setupBuf.skipBytes(2);
488         int fid = setupBuf.getShort();
489
490         DataBuffer paramBuf = tbuf.getParameterBuffer();
491         int state = paramBuf.getShort();
492
493         // Get the connection for the request
494

495         TreeConnection conn = sess.findConnection(tbuf.getTreeId());
496
497         // Get the IPC pipe file for the specified file id
498

499         DCEPipeFile netFile = (DCEPipeFile) conn.findFile(fid);
500         if (netFile == null)
501         {
502             sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos);
503             return;
504         }
505
506         // Debug
507

508         if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
509             logger.debug(" SetNmPHandState pipe=" + netFile.getName() + ", fid=" + fid + ", state=0x"
510                     + Integer.toHexString(state));
511
512         // Store the named pipe state
513

514         netFile.setPipeState(state);
515
516         // Setup the response packet
517

518         SMBSrvTransPacket.initTransactReply(outPkt, 0, 0, 0, 0);
519
520         // Send the response packet
521

522         sess.sendResponseSMB(outPkt);
523     }
524
525     /**
526      * Process an NT create andX request
527      *
528      * @param sess SMBSrvSession
529      * @param rxPkt SMBSrvPacket
530      * @param outPkt SMBSrvPacket
531      */

532     protected static void procNTCreateAndX(SMBSrvSession sess, SMBSrvPacket rxPkt, SMBSrvPacket outPkt)
533             throws IOException JavaDoc, SMBSrvException
534     {
535
536         // Get the tree id from the received packet and validate that it is a valid
537
// connection id.
538

539         int treeId = rxPkt.getTreeId();
540         TreeConnection conn = sess.findConnection(treeId);
541
542         if (conn == null)
543         {
544             sess.sendErrorResponseSMB(SMBStatus.NTInvalidParameter, SMBStatus.NTErr);
545             return;
546         }
547
548         // Extract the NT create andX parameters
549

550         NTParameterPacker prms = new NTParameterPacker(rxPkt.getBuffer(), SMBSrvPacket.PARAMWORDS + 5);
551
552         int nameLen = prms.unpackWord();
553         int flags = prms.unpackInt();
554         int rootFID = prms.unpackInt();
555         int accessMask = prms.unpackInt();
556         long allocSize = prms.unpackLong();
557         int attrib = prms.unpackInt();
558         int shrAccess = prms.unpackInt();
559         int createDisp = prms.unpackInt();
560         int createOptn = prms.unpackInt();
561         int impersonLev = prms.unpackInt();
562         int secFlags = prms.unpackByte();
563
564         // Extract the filename string
565

566         int pos = DataPacker.wordAlign(rxPkt.getByteOffset());
567         String JavaDoc fileName = DataPacker.getUnicodeString(rxPkt.getBuffer(), pos, nameLen);
568         if (fileName == null)
569         {
570             sess.sendErrorResponseSMB(SMBStatus.NTInvalidParameter, SMBStatus.NTErr);
571             return;
572         }
573
574         // Debug
575

576         if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
577             logger.debug("NT Create AndX [" + treeId + "] name=" + fileName + ", flags=0x"
578                     + Integer.toHexString(flags) + ", attr=0x" + Integer.toHexString(attrib) + ", allocSize="
579                     + allocSize);
580
581         // Check if the pipe name is a short or long name
582

583         if (fileName.startsWith("\\PIPE") == false)
584             fileName = "\\PIPE" + fileName;
585
586         // Check if the requested IPC$ file is valid
587

588         int pipeType = DCEPipeType.getNameAsType(fileName);
589         if (pipeType == -1)
590         {
591             sess.sendErrorResponseSMB(SMBStatus.NTObjectNotFound, SMBStatus.NTErr);
592             return;
593         }
594
595         // Check if there is a handler for the pipe file
596

597         if (DCEPipeHandler.getHandlerForType(pipeType) == null)
598         {
599             sess.sendErrorResponseSMB(SMBStatus.NTAccessDenied, SMBStatus.NTErr);
600             return;
601         }
602
603         // Create a network file for the special pipe
604

605         DCEPipeFile pipeFile = new DCEPipeFile(pipeType);
606         pipeFile.setGrantedAccess(NetworkFile.READWRITE);
607
608         // Add the file to the list of open files for this tree connection
609

610         int fid = -1;
611
612         try
613         {
614             fid = conn.addFile(pipeFile, sess);
615         }
616         catch (TooManyFilesException ex)
617         {
618
619             // Too many files are open on this connection, cannot open any more files.
620

621             sess.sendErrorResponseSMB(SMBStatus.Win32InvalidHandle, SMBStatus.NTErr);
622             return;
623         }
624
625         // Build the NT create andX response
626

627         outPkt.setParameterCount(34);
628
629         prms.reset(outPkt.getBuffer(), SMBSrvPacket.PARAMWORDS + 4);
630
631         prms.packByte(0);
632         prms.packWord(fid);
633         prms.packInt(0x0001); // File existed and was opened
634

635         prms.packLong(0); // Creation time
636
prms.packLong(0); // Last access time
637
prms.packLong(0); // Last write time
638
prms.packLong(0); // Change time
639

640         prms.packInt(0x0080); // File attributes
641
prms.packLong(4096); // Allocation size
642
prms.packLong(0); // End of file
643
prms.packWord(2); // File type - named pipe, message mode
644
prms.packByte(0xFF); // Pipe instancing count
645
prms.packByte(0x05); // IPC state bits
646

647         prms.packByte(0); // directory flag
648

649         outPkt.setByteCount(0);
650
651         outPkt.setAndXCommand(0xFF);
652         outPkt.setParameter(1, outPkt.getLength()); // AndX offset
653

654         // Send the response packet
655

656         sess.sendResponseSMB(outPkt);
657     }
658 }
Popular Tags