SessionFactory.java 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977
  1. /*
  2. * Copyright (C) 2006-2010 Alfresco Software Limited.
  3. *
  4. * This file is part of Alfresco
  5. *
  6. * Alfresco is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Alfresco is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package org.alfresco.jlan.client;
  20. import java.net.*;
  21. import java.security.*;
  22. import java.util.*;
  23. import java.io.*;
  24. import org.alfresco.jlan.client.admin.AdminSession;
  25. import org.alfresco.jlan.client.info.FileInfo;
  26. import org.alfresco.jlan.client.info.RAPServerInfo;
  27. import org.alfresco.jlan.client.info.ServerList;
  28. import org.alfresco.jlan.debug.Debug;
  29. import org.alfresco.jlan.netbios.NetBIOSName;
  30. import org.alfresco.jlan.netbios.NetBIOSNameList;
  31. import org.alfresco.jlan.netbios.NetBIOSSession;
  32. import org.alfresco.jlan.netbios.NetworkSession;
  33. import org.alfresco.jlan.netbios.RFCNetBIOSProtocol;
  34. import org.alfresco.jlan.server.filesys.AccessMode;
  35. import org.alfresco.jlan.server.filesys.FileAction;
  36. import org.alfresco.jlan.smb.Capability;
  37. import org.alfresco.jlan.smb.DataType;
  38. import org.alfresco.jlan.smb.Dialect;
  39. import org.alfresco.jlan.smb.DialectSelector;
  40. import org.alfresco.jlan.smb.NTTime;
  41. import org.alfresco.jlan.smb.PCShare;
  42. import org.alfresco.jlan.smb.PacketType;
  43. import org.alfresco.jlan.smb.Protocol;
  44. import org.alfresco.jlan.smb.SMBDate;
  45. import org.alfresco.jlan.smb.SMBDeviceType;
  46. import org.alfresco.jlan.smb.SMBErrorText;
  47. import org.alfresco.jlan.smb.SMBException;
  48. import org.alfresco.jlan.smb.SMBStatus;
  49. import org.alfresco.jlan.smb.ServerType;
  50. import org.alfresco.jlan.smb.SharingMode;
  51. import org.alfresco.jlan.smb.UnknownLocalDomainException;
  52. import org.alfresco.jlan.smb.UnsupportedDeviceTypeException;
  53. import org.alfresco.jlan.smb.dcerpc.info.WorkstationInfo;
  54. import org.alfresco.jlan.util.DataPacker;
  55. import org.alfresco.jlan.util.HexDump;
  56. import org.alfresco.jlan.util.IPAddress;
  57. import org.alfresco.jlan.util.StringList;
  58. /**
  59. * <p>The SessionFactory static class is used to create sessions to remote shared
  60. * resources using the SMB/CIFS protocol. A PCShare object is used to specify the
  61. * remote node and share details, as well as required access control details.
  62. *
  63. * <p>The OpenDisk () method opens a session to a remote disk share. The returned
  64. * session object provides disk specific methods such as opening remote files, file
  65. * and directory operations such as deleting files, renaming files etc. The disk
  66. * session may also be used to start directory searches to list files/directories
  67. * in a particular remote path.
  68. *
  69. * <p>The OpenPrinter () method opens a session to a remote printer share. The returned
  70. * session object provides print spooling functionality. To perform remote printer admin
  71. * functions use the OpenAdminSession () method to create an admin session to the remote node.
  72. *
  73. * <p>The OpenPipe () method opens a session to a remote named pipe share.
  74. *
  75. * <p>The OpenAdminSession () method creates a session that is connected to the remote IPC$
  76. * share, that is used for admin related functions, such as listing the available shares on
  77. * the remote node, listing print queues and manipulating jobs in the remote printer queues.
  78. *
  79. * <p>An AdminSession can also be used to access various DCE/RPC services for remote registry,
  80. * remote eventlog, service manager and server/workstation functions.
  81. *
  82. * @author gkspencer
  83. */
  84. public final class SessionFactory {
  85. // Constants
  86. private static final int BROADCAST_LOOKUP_TIMEOUT = 4000; // ms
  87. // Session index, used to make each session request call id unique
  88. private static int m_sessIdx = 1;
  89. // Local domain name, if known
  90. private static String m_localDomain = null;
  91. // Local domains browse master, if known
  92. private static String m_localBrowseMaster = null;
  93. // Default session packet buffer size
  94. private static int m_defPktSize = 4096 + RFCNetBIOSProtocol.HEADER_LEN;
  95. // List of local TCP/IP addresses
  96. private static InetAddress[] m_localAddrList;
  97. // Password encryptor
  98. private static PasswordEncryptor m_encryptor;
  99. // Flag to indicate if SMB signing is enabled, and if received packets are checked when signing is enabled.
  100. private static boolean m_smbSigningEnabled = true;
  101. private static boolean m_smbSigningCheckRx = true;
  102. // Default user name, password and domain used by methods that create their own connections.
  103. private static String m_defUserName = "";
  104. private static String m_defPassword = "";
  105. private static String m_defDomain = "?";
  106. // Default session settings
  107. private static SessionSettings m_defaultSettings;
  108. // Session factory debug flag
  109. private static boolean m_debug = false;
  110. // Flag to indicate if the local node details have been checked. A check is made on the local
  111. // node to get the local domain name, and other workstation details.
  112. private static boolean m_localChecked = false;
  113. // Use a global process id, so that all sessions share locks
  114. private static boolean m_globalPID = false;
  115. static {
  116. // Use the JCE based password encryptor if available, else use the BouncyCastle API based
  117. // encryptor
  118. try {
  119. // Load the JCE based password encryptor
  120. Object pwdEncObj = Class.forName("org.alfresco.jlan.client.JCEPasswordEncryptor").newInstance();
  121. if ( pwdEncObj != null)
  122. m_encryptor = (PasswordEncryptor) pwdEncObj;
  123. }
  124. catch (Exception ex) {
  125. }
  126. // Check if the password encryptor has been set
  127. if ( m_encryptor == null) {
  128. try {
  129. Object pwdEncObj = Class.forName("org.alfresco.jlan.client.j2me.J2MEPasswordEncryptor").newInstance();
  130. if ( pwdEncObj != null)
  131. m_encryptor = (PasswordEncryptor) pwdEncObj;
  132. }
  133. catch (Exception ex) {
  134. }
  135. }
  136. // Initialize the default session settings
  137. m_defaultSettings = new SessionSettings(Protocol.TCPNetBIOS, Protocol.NativeSMB);
  138. // Initialize the default dialect list
  139. SetupDefaultDialects();
  140. }
  141. /**
  142. * Build an SMB negotiate dialect packet.
  143. *
  144. * @param pkt SMBPacket to build the negotiate request
  145. * @param dlct SMB dialects to negotiate
  146. * @param pid Process id to be used by this new session
  147. * @return StringList
  148. */
  149. private final static StringList BuildNegotiatePacket(SMBPacket pkt, DialectSelector dlct, int pid) {
  150. // Initialize the SMB packet header fields
  151. pkt.setCommand(PacketType.Negotiate);
  152. pkt.setProcessId(pid);
  153. // If the NT dialect is enabled set the Unicode flag in the request flags
  154. int flags2 = 0;
  155. if ( dlct.hasDialect(Dialect.NT))
  156. flags2 += SMBPacket.FLG2_UNICODE;
  157. if ( isSMBSigningEnabled())
  158. flags2 += SMBPacket.FLG2_SECURITYSIG;
  159. pkt.setFlags2(flags2);
  160. // Build the SMB dialect list
  161. StringBuffer dia = new StringBuffer();
  162. StringList vec = new StringList();
  163. // Loop through all SMB dialect types and add the appropriate dialect strings
  164. // to the negotiate packet.
  165. int d = Dialect.Core;
  166. while (d < Dialect.Max) {
  167. // Check if the current dialect is selected
  168. if ( dlct.hasDialect(d)) {
  169. // Search the SMB dialect type string list and add all strings for the
  170. // current dialect
  171. for (int i = 0; i < Dialect.NumberOfDialects(); i++) {
  172. // Check if the current dialect string should be added to the list
  173. if ( Dialect.DialectType(i) == d) {
  174. // Get the current SMB dialect string
  175. String curDialect = Dialect.DialectString(i);
  176. vec.addString(curDialect);
  177. // Add the current SMB dialect type string to the negotiate packet
  178. dia.append(DataType.Dialect);
  179. dia.append(curDialect);
  180. dia.append((char) 0x00);
  181. }
  182. }
  183. }
  184. // Update the current dialect type
  185. d++;
  186. }
  187. // Copy the dialect strings to the SMB packet
  188. pkt.setBytes(dia.toString().getBytes());
  189. // Return the dialect strings
  190. return vec;
  191. }
  192. /**
  193. * Get the local nodes workstation details, if it is running an SMB server.
  194. */
  195. private static void CheckLocalNode() {
  196. try {
  197. // Make sure the local node checked flag is set, or we are going to loop
  198. m_localChecked = true;
  199. // Connect to the local node
  200. PCShare shr = new PCShare(InetAddress.getLocalHost().getHostName().toUpperCase(), "IPC$", getDefaultUserName(),
  201. getDefaultPassword());
  202. AdminSession admSess = OpenAdminSession(shr);
  203. // Get the local workstation details
  204. WorkstationInfo wrkInfo = admSess.getWorkstationInfo();
  205. if ( wrkInfo != null) {
  206. // Set the local domain/workgroup name
  207. m_localDomain = wrkInfo.getDomain();
  208. }
  209. // Close the admin session
  210. admSess.CloseSession();
  211. }
  212. catch (Exception ex) {
  213. }
  214. }
  215. /**
  216. * Connect to a remote device.
  217. *
  218. * @param shr Remote device details
  219. * @param sess SMB session.
  220. * @param devtyp Device type to connect to.
  221. * @return Tree identifier if successful, else -1.
  222. * @exception java.io.IOException If an I/O error occurs
  223. * @exception org.alfresco.jlan.smb.UnsupportedDeviceTypeException If the device type is not
  224. * supported by this SMB dialect
  225. * @exception SMBException If an SMB error occurs
  226. */
  227. private final static int ConnectDevice(PCShare shr, Session sess, int devtyp)
  228. throws java.io.IOException, UnsupportedDeviceTypeException, SMBException {
  229. // DEBUG
  230. if ( Debug.EnableInfo && hasSessionDebug())
  231. Debug.println("** Connecting to " + shr.getNodeName() + " " + shr.getShareName() + " (" + shr.getUserName()
  232. + "/********)");
  233. // Create a tree connect packet
  234. SMBPacket pkt = new SMBPacket();
  235. pkt.setProcessId(sess.getProcessId());
  236. pkt.setFlags(sess.getDefaultFlags());
  237. pkt.setFlags2(sess.getDefaultFlags2());
  238. // Set the user id
  239. pkt.setUserId(sess.getUserId());
  240. // Determine if Unicode strings should be used, if so then use the TreeConnectAndX SMB
  241. if ( pkt.isUnicode()) {
  242. // Use the TreeConnectAndX SMB request
  243. pkt.setCommand(PacketType.TreeConnectAndX);
  244. // Set the parameter words
  245. pkt.setParameterCount(4);
  246. pkt.setAndXCommand(0xFF);
  247. pkt.setParameter(1, 0); // offset to next command
  248. pkt.setParameter(2, 0); // flags
  249. pkt.setParameter(3, 1); // password length, just count the null
  250. // Pack the password and share details
  251. pkt.resetBytePointer();
  252. pkt.packByte(0);
  253. StringBuffer uncPath = new StringBuffer();
  254. uncPath.append("\\\\");
  255. uncPath.append(shr.getNodeName());
  256. uncPath.append("\\");
  257. uncPath.append(shr.getShareName());
  258. pkt.packString(uncPath.toString(), true);
  259. switch (devtyp) {
  260. // Disk device
  261. case SMBDeviceType.Disk:
  262. pkt.packString("A:", false);
  263. break;
  264. // Printer device
  265. case SMBDeviceType.Printer:
  266. pkt.packString("LPT1:", false);
  267. break;
  268. // Pipe device
  269. case SMBDeviceType.Pipe:
  270. pkt.packString("IPC", false);
  271. break;
  272. }
  273. // Set the byte count for the request
  274. pkt.setByteCount();
  275. }
  276. else {
  277. // Use the older TreeConnect SMB request
  278. pkt.setCommand(PacketType.TreeConnect);
  279. // Set the parameter words
  280. pkt.setParameterCount(0);
  281. // Pack the request details
  282. StringBuffer shrbuf = new StringBuffer();
  283. shrbuf.append(DataType.ASCII);
  284. shrbuf.append("\\\\");
  285. shrbuf.append(shr.getNodeName().toUpperCase());
  286. shrbuf.append("\\");
  287. shrbuf.append(shr.getShareName().toUpperCase());
  288. shrbuf.append((char) 0x00);
  289. shrbuf.append(DataType.ASCII);
  290. shrbuf.append(shr.getPassword());
  291. shrbuf.append((char) 0x00);
  292. // Set the device type to be connected to
  293. shrbuf.append(DataType.ASCII);
  294. switch (devtyp) {
  295. // Disk device
  296. case SMBDeviceType.Disk:
  297. shrbuf.append("A:");
  298. break;
  299. // Printer device
  300. case SMBDeviceType.Printer:
  301. shrbuf.append("LPT1:");
  302. break;
  303. // Pipe device
  304. case SMBDeviceType.Pipe:
  305. shrbuf.append("IPC");
  306. break;
  307. }
  308. shrbuf.append((char) 0x00);
  309. // Copy the data bytes string to the SMB packet
  310. pkt.setBytes(shrbuf.toString().getBytes());
  311. }
  312. // Send/receive the SMB tree connect packet
  313. pkt.ExchangeSMB(sess, pkt);
  314. // Check if a valid response was received
  315. if ( pkt.isValidResponse()) {
  316. // Check for a TreeConnect or TreeConnectAndX response
  317. if ( pkt.getCommand() == PacketType.TreeConnect && pkt.getParameterCount() == 2)
  318. return pkt.getParameter(1);
  319. else if ( pkt.getCommand() == PacketType.TreeConnectAndX && pkt.getParameterCount() == 3)
  320. return pkt.getTreeId();
  321. }
  322. // Invalid response/error occurred
  323. if ( pkt.isLongErrorCode())
  324. throw new SMBException(SMBStatus.NTErr, pkt.getLongErrorCode());
  325. else
  326. throw new SMBException(pkt.getErrorClass(), pkt.getErrorCode());
  327. }
  328. /**
  329. * Connect to a remote file server.
  330. *
  331. * @param shr PC share information and access control information.
  332. * @param sess SMB negotiate packet containing the receive negotiate packet.
  333. * @param negpkt Negotiate SMB packet response.
  334. * @param settings Session settings
  335. * @exception java.io.IOException If an I/O error occurs.
  336. * @exception SMBException Invalid username and/or password specified.
  337. */
  338. private final static void ConnectSession(PCShare shr, Session sess, SMBPacket negpkt, SessionSettings settings)
  339. throws java.io.IOException, SMBException {
  340. // Set the session process id
  341. sess.setProcessId(negpkt.getProcessId());
  342. // Set the security mode flags
  343. int keyLen = 0;
  344. boolean unicodeStr = false;
  345. int encAlgorithm = PasswordEncryptor.LANMAN;
  346. int defFlags2 = 0;
  347. if ( sess.getDialect() == Dialect.NT) {
  348. // Read the returned negotiate parameters, for NT dialect the parameters are not aligned
  349. negpkt.resetParameterPointer();
  350. negpkt.skipBytes(2); // skip the dialect index
  351. sess.setSecurityMode(negpkt.unpackByte());
  352. // Set the maximum virtual circuits and multiplxed requests allowed by the server
  353. sess.setMaximumMultiplexedRequests(negpkt.unpackWord());
  354. sess.setMaximumVirtualCircuits(negpkt.unpackWord());
  355. // Set the maximum buffer size
  356. sess.setMaximumPacketSize(negpkt.unpackInt());
  357. // Skip the maximum raw buffer size and session key
  358. negpkt.skipBytes(8);
  359. // Set the server capabailities
  360. sess.setCapabilities(negpkt.unpackInt());
  361. // Get the server system time and timezone
  362. SMBDate srvTime = NTTime.toSMBDate(negpkt.unpackLong());
  363. int tzone = negpkt.unpackWord();
  364. // Get the encryption key length
  365. keyLen = negpkt.unpackByte();
  366. // Indicate that strings are UniCode
  367. unicodeStr = true;
  368. // Use NTLMv1 password encryption
  369. encAlgorithm = PasswordEncryptor.NTLM1;
  370. // Set the default flags for subsequent SMB requests
  371. defFlags2 = SMBPacket.FLG2_LONGFILENAMES + SMBPacket.FLG2_LONGERRORCODE;
  372. if ( sess.supportsUnicode())
  373. defFlags2 += SMBPacket.FLG2_UNICODE;
  374. if ( isSMBSigningEnabled())
  375. defFlags2 += SMBPacket.FLG2_SECURITYSIG;
  376. }
  377. else if ( sess.getDialect() > Dialect.CorePlus) {
  378. // Set the security mode and encrypted password mode
  379. int secMode = negpkt.getParameter(1);
  380. sess.setSecurityMode((secMode & 0x01) != 0 ? Session.SecurityModeUser : Session.SecurityModeShare);
  381. if ( negpkt.getParameterCount() >= 11)
  382. keyLen = negpkt.getParameter(11) & 0xFF; // should always be 8
  383. // Set the maximum virtual circuits and multiplxed requests allowed by the server
  384. sess.setMaximumMultiplexedRequests(negpkt.getParameter(3));
  385. sess.setMaximumVirtualCircuits(negpkt.getParameter(4));
  386. // Check if Unicode strings are being used
  387. if ( negpkt.isUnicode())
  388. unicodeStr = true;
  389. // Set the default flags for subsequent SMB requests
  390. defFlags2 = SMBPacket.FLG2_LONGFILENAMES;
  391. }
  392. // Set the default packet flags for this session
  393. sess.setDefaultFlags2(defFlags2);
  394. // Get the server details from the negotiate SMB packet
  395. if ( negpkt.getByteCount() > 0) {
  396. // Get the returned byte area length and offset
  397. int bytsiz = negpkt.getByteCount();
  398. int bytpos = negpkt.getByteOffset();
  399. byte[] buf = negpkt.getBuffer();
  400. // Extract the challenge response key, if specified
  401. if ( keyLen > 0) {
  402. // Allocate a buffer for the challenge response key
  403. byte[] encryptKey = new byte[keyLen];
  404. // Copy the challenge response key
  405. System.arraycopy(buf, bytpos, encryptKey, 0, keyLen);
  406. bytpos += keyLen;
  407. // Set the sessions encryption key
  408. sess.setEncryptionKey(encryptKey);
  409. // DEBUG
  410. if ( Debug.EnableInfo && Session.hasDebugOption(Session.DBGDumpPacket)) {
  411. Debug.print("** Encryption Key: ");
  412. Debug.print(HexDump.hexString(encryptKey));
  413. Debug.println(", length = " + keyLen);
  414. }
  415. }
  416. // Extract the domain name
  417. String dom;
  418. if ( unicodeStr == false)
  419. dom = DataPacker.getString(buf, bytpos, bytsiz);
  420. else
  421. dom = DataPacker.getUnicodeString(buf, bytpos, bytsiz / 2);
  422. sess.setDomain(dom);
  423. // DEBUG
  424. if ( Debug.EnableInfo && Session.hasDebugOption(Session.DBGDumpPacket))
  425. Debug.println("** Server domain : " + sess.getDomain() + ".");
  426. }
  427. // Set the password string, if encrypted passwords are required then
  428. // generate a 24 byte encrypted password.
  429. byte[] password = null;
  430. if ( sess.hasEncryptionKey() && shr.isNullLogon() == false) {
  431. try {
  432. // Generate a 24 byte encrypted password
  433. password = m_encryptor.generateEncryptedPassword(sess.getPassword(), sess.getEncryptionKey(), encAlgorithm);
  434. // DEBUG
  435. if ( Debug.EnableInfo && Session.hasDebugOption(Session.DBGDumpPacket)) {
  436. Debug.print("** Encrypted Password (");
  437. Debug.print(PasswordEncryptor.getAlgorithmName(encAlgorithm));
  438. Debug.print(") : ");
  439. Debug.println(HexDump.hexString(password));
  440. }
  441. // If SMB signing is enabled then generated a session key
  442. if ( (defFlags2 & SMBPacket.FLG2_SECURITYSIG) != 0) {
  443. // Create the session key
  444. byte[] sessKey = m_encryptor.generateSessionKey(sess.getPassword(), sess.getEncryptionKey(),
  445. PasswordEncryptor.NTLM1);
  446. // Enable SMB signing for this session
  447. sess.enableSMBSigning(sessKey);
  448. // DEBUG
  449. if ( Debug.EnableInfo && Session.hasDebugOption(Session.DBGSigning))
  450. Debug.print("** SMB signing enabled, session key=" + HexDump.hexString(sessKey, " "));
  451. }
  452. }
  453. catch (NoSuchAlgorithmException ex) {
  454. throw new IOException("Missing security provider - " + ex.toString());
  455. }
  456. }
  457. else {
  458. // Use a plain text password
  459. password = sess.getPassword().getBytes();
  460. }
  461. // Create a session setup packet
  462. SMBPacket pkt = new SMBPacket();
  463. pkt.setCommand(PacketType.SessionSetupAndX);
  464. pkt.setFlags(sess.getDefaultFlags());
  465. pkt.setFlags2(sess.getDefaultFlags2());
  466. // Check if the negotiated SMB dialect is NT LM 1.2 or an earlier dialect
  467. if ( sess.getDialect() == Dialect.NT) {
  468. // NT LM 1.2 SMB dialect
  469. pkt.setParameterCount(13);
  470. pkt.setAndXCommand(0xFF); // no secondary command
  471. pkt.setParameter(1, 0); // offset to next command
  472. pkt.setParameter(2, SessionFactory.DefaultPacketSize());
  473. pkt.setParameter(3, sess.getMaximumMultiplexedRequests());
  474. // Set the virtual circuit number
  475. //
  476. // Using a value of zero will cause a Windows server to disconnect all other sessions
  477. // from this
  478. // client.
  479. pkt.setParameter(4, settings.getVirtualCircuit());
  480. pkt.setParameterLong(5, 0); // session key
  481. // Set the share password length(s)
  482. pkt.setParameter(7, shr.isNullLogon() ? 1 : 0); // ANSI password length
  483. pkt.setParameter(8, shr.isNullLogon() ? 0 : password.length); // Unicode password length
  484. pkt.setParameter(9, 0); // reserved, must be zero
  485. pkt.setParameter(10, 0); // reserved, must be zero
  486. // Send the client capabilities
  487. int caps = Capability.LargeFiles + Capability.Unicode + Capability.NTSMBs + Capability.NTStatus
  488. + Capability.RemoteAPIs;
  489. pkt.setParameterLong(11, caps);
  490. // Store the encrypted password
  491. pkt.setPosition(pkt.getByteOffset());
  492. if ( shr.isNullLogon()) {
  493. int pos = pkt.getByteOffset();
  494. pkt.getBuffer()[pos++] = (byte) 0;
  495. pkt.setPosition(pos);
  496. }
  497. else
  498. pkt.packBytes(password, password.length);
  499. // Pack the account name
  500. pkt.packString(shr.getUserName(), sess.supportsUnicode());
  501. // Check if the share has a domain, if not then use the default domain string
  502. if ( shr.isNullLogon())
  503. pkt.packString("", sess.supportsUnicode());
  504. else if ( shr.hasDomain())
  505. pkt.packString(shr.getDomain(), sess.supportsUnicode());
  506. else
  507. pkt.packString(getDefaultDomain(), sess.supportsUnicode());
  508. pkt.packString("Java VM", sess.supportsUnicode());
  509. pkt.packString("Alfresco-JLAN", sess.supportsUnicode());
  510. // Set the byte count
  511. pkt.setByteCount();
  512. }
  513. else {
  514. // Earlier SMB dialect
  515. pkt.setUserId(1);
  516. pkt.setParameterCount(10);
  517. pkt.setAndXCommand(0xFF); // no secondary command
  518. pkt.setParameter(1, 0); // offset to next command
  519. pkt.setParameter(2, SessionFactory.DefaultPacketSize());
  520. pkt.setParameter(3, 2); // max multiplexed pending requests
  521. pkt.setParameter(4, 0); // sess.getSessionId ());
  522. pkt.setParameter(5, 0);
  523. pkt.setParameter(6, 0);
  524. pkt.setParameter(7, shr.isNullLogon() ? 0 : password.length);
  525. pkt.setParameter(8, 0);
  526. pkt.setParameter(9, 0);
  527. // Put the password into the SMB packet
  528. byte[] buf = pkt.getBuffer();
  529. int pos = pkt.getByteOffset();
  530. if ( shr.isNullLogon())
  531. buf[pos++] = (byte) 0;
  532. else {
  533. for (int i = 0; i < password.length; i++)
  534. buf[pos++] = password[i];
  535. }
  536. // Build the account/client details
  537. StringBuffer clbuf = new StringBuffer();
  538. clbuf.append(shr.getUserName());
  539. clbuf.append((char) 0x00);
  540. // Check if the share has a domain, if not then use the unknown domain string
  541. if ( shr.isNullLogon())
  542. clbuf.append("");
  543. else if ( shr.hasDomain())
  544. clbuf.append(shr.getDomain());
  545. else
  546. clbuf.append(getDefaultDomain());
  547. clbuf.append((char) 0x00);
  548. clbuf.append("Java VM");
  549. clbuf.append((char) 0x00);
  550. clbuf.append("Alfresco-JLAN");
  551. clbuf.append((char) 0x00);
  552. // Copy the remaining data to the SMB packet
  553. byte[] byts = clbuf.toString().getBytes();
  554. for (int i = 0; i < byts.length; i++)
  555. buf[pos++] = byts[i];
  556. pkt.setByteCount(password.length + byts.length);
  557. }
  558. // Set the process id
  559. pkt.setProcessId(sess.getProcessId());
  560. // Exchange an SMB session setup packet with the remote file server
  561. pkt.ExchangeSMB(sess, pkt, true);
  562. // Save the session user id
  563. sess.setUserId(pkt.getUserId());
  564. // Check if SMB signing is enabled
  565. if ( pkt.hasSecuritySignature()) {
  566. }
  567. // Check if the session was created as a guest
  568. if ( pkt.getParameterCount() >= 3) {
  569. // Set the guest status for the session
  570. sess.setGuest(pkt.getParameter(2) != 0 ? true : false);
  571. }
  572. // The response packet should also have the server OS, LAN Manager type
  573. // and primary domain name.
  574. if ( pkt.getByteCount() > 0) {
  575. // Get the server OS
  576. pkt.setPosition(pkt.getByteOffset());
  577. String srvOS = pkt.unpackString(unicodeStr);
  578. sess.setOperatingSystem(srvOS);
  579. String lanman = pkt.unpackString(unicodeStr);
  580. sess.setLANManagerType(lanman);
  581. String domain = pkt.unpackString(unicodeStr);
  582. // Check if we have the primary domain for this session
  583. if ( domain != null && domain.length() > 0 && (sess.getDomain() == null || sess.getDomain().length() == 0))
  584. sess.setDomain(domain);
  585. }
  586. // Check for a core protocol session, set the maximum packet size
  587. if ( sess.getDialect() == Dialect.Core || sess.getDialect() == Dialect.CorePlus) {
  588. // Set the maximum packet size to be used on this session
  589. sess.setMaximumPacketSize(pkt.getParameter(2));
  590. }
  591. }
  592. /**
  593. * Create a new SMB disk session
  594. *
  595. * @param shr PC share information and access control information.
  596. * @param pkt SMB negotiate packet containing the receive negotiate packet.
  597. * @param netSess NetBIOS transport session connected to the remote file server.
  598. * @param dia SMB dialect that has been negotiated for this session.
  599. * @param settings Session settings
  600. * @return SMBDiskSession if the request was successful, else null
  601. * @exception java.io.IOException If an I/O error occurs.
  602. * @exception SMBException Invalid username and/or password.
  603. */
  604. private final static DiskSession CreateDiskSession(PCShare shr, SMBPacket pkt, NetworkSession netSess, int dialect,
  605. SessionSettings settings)
  606. throws java.io.IOException, SMBException {
  607. // Create the SMB disk session depending on the SMB dialect negotiated
  608. DiskSession sess;
  609. if ( dialect == Dialect.Core || dialect == Dialect.CorePlus) {
  610. // Create a core protocol disk session
  611. sess = new CoreDiskSession(shr, dialect);
  612. }
  613. else {
  614. // Create a CIFS protocol disk session
  615. sess = new CIFSDiskSession(shr, dialect);
  616. // Set the maximum packet size allowed on this session
  617. sess.setMaximumPacketSize(pkt.getParameter(2));
  618. }
  619. // Attach the network session to the SMB session
  620. sess.setSession(netSess);
  621. // Connect the session
  622. ConnectSession(shr, sess, pkt, settings);
  623. // Connect to the remote share/disk
  624. try {
  625. int treeId = ConnectDevice(shr, sess, SMBDeviceType.Disk);
  626. if ( treeId != -1) {
  627. // Set the disk sessions allocated tree identifier, and return the
  628. // session.
  629. sess.setTreeId(treeId);
  630. return sess;
  631. }
  632. }
  633. catch (UnsupportedDeviceTypeException ex) {
  634. }
  635. // Failed to connect to the remote disk
  636. return null;
  637. }
  638. /**
  639. * Create a new SMB session that is connected to a remote pipe resource.
  640. *
  641. * @param shr PC share information and access control information.
  642. * @param pkt SMB negotiate packet containing the received negotiate response.
  643. * @param netSess Network transport session connected to the remote file server.
  644. * @param dia SMB dialect that has been negotiated for this session.
  645. * @param settings Session settings
  646. * @return SMBIPCSession if successful, else null
  647. * @exception java.io.IOException If an I/O error occurs
  648. * @exception SMBException Invalid username and/or password.
  649. */
  650. private final static IPCSession CreatePipeSession(PCShare shr, SMBPacket pkt, NetworkSession netSess, int dialect,
  651. SessionSettings settings)
  652. throws java.io.IOException, SMBException {
  653. // Create the SMB pipe session
  654. CIFSPipeSession sess = new CIFSPipeSession(shr, dialect);
  655. sess.setSession(netSess);
  656. // Check if the dialect is higher than core protocol
  657. if ( dialect > Dialect.CorePlus) {
  658. // Set the maximum packet size allowed on this session
  659. sess.setMaximumPacketSize(pkt.getParameter(2));
  660. }
  661. // Connect the session
  662. ConnectSession(shr, sess, pkt, settings);
  663. // Connect to the remote pipe resource
  664. try {
  665. int treeId = ConnectDevice(shr, sess, SMBDeviceType.Pipe);
  666. if ( treeId != -1) {
  667. // Set the pipe sessions allocated tree identifier, and return the
  668. // session.
  669. sess.setTreeId(treeId);
  670. return sess;
  671. }
  672. }
  673. catch (UnsupportedDeviceTypeException ex) {
  674. }
  675. // Failed to connect to the remote pipe
  676. return null;
  677. }
  678. /**
  679. * Create a new SMB session that is connected to a remote printer resource.
  680. *
  681. * @param shr PC share information and access control information.
  682. * @param pkt SMB negotiate packet containing the received negotiate response.
  683. * @param netSess Network transport session connected to the remote file server.
  684. * @param dia SMB dialect that has been negotiated for this session.
  685. * @param settings Session settings
  686. * @return SMBPrinterSession if successful, else null
  687. * @exception java.io.IOException If an I/O error occurs
  688. * @exception SMBException Invalid username and/or password.
  689. */
  690. private final static PrintSession CreatePrinterSession(PCShare shr, SMBPacket pkt, NetworkSession netSess, int dialect,
  691. SessionSettings settings)
  692. throws java.io.IOException, SMBException {
  693. // Create the SMB print session
  694. PrintSession sess = null;
  695. if ( dialect == Dialect.Core || dialect == Dialect.CorePlus) {
  696. // Create a core protocol print session
  697. sess = new CorePrintSession(shr, dialect);
  698. }
  699. else {
  700. // Create a CIFS protocol print session
  701. sess = new CIFSPrintSession(shr, dialect);
  702. // Set the maximum packet size allowed on this session
  703. sess.setMaximumPacketSize(pkt.getParameter(2));
  704. }
  705. // Attach the network session to the SMB session
  706. sess.setSession(netSess);
  707. // Connect the session
  708. ConnectSession(shr, sess, pkt, settings);
  709. // Connect to the remote printer device
  710. try {
  711. int treeId = ConnectDevice(shr, sess, SMBDeviceType.Printer);
  712. if ( treeId != -1) {
  713. // Set the print sessions allocated tree identifier, and return the
  714. // session.
  715. sess.setTreeId(treeId);
  716. return sess;
  717. }
  718. }
  719. catch (UnsupportedDeviceTypeException ex) {
  720. }
  721. // Failed to connect to the remote printer
  722. return null;
  723. }
  724. /**
  725. * Create a new SMB session
  726. *
  727. * @param shr PC share information and access control information.
  728. * @param pkt SMB negotiate packet containing the receive negotiate packet.
  729. * @param netSess Network transport session connected to the remote file server.
  730. * @param dia SMB dialect that has been negotiated for this session.
  731. * @param settings Session settings
  732. * @return SMBSession if the request was successful, else null
  733. * @exception java.io.IOException If an I/O error occurs
  734. * @exception SMBException Invalid username and/or password.
  735. */
  736. private final static Session CreateSession(PCShare shr, SMBPacket pkt, NetworkSession netSess, int dialect,
  737. SessionSettings settings)
  738. throws java.io.IOException, SMBException {
  739. // Create the SMB session
  740. Session sess = new Session(shr, dialect, null);
  741. sess.setSession(netSess);
  742. // Connect the session
  743. ConnectSession(shr, sess, pkt, settings);
  744. // Return the SMB session
  745. return sess;
  746. }
  747. /**
  748. * Return the default SMB packet size
  749. *
  750. * @return Default SMB packet size to allocate.
  751. */
  752. protected final static int DefaultPacketSize() {
  753. return m_defPktSize;
  754. }
  755. /**
  756. * Disable session factory debugging.
  757. */
  758. public final static void disableDebug() {
  759. m_debug = false;
  760. }
  761. /**
  762. * Disable the specified SMB dialect when setting up new sessions.
  763. *
  764. * @param d int
  765. */
  766. public final static void disableDialect(int d) {
  767. // Check if the dialect is enabled
  768. if ( m_defaultSettings.getDialects().hasDialect(d)) {
  769. // Disable the dialect
  770. m_defaultSettings.getDialects().RemoveDialect(d);
  771. }
  772. }
  773. /**
  774. * Enable session factory debug output.
  775. */
  776. public final static void enableDebug() {
  777. m_debug = true;
  778. }
  779. /**
  780. * Enable the specified SMB dialect when setting up new sessions.
  781. *
  782. * @param d int
  783. */
  784. public final static void enableDialect(int d) {
  785. // Check if the dialect is already enabled
  786. if ( m_defaultSettings.getDialects().hasDialect(d))
  787. return;
  788. // Enable the specified dialect
  789. m_defaultSettings.getDialects().AddDialect(d);
  790. }
  791. /**
  792. * Find the browse master for this network.
  793. *
  794. * @return NetBIOSName
  795. * @exception SMBException The exception description.
  796. */
  797. public final static NetBIOSName findBrowseMaster()
  798. throws SMBException, java.io.IOException {
  799. // Find a browse master to query for the domain list
  800. int retry = 0;
  801. NetBIOSName netName = null;
  802. while (retry++ < 5 && netName == null) {
  803. try {
  804. netName = NetBIOSSession.FindName(NetBIOSName.BrowseMasterName, NetBIOSName.BrowseMasterGroup,
  805. BROADCAST_LOOKUP_TIMEOUT);
  806. }
  807. catch (Exception ex) {
  808. }
  809. }
  810. // Return the browse master NetBIOS name details, or null
  811. return netName;
  812. }
  813. /**
  814. * Return the list of SMB dialects that will be negotiated when a new session is created.
  815. *
  816. * @return org.alfresco.jlan.smb.DialectSelector List of enabled SMB dialects.
  817. */
  818. public final static DialectSelector getDefaultDialects() {
  819. return m_defaultSettings.getDialects();
  820. }
  821. /**
  822. * Return the default domain name
  823. *
  824. * @return String
  825. */
  826. public static String getDefaultDomain() {
  827. return m_defDomain;
  828. }
  829. /**
  830. * Return the default password.
  831. *
  832. * @return java.lang.String
  833. */
  834. public static String getDefaultPassword() {
  835. return m_defPassword;
  836. }
  837. /**
  838. * Return the default user name.
  839. *
  840. * @return java.lang.String
  841. */
  842. public static String getDefaultUserName() {
  843. return m_defUserName;
  844. }
  845. /**
  846. * Return the default session settings
  847. *
  848. * @return SessionSettings
  849. */
  850. public static SessionSettings getDefaultSettings() {
  851. return m_defaultSettings;
  852. }
  853. /**
  854. * Return the list of available domains/workgroups.
  855. *
  856. * @return org.alfresco.jlan.smb.SMBServerList List of available domains.
  857. * @exception SMBException If an SMB error occurs.
  858. * @exception IOException If an I/O error occurs.
  859. */
  860. public final static ServerList getDomainList()
  861. throws SMBException, IOException {
  862. // Check if this node is a browse master
  863. PCShare admShr = null;
  864. AdminSession admSess = null;
  865. try {
  866. // Try and connect to the local host, it may be a browse master
  867. String localHost = InetAddress.getLocalHost().getHostAddress();
  868. admShr = new PCShare(localHost, "", getDefaultUserName(), getDefaultPassword());
  869. admSess = SessionFactory.OpenAdminSession(admShr);
  870. // Get the domain list
  871. ServerList domList = admSess.getServerList(ServerType.DomainEnum);
  872. admSess.CloseSession();
  873. return domList;
  874. }
  875. catch (SMBException ex) {
  876. }
  877. catch (IOException ex) {
  878. }
  879. // Find a browse master to query for the domain list
  880. NetBIOSName browseMaster = NetBIOSSession.FindName(NetBIOSName.BrowseMasterName, NetBIOSName.BrowseMasterGroup, 2000);
  881. if ( browseMaster == null)
  882. return null;
  883. // Connect to the domain browse master IPC$ named pipe share
  884. String browseAddr = null;
  885. if ( browseMaster.numberOfAddresses() > 1) {
  886. // Find the best address to connect to the browse master
  887. int addrIdx = browseMaster.findBestMatchAddress(getLocalTcpipAddresses());
  888. if ( addrIdx != -1)
  889. browseAddr = browseMaster.getIPAddressString(addrIdx);
  890. }
  891. else {
  892. // Only one address available
  893. browseAddr = browseMaster.getIPAddressString(0);
  894. }
  895. // Connect to the browse master
  896. admShr = new PCShare(browseAddr, "", getDefaultUserName(), getDefaultPassword());
  897. admSess = SessionFactory.OpenAdminSession(admShr);
  898. ServerList domList = null;
  899. try {
  900. // Ask the browse master for the domain list
  901. domList = admSess.getServerList(ServerType.DomainEnum);
  902. }
  903. catch (SMBException ex) {
  904. // Add the local domain to the list as we can't get the list from the browse master
  905. domList = new ServerList();
  906. domList.addServerInfo(new RAPServerInfo(admSess.getSession().getDomain(), true));
  907. }
  908. // Close the session to the browse master
  909. admSess.CloseSession();
  910. return domList;
  911. }
  912. /**
  913. * Return the local browse master node name.
  914. *
  915. * @return Local browse master node name string.
  916. */
  917. private String getLocalBrowser() {
  918. return m_localBrowseMaster;
  919. }
  920. /**
  921. * Return the local domain name, if known.
  922. *
  923. * @return Local domain name string, else null.
  924. */
  925. public static String getLocalDomain() {
  926. // Check if the local node details have been checked
  927. if ( m_localChecked == false)
  928. CheckLocalNode();
  929. // Return the local domain/workgroup name
  930. return m_localDomain;
  931. }
  932. /**
  933. * Return a list of the local servers, if the local domain/workgroup can be determined.
  934. *
  935. * @return org.alfresco.jlan.smb.SMBServerList
  936. * @exception SMBException The exception description.
  937. * @exception java.io.IOException The exception description.
  938. */
  939. public static ServerList getLocalServerList()
  940. throws SMBException, IOException, UnknownLocalDomainException {
  941. // Check if the local node details have been checked
  942. if ( m_localChecked == false)
  943. CheckLocalNode();
  944. // Check if the local domain/workgroup name is known
  945. if ( getLocalDomain().length() == 0)
  946. throw new UnknownLocalDomainException();
  947. // Return the local server list
  948. return getServerList(getLocalDomain());
  949. }
  950. /**
  951. * Return the NetBIOS scope id, or null if not set
  952. *
  953. * @return String
  954. */
  955. public static String getNetBIOSNameScope() {
  956. return m_defaultSettings.getNetBIOSNameScope();
  957. }
  958. /**
  959. * Return the NetBIOS socket number that new sessions are connected to.
  960. *
  961. * @return int NetBIOS session socket number.
  962. */
  963. public static int getNetBIOSPort() {
  964. return m_defaultSettings.getNetBIOSSessionPort();
  965. }
  966. /**
  967. * Return the primary connection protocol (either Protocol.TCPNetBIOS or Protocol.NativeSMB)
  968. *
  969. * @return int
  970. */
  971. public static final int getPrimaryProtocol() {
  972. return m_defaultSettings.getPrimaryProtocol();
  973. }
  974. /**
  975. * Return the secondary connection protocol (Protocol.TCPNetBIOS, Protocol.NativeSMB or
  976. * Protocol.None)
  977. *
  978. * @return int
  979. */
  980. public static final int getSecondaryProtocol() {
  981. return m_defaultSettings.getSecondaryProtocol();
  982. }
  983. /**
  984. * Get the list of nodes in the specified domain
  985. *
  986. * @param domnam Domain name to return nodes for
  987. * @return SMBServerList containing the details of the nodes found
  988. * @exception java.io.IOException I/O error occurred
  989. * @exception SMBException SMB error occurred
  990. */
  991. public final static ServerList getServerList(String domnam)
  992. throws java.io.IOException, SMBException {
  993. // Chain to the main server list method
  994. return getServerList(domnam, 0x0FFFFFFF);
  995. }
  996. /**
  997. * Get the list of nodes in the specified domain that match the node type flags.
  998. *
  999. * @param domnam Domain name to return nodes for
  1000. * @param srvFlags Node type flags
  1001. * @return SMBServerList containing the details of the nodes found.
  1002. * @exception SMBException If an SMB exception occurs.
  1003. * @exception java.io.IOException If an I/O error occurs.
  1004. */
  1005. public final static ServerList getServerList(String domnam, int srvFlags)
  1006. throws SMBException, java.io.IOException {
  1007. // Check if this node is the browse master for the specified domain
  1008. PCShare admShr = null;
  1009. AdminSession admSess = null;
  1010. String browseMaster = null;
  1011. try {
  1012. // Try and connect to the local host, it may be a browse master
  1013. // String localHost = InetAddress.getLocalHost().getHostName().toUpperCase();
  1014. String localHost = InetAddress.getLocalHost().getHostAddress();
  1015. admShr = new PCShare(localHost, "", getDefaultUserName(), getDefaultPassword());
  1016. admSess = SessionFactory.OpenAdminSession(admShr);
  1017. // Check if the local domain is the required domain
  1018. if ( admSess.getSession().getDomain() != null && admSess.getSession().getDomain().compareTo(domnam) == 0) {
  1019. // Get the local domains server list
  1020. ServerList srvList = admSess.getServerList(srvFlags & 0x0FFFFFFF);
  1021. admSess.CloseSession();
  1022. return srvList;
  1023. }
  1024. // Get the domain list
  1025. ServerList domList = admSess.getServerList(ServerType.DomainEnum);
  1026. if ( domList != null) {
  1027. // Check if we have found the requested domain in the list
  1028. int i = 0;
  1029. while (i < domList.NumberOfServers() && browseMaster == null) {
  1030. // Check if the current server information is the requested domain
  1031. RAPServerInfo srvInfo = domList.getServerInfo(i);
  1032. if ( srvInfo.getServerName().compareTo(domnam) == 0 && srvInfo.getComment().length() > 0) {
  1033. // Set the browse master node name for the requested domain
  1034. browseMaster = srvInfo.getComment();
  1035. }
  1036. else {
  1037. // Update the server information index
  1038. i++;
  1039. }
  1040. } // end while server information
  1041. // Check if the browse master for the requested domain is the current node,
  1042. // if so then keep the admin session open, if not then close the session.
  1043. if ( browseMaster != null && browseMaster.compareTo(localHost) != 0) {
  1044. // Close the admin session
  1045. admSess.CloseSession();
  1046. admSess = null;
  1047. }
  1048. }
  1049. }
  1050. catch (SMBException ex) {
  1051. if ( Debug.EnableError && hasDebug())
  1052. Debug.println("getServerList (): " + ex.toString());
  1053. if ( admSess != null) {
  1054. admSess.CloseSession();
  1055. admSess = null;
  1056. }
  1057. }
  1058. catch (java.io.IOException ex) {
  1059. if ( Debug.EnableError && hasDebug())
  1060. Debug.println("getServerList (): " + ex.toString());
  1061. if ( admSess != null) {
  1062. admSess.CloseSession();
  1063. admSess = null;
  1064. }
  1065. }
  1066. // If the browse master for the requested domain has not been set then try
  1067. // and find it via a NetBIOS name lookup
  1068. if ( browseMaster == null) {
  1069. // Try to find the browse master via broadcast
  1070. int retry = 0;
  1071. while (retry++ < 5 && browseMaster == null) {
  1072. try {
  1073. NetBIOSName netName = NetBIOSSession.FindName(domnam.toUpperCase(), NetBIOSName.MasterBrowser,
  1074. BROADCAST_LOOKUP_TIMEOUT);
  1075. if ( netName != null) {
  1076. // Get the browse master IP address
  1077. if ( netName.numberOfAddresses() > 1) {
  1078. // Find the best address to connect to the browse master
  1079. int addrIdx = netName.findBestMatchAddress(getLocalTcpipAddresses());
  1080. if ( addrIdx != -1)
  1081. browseMaster = netName.getIPAddressString(addrIdx);
  1082. }
  1083. else {
  1084. // Only one address available
  1085. browseMaster = netName.getIPAddressString(0);
  1086. }
  1087. }
  1088. }
  1089. catch (Exception ex) {
  1090. }
  1091. }
  1092. }
  1093. // Connect to the domain browse master IPC$ named pipe share, if not already
  1094. // connected.
  1095. if ( admSess == null) {
  1096. // Connect to the remote domains browse master
  1097. admShr = new PCShare(browseMaster, "", getDefaultUserName(), getDefaultPassword());
  1098. admSess = SessionFactory.OpenAdminSession(admShr);
  1099. }
  1100. // Return the server list for the domain, make sure we do not search for domains, mask
  1101. // out the domain search flags.
  1102. ServerList srvList = admSess.getServerList(srvFlags & 0x0FFFFFFF);
  1103. admSess.CloseSession();
  1104. return srvList;
  1105. }
  1106. /**
  1107. * Return the next session id
  1108. *
  1109. * @return int
  1110. */
  1111. private static synchronized int getSessionId() {
  1112. int sessId = m_sessIdx++ + (NetBIOSSession.getJVMIndex() * 100);
  1113. return sessId;
  1114. }
  1115. /**
  1116. * Get the list of local TCP/IP addresses
  1117. *
  1118. * @return InetAddress[]
  1119. */
  1120. private static synchronized InetAddress[] getLocalTcpipAddresses() {
  1121. // Get the list of local TCP/IP addresses
  1122. if ( m_localAddrList == null) {
  1123. try {
  1124. m_localAddrList = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
  1125. }
  1126. catch (UnknownHostException ex) {
  1127. }
  1128. }
  1129. // Return the address list
  1130. return m_localAddrList;
  1131. }
  1132. /**
  1133. * Determine if session factory debugging is enabled.
  1134. *
  1135. * @return boolean
  1136. */
  1137. public final static boolean hasDebug() {
  1138. return m_debug;
  1139. }
  1140. /**
  1141. * Determine if a global process id is used for all sessions
  1142. *
  1143. * @return boolean
  1144. */
  1145. public final static boolean hasGlobalProcessId() {
  1146. return m_globalPID;
  1147. }
  1148. /**
  1149. * Determine if the NetBIOS name scope is set
  1150. *
  1151. * @return boolean
  1152. */
  1153. public final static boolean hasNetBIOSNameScope() {
  1154. return m_defaultSettings.hasNetBIOSNameScope();
  1155. }
  1156. /**
  1157. * Determine if SMB session debugging is enabled.
  1158. *
  1159. * @return true if SMB session debugging is enabled, else false.
  1160. */
  1161. public final static boolean hasSessionDebug() {
  1162. return Session.hasDebug();
  1163. }
  1164. /**
  1165. * Determine if SMB signing is enabled
  1166. *
  1167. * @return boolean
  1168. */
  1169. public final static boolean isSMBSigningEnabled() {
  1170. return m_smbSigningEnabled;
  1171. }
  1172. /**
  1173. * Determine if received packets should validate the SMB signing value
  1174. *
  1175. * @return boolean
  1176. */
  1177. public final static boolean isReceivedSMBSigningEnabled() {
  1178. return m_smbSigningCheckRx;
  1179. }
  1180. /**
  1181. * Return a version string for this software release
  1182. *
  1183. * @return Software version number string
  1184. */
  1185. static final public String isVersion() {
  1186. return "4.0.0";
  1187. }
  1188. /**
  1189. * Open a connection to a remote server admin pipe
  1190. *
  1191. * @param shr Remote share information object.
  1192. * @return SMBAdminSession used to perform admin operations
  1193. * @exception java.io.Exception Network I/O error occurred.
  1194. * @exception java.net.UnkownHostException Remote node is unknown.
  1195. * @exception SMBException Failed to setup a new SMB session
  1196. */
  1197. static final public AdminSession OpenAdminSession(PCShare shr)
  1198. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1199. // Use the default timeout for the session
  1200. return OpenAdminSession(shr, getDefaultSettings());
  1201. }
  1202. /**
  1203. * Open a connection to a remote server admin pipe
  1204. *
  1205. * @param shr Remote share information object.
  1206. * @param settings Session settings
  1207. * @return SMBAdminSession used to perform admin operations
  1208. * @exception java.io.Exception Network I/O error occurred.
  1209. * @exception java.net.UnkownHostException Remote node is unknown.
  1210. * @exception SMBException Failed to setup a new SMB session
  1211. */
  1212. static final public AdminSession OpenAdminSession(PCShare shr, SessionSettings settings)
  1213. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1214. // Create a new IPC/pipe session to the remote admin pipe
  1215. shr.setShareName("IPC$");
  1216. IPCSession sess = (IPCSession) OpenSession(shr, SMBDeviceType.Pipe, settings);
  1217. // Create an admin session that can perform admin operations using the
  1218. // pipe session.
  1219. return new AdminSession(sess);
  1220. }
  1221. /**
  1222. * Open a connection to a remote file server disk share.
  1223. *
  1224. * @param shr Remote share information object.
  1225. * @return SMBSession used to access the remote share.
  1226. * @exception java.io.Exception Network I/O error occurred.
  1227. * @exception java.net.UnkownHostException Remote node is unknown.
  1228. * @exception SMBException Failed to setup a new SMB session
  1229. */
  1230. static final public DiskSession OpenDisk(PCShare shr)
  1231. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1232. // Create a new disk session
  1233. return (DiskSession) OpenSession(shr, SMBDeviceType.Disk, getDefaultSettings());
  1234. }
  1235. /**
  1236. * Open a connection to a remote file server disk share.
  1237. *
  1238. * @param shr Remote share information object.
  1239. * @param settings Session settings
  1240. * @return SMBSession used to access the remote share.
  1241. * @exception java.io.Exception Network I/O error occurred.
  1242. * @exception java.net.UnkownHostException Remote node is unknown.
  1243. * @exception SMBException Failed to setup a new SMB session
  1244. */
  1245. static final public DiskSession OpenDisk(PCShare shr, SessionSettings settings)
  1246. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1247. // Create a new disk session
  1248. return (DiskSession) OpenSession(shr, SMBDeviceType.Disk, settings);
  1249. }
  1250. /**
  1251. * Open a connection to a remote file server disk share using the existing sessions network
  1252. * session.
  1253. *
  1254. * @param shr Remote share information object.
  1255. * @param sess Existing connection to the remote server.
  1256. * @return SMBSession used to access the remote share.
  1257. * @exception java.io.Exception Network I/O error occurred.
  1258. * @exception java.net.UnkownHostException Remote node is unknown.
  1259. * @exception SMBException Failed to setup a new SMB session
  1260. */
  1261. static final public DiskSession OpenDisk(PCShare shr, Session sess)
  1262. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1263. // Create the SMB disk session depending on the SMB dialect negotiated
  1264. DiskSession diskSess;
  1265. if ( sess.getDialect() == Dialect.Core || sess.getDialect() == Dialect.CorePlus) {
  1266. // Create a core protocol disk session
  1267. diskSess = new CoreDiskSession(shr, sess.getDialect());
  1268. }
  1269. else {
  1270. // Create a CIFS protocol disk session
  1271. diskSess = new CIFSDiskSession(shr, sess.getDialect());
  1272. // Set the maximum packet size allowed on this session
  1273. diskSess.setMaximumPacketSize(sess.getMaximumPacketSize());
  1274. }
  1275. // Attach the network session to the SMB session
  1276. diskSess.setSession(sess.getSession());
  1277. // Copy settings from the original session
  1278. diskSess.setUserId(sess.getUserId());
  1279. diskSess.setProcessId(sess.getProcessId());
  1280. // Connect to the remote share/disk
  1281. try {
  1282. int treeId = ConnectDevice(shr, sess, SMBDeviceType.Disk);
  1283. if ( treeId != -1) {
  1284. // Set the disk sessions allocated tree identifier, and return the
  1285. // session.
  1286. diskSess.setTreeId(treeId);
  1287. return diskSess;
  1288. }
  1289. }
  1290. catch (UnsupportedDeviceTypeException ex) {
  1291. }
  1292. // Failed to connect to the remote disk
  1293. return null;
  1294. }
  1295. /**
  1296. * Open a connection to a remote pipe/IPC
  1297. *
  1298. * @param shr Remote share information object.
  1299. * @return SMBSession used to access the pipe/IPC session.
  1300. * @exception java.io.Exception Network I/O error occurred.
  1301. * @exception java.net.UnkownHostException Remote node is unknown.
  1302. * @exception SMBException Failed to setup a new SMB session
  1303. */
  1304. static final public IPCSession OpenPipe(PCShare shr)
  1305. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1306. // Create a new IPC/pipe session
  1307. return (IPCSession) OpenSession(shr, SMBDeviceType.Pipe, getDefaultSettings());
  1308. }
  1309. /**
  1310. * Open a connection to a remote pipe/IPC
  1311. *
  1312. * @param shr Remote share information object.
  1313. * @param settings Session settings
  1314. * @return SMBSession used to access the pipe/IPC session.
  1315. * @exception java.io.Exception Network I/O error occurred.
  1316. * @exception java.net.UnkownHostException Remote node is unknown.
  1317. * @exception SMBException Failed to setup a new SMB session
  1318. */
  1319. static final public IPCSession OpenPipe(PCShare shr, SessionSettings settings)
  1320. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1321. // Create a new IPC/pipe session
  1322. return (IPCSession) OpenSession(shr, SMBDeviceType.Pipe, settings);
  1323. }
  1324. /**
  1325. * Open a connection to a remote pipe/IPC, in data mode
  1326. *
  1327. * @param shr Remote share information object.
  1328. * @param pipeName String
  1329. * @return DataPipeFile used to read/write to the named pipe
  1330. * @exception java.io.Exception Network I/O error occurred.
  1331. * @exception java.net.UnkownHostException Remote node is unknown.
  1332. * @exception SMBException Failed to setup a new SMB session
  1333. */
  1334. static final public DataPipeFile OpenDataPipe(PCShare shr, String pipeName)
  1335. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1336. // Create a new pipe session and connect a file
  1337. return OpenDataPipe(shr, pipeName, getDefaultSettings());
  1338. }
  1339. /**
  1340. * Open a connection to a remote pipe/IPC, in data mode
  1341. *
  1342. * @param shr Remote share information object.
  1343. *
  1344. * @param settings Session settings
  1345. * @return DataPipeFile used to read/write to the named pipe
  1346. * @exception java.io.Exception Network I/O error occurred.
  1347. * @exception java.net.UnkownHostException Remote node is unknown.
  1348. * @exception SMBException Failed to setup a new SMB session
  1349. */
  1350. static final public DataPipeFile OpenDataPipe(PCShare shr, String pipeName, SessionSettings settings)
  1351. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1352. // Create a new IPC/pipe session
  1353. IPCSession sess = (IPCSession) OpenSession(shr, SMBDeviceType.Pipe, settings);
  1354. // Open the pipe file
  1355. // Check if we have negotiated NT dialect
  1356. if ( sess.getDialect() != Dialect.NT)
  1357. throw new SMBException(SMBStatus.NetErr, SMBStatus.NETUnsupported);
  1358. // Build the NTCreateAndX SMB packet
  1359. SMBPacket smbPkt = sess.m_pkt;
  1360. smbPkt.setFlags(sess.getDefaultFlags());
  1361. smbPkt.setFlags2(sess.getDefaultFlags2());
  1362. smbPkt.setCommand(PacketType.NTCreateAndX);
  1363. smbPkt.setUserId(sess.getUserId());
  1364. smbPkt.setTreeId(sess.getTreeId());
  1365. smbPkt.setParameterCount(24);
  1366. smbPkt.resetParameterPointer();
  1367. smbPkt.packByte(0xFF); // no chained command
  1368. smbPkt.packByte(0); // reserved
  1369. smbPkt.packWord(0); // AndX offset
  1370. smbPkt.packByte(0); // reserved
  1371. smbPkt.packWord((pipeName.length() * 2) + 2); // name length in bytes, inc null
  1372. smbPkt.packInt(0); // flags
  1373. smbPkt.packInt(0); // root FID
  1374. smbPkt.packInt(AccessMode.NTReadWrite); // desired access mode
  1375. smbPkt.packLong(0); // allocation size
  1376. smbPkt.packInt(0); // file attributes
  1377. smbPkt.packInt(SharingMode.READWRITE); // share access mode
  1378. smbPkt.packInt(FileAction.OpenIfExists); // action to take if file exists
  1379. smbPkt.packInt(0); // file create options
  1380. smbPkt.packInt(2); // impersonation level, 0=anonymous, 2=impersonation
  1381. smbPkt.packByte(0); // security flags
  1382. smbPkt.resetBytePointer();
  1383. smbPkt.packString(pipeName, smbPkt.isUnicode());
  1384. smbPkt.setByteCount();
  1385. // Send/receive the NT create andX request
  1386. smbPkt.ExchangeSMB(sess, smbPkt, true);
  1387. // Unpack the file/directory details
  1388. smbPkt.resetParameterPointer();
  1389. smbPkt.skipBytes(5);
  1390. int fid = smbPkt.unpackWord();
  1391. int createAction = smbPkt.unpackInt();
  1392. long createTime = smbPkt.unpackLong();
  1393. long lastAccessTime = smbPkt.unpackLong();
  1394. long lastWriteTime = smbPkt.unpackLong();
  1395. long changeTime = smbPkt.unpackLong();
  1396. int attr = smbPkt.unpackInt();
  1397. long allocSize = smbPkt.unpackLong();
  1398. long eofOffset = smbPkt.unpackLong();
  1399. int devType = smbPkt.unpackWord();
  1400. // Create the file information
  1401. FileInfo finfo = new FileInfo(pipeName, eofOffset, attr);
  1402. finfo.setFileId(fid);
  1403. // Create the file object
  1404. return new DataPipeFile(sess, finfo, fid);
  1405. }
  1406. /**
  1407. * Open a connection to a remote print server
  1408. *
  1409. * @param shr Remote share information object.
  1410. * @param settings Session settings
  1411. * @return SMBSession used to access the remote share.
  1412. * @exception java.io.Exception Network I/O error occurred.
  1413. * @exception java.net.UnkownHostException Remote node is unknown.
  1414. * @exception SMBException Failed to setup a new SMB session
  1415. */
  1416. static final public PrintSession OpenPrinter(PCShare shr, SessionSettings settings)
  1417. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1418. // Create a new print session
  1419. return (PrintSession) OpenSession(shr, SMBDeviceType.Printer, settings);
  1420. }
  1421. /**
  1422. * Open a session to a remote server.
  1423. *
  1424. * @param shr Remote server share and access control details.
  1425. * @param devtyp Device type to connect to on the remote node.
  1426. * @param settings Session settings
  1427. * @return SMBSession for the new session, else null.
  1428. * @exception java.io.IOException If an I/O error occurs.
  1429. * @exception java.net.UnknownHostException Remote node is unknown.
  1430. * @exception SMBException Failed to setup a new session.
  1431. */
  1432. private static Session OpenSession(PCShare shr, int devtyp, SessionSettings settings)
  1433. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1434. // Build a unique caller name
  1435. int pid = getSessionId();
  1436. StringBuffer nameBuf = new StringBuffer(InetAddress.getLocalHost().getHostName() + "_" + pid);
  1437. String localName = nameBuf.toString();
  1438. // Debug
  1439. if ( Debug.EnableInfo && Session.hasDebug()) {
  1440. Debug.println("** New session from " + localName + " to " + shr.toString());
  1441. // Display the Java system variables
  1442. Debug.println("** os.arch = " + System.getProperty("os.arch") + ", java.version: "
  1443. + System.getProperty("java.version"));
  1444. Debug.println("** JLAN version is " + SessionFactory.isVersion());
  1445. Debug.println("** Trying primary protocol - " + Protocol.asString(settings.getPrimaryProtocol()));
  1446. }
  1447. // Connect to the requested server using the primary protocol
  1448. NetworkSession netSession = null;
  1449. try {
  1450. switch (settings.getPrimaryProtocol()) {
  1451. // NetBIOS connection
  1452. case Protocol.TCPNetBIOS:
  1453. netSession = connectNetBIOSSession(shr.getNodeName(), localName, settings);
  1454. break;
  1455. // Native SMB connection
  1456. case Protocol.NativeSMB:
  1457. netSession = connectNativeSMBSession(shr.getNodeName(), localName, settings);
  1458. break;
  1459. }
  1460. }
  1461. catch (IOException ex) {
  1462. // Check if there is a secondary protocolcfno configured, if not then rethrow the
  1463. // exception
  1464. if ( settings.getSecondaryProtocol() == Protocol.None)
  1465. throw ex;
  1466. }
  1467. // If the connection was not made using the primary protocol try the secondary protocol, if
  1468. // configured
  1469. if ( netSession == null) {
  1470. // DEBUG
  1471. if ( Debug.EnableInfo && Session.hasDebug())
  1472. Debug.println("** Trying secondary protocol - " + Protocol.asString(settings.getSecondaryProtocol()));
  1473. // Try the secondary protocol
  1474. switch (settings.getSecondaryProtocol()) {
  1475. // NetBIOS connection
  1476. case Protocol.TCPNetBIOS:
  1477. netSession = connectNetBIOSSession(shr.getNodeName(), localName, settings);
  1478. break;
  1479. // Native SMB connection
  1480. case Protocol.NativeSMB:
  1481. netSession = connectNativeSMBSession(shr.getNodeName(), localName, settings);
  1482. break;
  1483. }
  1484. // If the secondary connection was successful check if the protocol order should be
  1485. // updated
  1486. if ( settings.hasUpdateProtocol() && netSession != null) {
  1487. // Update the primary protocol
  1488. settings.setPrimaryProtocol(settings.getSecondaryProtocol());
  1489. settings.setSecondaryProtocol(Protocol.None);
  1490. // Debug
  1491. if ( Debug.EnableInfo && Session.hasDebug())
  1492. Debug.println("** Updated primary protocol : " + Protocol.asString(settings.getPrimaryProtocol()));
  1493. }
  1494. }
  1495. // Check if we connected to the remote host
  1496. if ( netSession == null)
  1497. throw new IOException("Failed to connect to host, " + shr.getNodeName());
  1498. // Debug
  1499. if ( Debug.EnableInfo && Session.hasDebug())
  1500. Debug.println("** Connected session, protocol : " + netSession.getProtocolName());
  1501. // Build a protocol negotiation SMB packet, and send it to the remote
  1502. // file server.
  1503. SMBPacket pkt = new SMBPacket();
  1504. DialectSelector selDialect = settings.getDialects();
  1505. if ( selDialect == null) {
  1506. // Use the default SMB dialect list
  1507. selDialect = new DialectSelector();
  1508. selDialect.copyFrom(m_defaultSettings.getDialects());
  1509. }
  1510. // Build the negotiate SMB dialect packet and exchange with the remote server
  1511. StringList diaList = BuildNegotiatePacket(pkt, selDialect, hasGlobalProcessId() ? 1 : pid);
  1512. pkt.ExchangeLowLevelSMB(netSession, pkt, true);
  1513. // Determine the selected SMB dialect
  1514. String diaStr = diaList.getStringAt(pkt.getParameter(0));
  1515. int dialectId = Dialect.DialectType(diaStr);
  1516. // DEBUG
  1517. if ( Debug.EnableInfo && Session.hasDebug())
  1518. Debug.println("** SessionFactory: Negotiated SMB dialect " + diaStr);
  1519. if ( dialectId == Dialect.Unknown) {
  1520. // Close the low level session
  1521. netSession.Close();
  1522. // Indicate that the SMB dialect could not be negotiated
  1523. throw new java.io.IOException("Unknown SMB dialect");
  1524. }
  1525. // Determine the type of session that should be created
  1526. Session sess = null;
  1527. try {
  1528. switch (devtyp) {
  1529. // Disk share
  1530. case SMBDeviceType.Disk:
  1531. sess = CreateDiskSession(shr, pkt, netSession, dialectId, settings);
  1532. break;
  1533. // Printer share
  1534. case SMBDeviceType.Printer:
  1535. sess = CreatePrinterSession(shr, pkt, netSession, dialectId, settings);
  1536. break;
  1537. // IPC/pipe
  1538. case SMBDeviceType.Pipe:
  1539. sess = CreatePipeSession(shr, pkt, netSession, dialectId, settings);
  1540. break;
  1541. }
  1542. }
  1543. catch (SMBException ex) {
  1544. // Close the low level session
  1545. netSession.Close();
  1546. // Rethrow the exception
  1547. throw ex;
  1548. }
  1549. catch (IOException ex) {
  1550. // Close the low level session
  1551. netSession.Close();
  1552. // Rethrow the exception
  1553. throw ex;
  1554. }
  1555. // Set the sessions SMB dialect string, if valid
  1556. if ( sess != null)
  1557. sess.setDialectString(diaStr);
  1558. // Return the new session
  1559. return sess;
  1560. }
  1561. /**
  1562. * Open a session to a remote server, negotiate an SMB dialect and get the returned challenge
  1563. * key. Returns an AuthenticateSession which can then be used to provide passthru
  1564. * authentication.
  1565. *
  1566. * @param shr Remote server share and access control details.
  1567. * @return AuthenticateSession for the new session, else null.
  1568. * @exception java.io.IOException If an I/O error occurs.
  1569. * @exception java.net.UnknownHostException Remote node is unknown.
  1570. * @exception SMBException Failed to setup a new session.
  1571. */
  1572. public static AuthenticateSession OpenAuthenticateSession(PCShare shr)
  1573. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1574. // Open an authentication session
  1575. return OpenAuthenticateSession(shr, m_defaultSettings);
  1576. }
  1577. /**
  1578. * Open a session to a remote server, negotiate an SMB dialect and get the returned challenge
  1579. * key. Returns an AuthenticateSession which can then be used to provide passthru
  1580. * authentication.
  1581. *
  1582. * @param shr Remote server share and access control details.
  1583. * @param settings Session settings
  1584. * @return AuthenticateSession for the new session, else null.
  1585. * @exception java.io.IOException If an I/O error occurs.
  1586. * @exception java.net.UnknownHostException Remote node is unknown.
  1587. * @exception SMBException Failed to setup a new session.
  1588. */
  1589. public static AuthenticateSession OpenAuthenticateSession(PCShare shr, SessionSettings settings)
  1590. throws java.io.IOException, java.net.UnknownHostException, SMBException {
  1591. // Build a unique caller name
  1592. int pid = getSessionId();
  1593. StringBuffer nameBuf = new StringBuffer(InetAddress.getLocalHost().getHostName() + "_" + pid);
  1594. String localName = nameBuf.toString();
  1595. // Debug
  1596. if ( Debug.EnableInfo && Session.hasDebug()) {
  1597. Debug.println("** New auth session from " + localName + " to " + shr.toString());
  1598. // Display the Java system variables
  1599. Debug.println("** os.arch = " + System.getProperty("os.arch") + ", java.version: "
  1600. + System.getProperty("java.version"));
  1601. Debug.println("** JLAN version is " + SessionFactory.isVersion());
  1602. }
  1603. // Connect to the requested server using the primary protocol
  1604. NetworkSession netSession = null;
  1605. try {
  1606. switch (settings.getPrimaryProtocol()) {
  1607. // NetBIOS connection
  1608. case Protocol.TCPNetBIOS:
  1609. netSession = connectNetBIOSSession(shr.getNodeName(), localName, settings);
  1610. break;
  1611. // Native SMB connection
  1612. case Protocol.NativeSMB:
  1613. netSession = connectNativeSMBSession(shr.getNodeName(), localName, settings);
  1614. break;
  1615. }
  1616. }
  1617. catch (IOException ex) {
  1618. // Check if there is a secondary protocolcfno configured, if not then rethrow the
  1619. // exception
  1620. if ( settings.getSecondaryProtocol() == Protocol.None)
  1621. throw ex;
  1622. }
  1623. // If the connection was not made using the primary protocol try the secondary protocol, if
  1624. // configured
  1625. if ( netSession == null) {
  1626. // DEBUG
  1627. if ( Debug.EnableInfo && Session.hasDebug())
  1628. Debug.println("** Trying secondary protocol - " + Protocol.asString(settings.getSecondaryProtocol()));
  1629. // Try the secondary protocol
  1630. switch (settings.getSecondaryProtocol()) {
  1631. // NetBIOS connection
  1632. case Protocol.TCPNetBIOS:
  1633. netSession = connectNetBIOSSession(shr.getNodeName(), localName, settings);
  1634. break;
  1635. // Native SMB connection
  1636. case Protocol.NativeSMB:
  1637. netSession = connectNativeSMBSession(shr.getNodeName(), localName, settings);
  1638. break;
  1639. }
  1640. // If the secondary connection was successful check if the protocol order should be
  1641. // updated
  1642. if ( settings.hasUpdateProtocol() && netSession != null) {
  1643. // Update the primary protocol
  1644. settings.setPrimaryProtocol(settings.getSecondaryProtocol());
  1645. settings.setSecondaryProtocol(Protocol.None);
  1646. // Debug
  1647. if ( Debug.EnableInfo && Session.hasDebug())
  1648. Debug.println("** Updated primary protocol : " + Protocol.asString(settings.getPrimaryProtocol()));
  1649. }
  1650. }
  1651. // Check if we connected to the remote host
  1652. if ( netSession == null)
  1653. throw new IOException("Failed to connect to host, " + shr.getNodeName());
  1654. // Debug
  1655. if ( Debug.EnableInfo && Session.hasDebug())
  1656. Debug.println("** Connected session, protocol : " + netSession.getProtocolName());
  1657. // Build a protocol negotiation SMB packet, and send it to the remote
  1658. // file server.
  1659. SMBPacket pkt = new SMBPacket();
  1660. DialectSelector selDialect = settings.getDialects();
  1661. if ( selDialect == null) {
  1662. // Use the default SMB dialect list
  1663. selDialect = new DialectSelector();
  1664. selDialect.copyFrom(m_defaultSettings.getDialects());
  1665. }
  1666. // Build the negotiate SMB dialect packet and exchange with the remote server
  1667. StringList diaList = BuildNegotiatePacket(pkt, selDialect, hasGlobalProcessId() ? 1 : pid);
  1668. pkt.ExchangeLowLevelSMB(netSession, pkt, true);
  1669. // Determine the selected SMB dialect
  1670. String diaStr = diaList.getStringAt(pkt.getParameter(0));
  1671. int dialectId = Dialect.DialectType(diaStr);
  1672. // DEBUG
  1673. if ( Debug.EnableInfo && Session.hasDebug())
  1674. Debug.println("** SessionFactory: Negotiated SMB dialect " + diaStr);
  1675. if ( dialectId == Dialect.Unknown)
  1676. throw new java.io.IOException("Unknown SMB dialect");
  1677. // Create the authenticate session
  1678. AuthenticateSession authSess = new AuthenticateSession(shr, netSession, dialectId, pkt);
  1679. return authSess;
  1680. }
  1681. /**
  1682. * Send a message to a remote user.
  1683. *
  1684. * @param dNode Destination node name.
  1685. * @param msg Message to be sent (maximum of 128 bytes).
  1686. * @param tmo int
  1687. * @exception SMBException If an SMB error occurs.
  1688. * @exception java.io.IOException If an I/O error occurs.
  1689. * @exception java.net.UnknownHostException If the destination host is invalid/unknown.
  1690. */
  1691. public final static void SendMessage(String dNode, String msg, int tmo)
  1692. throws SMBException, java.io.IOException, UnknownHostException {
  1693. // Enable debug
  1694. // SMBSession.setDebug(0xFFFF);
  1695. // Check if the destination address is a numeric IP address
  1696. String remName = dNode;
  1697. if ( IPAddress.isNumericAddress(remName)) {
  1698. // Get a list of NetBIOS names from the remote host
  1699. NetBIOSNameList nameList = NetBIOSSession.FindNamesForAddress(dNode);
  1700. // Find the messenger service name
  1701. NetBIOSName nbName = nameList.findName(NetBIOSName.RemoteMessenger, false);
  1702. if ( nbName == null)
  1703. throw new IOException("Messenger service not running");
  1704. // Set the remote host name
  1705. remName = nbName.getName();
  1706. }
  1707. // Build a unique caller NetBIOS name
  1708. String localName = InetAddress.getLocalHost().getHostName().toUpperCase();
  1709. // Debug
  1710. if ( Debug.EnableInfo && Session.hasDebug()) {
  1711. Debug.println("** New session from " + localName + " to " + dNode);
  1712. // Display the Java system variables
  1713. Debug.println("** os.arch = " + System.getProperty("os.arch") + ", java.version: "
  1714. + System.getProperty("java.version"));
  1715. }
  1716. // Connect to the requested server
  1717. NetBIOSSession nbSession = new NetBIOSSession(tmo);
  1718. nbSession.setLocalNameType(NetBIOSName.Messenger);
  1719. nbSession.setRemoteNameType(NetBIOSName.RemoteMessenger);
  1720. nbSession.Open(remName, localName, dNode);
  1721. // Build a send message packet
  1722. SMBPacket pkt = new SMBPacket();
  1723. pkt.setCommand(PacketType.SendMessage);
  1724. pkt.setFlags(0);
  1725. pkt.setParameterCount(0);
  1726. // Set the session id and sequence number
  1727. pkt.setSID(0);
  1728. pkt.setSeqNo(0);
  1729. pkt.resetBytePointer();
  1730. pkt.packByte(DataType.ASCII);
  1731. pkt.packString(localName, false);
  1732. pkt.packByte(DataType.ASCII);
  1733. pkt.packString(remName.toUpperCase(), false);
  1734. pkt.packByte(DataType.DataBlock);
  1735. pkt.packWord(msg.length());
  1736. pkt.packBytes(msg.getBytes(), msg.length());
  1737. pkt.setByteCount();
  1738. // Send the message
  1739. pkt.ExchangeLowLevelSMB(nbSession, pkt, false);
  1740. // Close the NetBIOS session
  1741. nbSession.Close();
  1742. // Check if the send got an error
  1743. if ( pkt.getErrorClass() != SMBStatus.Success && pkt.getErrorCode() != SMBStatus.Success)
  1744. throw new java.io.IOException(SMBErrorText.ErrorString(pkt.getErrorClass(), pkt.getErrorCode()));
  1745. }
  1746. /**
  1747. * Send a message to a remote user.
  1748. *
  1749. * @param dNode Destination node name.
  1750. * @param msg Message to be sent (maximum of 128 bytes).
  1751. * @exception SMBException If an SMB error occurs.
  1752. * @exception java.io.IOException If an I/O error occurs.
  1753. * @exception java.net.UnknownHostException If the destination host is invalid/unknown.
  1754. */
  1755. public final static void SendMessage(String dNode, String msg)
  1756. throws SMBException, java.io.IOException, UnknownHostException {
  1757. // Send a message using the default timeout
  1758. SendMessage(dNode, msg, RFCNetBIOSProtocol.TMO);
  1759. }
  1760. /**
  1761. * Set the default SMB dialects that are to be negotiated when a new session is created.
  1762. *
  1763. * @param dialist DialectSelector containing the SMB dialects to negotiate.
  1764. */
  1765. public final static void setDefaultDialects(DialectSelector dialist) {
  1766. // Copy the SMB dialect list
  1767. m_defaultSettings.setDialects(dialist);
  1768. }
  1769. /**
  1770. * Set the default domain.
  1771. *
  1772. * @param domain String
  1773. */
  1774. public static void setDefaultDomain(String domain) {
  1775. m_defDomain = domain;
  1776. }
  1777. /**
  1778. * Set the default password.
  1779. *
  1780. * @param pwd java.lang.String
  1781. */
  1782. public static void setDefaultPassword(String pwd) {
  1783. m_defPassword = pwd;
  1784. }
  1785. /**
  1786. * Set the default user name.
  1787. *
  1788. * @param user java.lang.String
  1789. */
  1790. public static void setDefaultUserName(String user) {
  1791. m_defUserName = user;
  1792. }
  1793. /**
  1794. * Set/clear the global process id flag. If the flag is false a unique process id is generated
  1795. * for each session.
  1796. *
  1797. * @param ena boolean
  1798. */
  1799. public final static void setGlobalProcessId(boolean ena) {
  1800. m_globalPID = ena;
  1801. }
  1802. /**
  1803. * Set the NetBIOS socket number to be used when setting up new sessions. The default socket is
  1804. * 139.
  1805. *
  1806. * @param port int
  1807. */
  1808. public static void setNetBIOSPort(int port) {
  1809. m_defaultSettings.setNetBIOSSessionPort(port);
  1810. }
  1811. /**
  1812. * Set the NetBIOS scope id
  1813. *
  1814. * @param scope String
  1815. */
  1816. public static void setNetBIOSNameScope(String scope) {
  1817. String nbScope = scope;
  1818. if ( nbScope != null && nbScope.startsWith("."))
  1819. nbScope = nbScope.substring(1);
  1820. m_defaultSettings.setNetBIOSNameScope(nbScope);
  1821. }
  1822. /**
  1823. * Set the protocol connection order
  1824. *
  1825. * @param pri Primary connection protocol
  1826. * @param sec Secondary connection protocol, or none
  1827. * @return boolean
  1828. */
  1829. public static final boolean setProtocolOrder(int pri, int sec) {
  1830. // Primary protocol must be specified
  1831. if ( pri != Protocol.TCPNetBIOS && pri != Protocol.NativeSMB)
  1832. return false;
  1833. // Primary and secondary must be different
  1834. if ( pri == sec)
  1835. return false;
  1836. // Save the settings
  1837. m_defaultSettings.setPrimaryProtocol(pri);
  1838. m_defaultSettings.setSecondaryProtocol(sec);
  1839. return true;
  1840. }
  1841. /**
  1842. * Enable/disable SMB signing support
  1843. *
  1844. * @param ena boolean
  1845. */
  1846. public final static void setSMBSigningEnabled(boolean ena) {
  1847. m_smbSigningEnabled = ena;
  1848. }
  1849. /**
  1850. * Enable/disable validation of received SMB signatures when signing is enabled
  1851. *
  1852. * @param ena boolean
  1853. */
  1854. public final static void setReceivedSMBSigningEnabled(boolean ena) {
  1855. m_smbSigningCheckRx = ena;
  1856. }
  1857. /**
  1858. * Enable/disable SMB session debugging.
  1859. *
  1860. * @param dbg true to enable SMB session debugging, else false.
  1861. */
  1862. public final static void setSessionDebug(boolean dbg) {
  1863. if ( dbg == true)
  1864. Session.setDebug(Session.DBGPacketType);
  1865. else
  1866. Session.setDebug(0);
  1867. }
  1868. /**
  1869. * Set the subnet mask string for network broadcast requests
  1870. *
  1871. * If the subnet mask is not set a default broadcast mask for the TCP/IP address class will be
  1872. * used.
  1873. *
  1874. * @param subnet Subnet mask string, in 'nnn.nnn.nnn.nnn' format.
  1875. */
  1876. public final static void setSubnetMask(String subnet) {
  1877. NetBIOSSession.setDefaultSubnetMask(subnet);
  1878. }
  1879. /**
  1880. * Setup the default SMB dialects to be negotiated when creating new sessions.
  1881. */
  1882. private static void SetupDefaultDialects() {
  1883. // Initialize the default dialect list
  1884. DialectSelector dialects = new DialectSelector();
  1885. // Always enable core protocol
  1886. dialects.AddDialect(Dialect.Core);
  1887. dialects.AddDialect(Dialect.CorePlus);
  1888. // Determine if the CIFS classes are available, if so then enable
  1889. // negotiation of the extra SMB dialects
  1890. try {
  1891. // Try and load the CIFS session classes
  1892. Class.forName("org.alfresco.jlan.client.CIFSDiskSession");
  1893. Class.forName("org.alfresco.jlan.client.CIFSPrintSession");
  1894. // The CIFS protocol session classes are available
  1895. dialects.AddDialect(Dialect.DOSLanMan1);
  1896. dialects.AddDialect(Dialect.DOSLanMan2);
  1897. dialects.AddDialect(Dialect.LanMan1);
  1898. dialects.AddDialect(Dialect.LanMan2);
  1899. dialects.AddDialect(Dialect.LanMan2_1);
  1900. dialects.AddDialect(Dialect.NT);
  1901. }
  1902. catch (java.lang.ClassNotFoundException ex) {
  1903. }
  1904. catch (java.lang.ExceptionInInitializerError ex) {
  1905. }
  1906. catch (java.lang.LinkageError ex) {
  1907. }
  1908. // Set the default dialects to negotiate
  1909. m_defaultSettings.setDialects(dialects);
  1910. }
  1911. /**
  1912. * Connect a NetBIOS network session
  1913. *
  1914. * @param toName Host name/address to connect to
  1915. * @param fromName Local host name/address
  1916. * @param settings Session settings
  1917. * @return NetworkSession
  1918. * @exception IOException If a network error occurs
  1919. */
  1920. private static final NetworkSession connectNetBIOSSession(String toName, String fromName, SessionSettings settings)
  1921. throws IOException {
  1922. // Connect to the requested server
  1923. NetBIOSSession nbSession = new NetBIOSSession(settings.getSessionTimeout(), settings.getNetBIOSSessionPort(), settings
  1924. .getNetBIOSNamePort());
  1925. // Set per session overrides for the new session
  1926. nbSession.setSubnetMask(settings.getSubnetMask());
  1927. nbSession.setWildcardFileServerName(settings.useWildcardServerName());
  1928. nbSession.setWINSServer(settings.getWINSServer());
  1929. nbSession.setLookupType(settings.getLookupType());
  1930. nbSession.setLookupTimeout(settings.getLookupTimeout());
  1931. // Make sure the destination name is uppercased
  1932. toName = toName.toUpperCase();
  1933. // Check if the remote host is specified as a TCP/IP address
  1934. NetBIOSName nbName = null;
  1935. if ( IPAddress.isNumericAddress(toName)) {
  1936. // Convert the TCP/IP address to a NetBIOS name using a DNS or WINS/NetBIOS name lookup
  1937. nbName = NetBIOSSession.ConvertAddressToName(toName, NetBIOSName.FileServer, false, nbSession);
  1938. }
  1939. else {
  1940. IOException savedException = null;
  1941. try {
  1942. // Find the remote host and get a list of the network addresses it is using
  1943. nbName = NetBIOSSession.FindName(toName, NetBIOSName.FileServer, 500, nbSession);
  1944. // If the lookup type is DNS only then make sure the file server responds on that
  1945. // name. The DNS lookup
  1946. // could return a name that has a domain but it it unlikely that NetBIOS is setup
  1947. // with name scopes on
  1948. // the server.
  1949. if ( nbSession.getLookupType() == NetBIOSSession.DNSOnly && nbName != null && nbName.hasNameScope()) {
  1950. // Clear the NetBIOS name until the connection is successful
  1951. NetBIOSName srvName = nbName;
  1952. srvName.setType(NetBIOSName.FileServer);
  1953. nbName = null;
  1954. // Search for the server name using NetBIOS
  1955. nbName = NetBIOSSession.FindName(srvName, 500, NetBIOSSession.WINSOnly, nbSession);
  1956. }
  1957. }
  1958. catch (IOException ex) {
  1959. savedException = ex;
  1960. }
  1961. // Check if the server name contains a name scope
  1962. if ( nbName == null && toName.indexOf('.') != -1) {
  1963. // Parse the NetBIOS server name
  1964. NetBIOSName srvName = new NetBIOSName(toName);
  1965. if ( srvName.hasNameScope()) {
  1966. // Remove the NetBIOS name scope
  1967. srvName.setNameScope(null);
  1968. // Set the new server name
  1969. toName = srvName.getName();
  1970. // Try the connection attempt again without the NetBIOS name scope
  1971. try {
  1972. // Find the remote host and get a list of the network addresses it is using
  1973. nbName = NetBIOSSession.FindName(toName, NetBIOSName.FileServer, 500, nbSession);
  1974. }
  1975. catch (IOException ex) {
  1976. savedException = ex;
  1977. }
  1978. }
  1979. }
  1980. // If the NetBIOS name was not found then check if the local system has the name
  1981. if ( nbName == null) {
  1982. // Make sure NetBIOS name lookups are enabled
  1983. if ( nbSession.getLookupType() != NetBIOSSession.DNSOnly) {
  1984. // Get a list of NetBIOS names for the local system
  1985. NetBIOSNameList localList = NetBIOSSession.FindNamesForAddress(InetAddress.getLocalHost().getHostAddress());
  1986. if ( localList != null) {
  1987. nbName = localList.findName(toName, NetBIOSName.FileServer, false);
  1988. if ( nbName != null)
  1989. nbName.addIPAddress(InetAddress.getLocalHost().getAddress());
  1990. else
  1991. throw savedException;
  1992. }
  1993. }
  1994. else
  1995. throw savedException;
  1996. }
  1997. }
  1998. // Check if the NetBIOS name scope has been set, if so then update the names to add the
  1999. // scope id
  2000. if ( nbName.hasNameScope()) {
  2001. // Add the NetBIOS scope id to the to/from NetBIOS names
  2002. toName = nbName.getFullName();
  2003. fromName = fromName + "." + nbName.getNameScope();
  2004. }
  2005. else if ( settings.hasNetBIOSNameScope()) {
  2006. // Add the NetBIOS scope id to the to/from NetBIOS names
  2007. toName = toName + "." + settings.getNetBIOSNameScope();
  2008. fromName = fromName + "." + settings.getNetBIOSNameScope();
  2009. }
  2010. // If the NetBIOS name has more than one TCP/IP address then find the best match for the
  2011. // client and
  2012. // try to connect on that address first, if that fails then we will have to try each address
  2013. // in turn.
  2014. if ( nbName.numberOfAddresses() > 1) {
  2015. // Get the local TCP/IP address list and search for a best match address to connect to
  2016. // the server on
  2017. InetAddress[] addrList = getLocalTcpipAddresses();
  2018. int addrIdx = nbName.findBestMatchAddress(addrList);
  2019. if ( addrIdx != -1) {
  2020. try {
  2021. // Get the server IP address
  2022. String ipAddr = nbName.getIPAddressString(addrIdx);
  2023. // DEBUG
  2024. if ( Debug.EnableInfo && hasSessionDebug())
  2025. Debug.println("** Server is multi-homed, trying to connect to " + ipAddr);
  2026. // Open the session to the remote host
  2027. nbSession.Open(toName, fromName, ipAddr);
  2028. // Check if the session is connected
  2029. if ( nbSession.isConnected() == false) {
  2030. // Close the session
  2031. try {
  2032. nbSession.Close();
  2033. }
  2034. catch (Exception ex) {
  2035. }
  2036. }
  2037. else if ( Debug.EnableInfo && hasSessionDebug() && nbSession.isConnected())
  2038. Debug.println("** Connected to address " + ipAddr);
  2039. }
  2040. catch (IOException ex) {
  2041. }
  2042. }
  2043. }
  2044. // DEBUG
  2045. if ( Debug.EnableInfo && hasSessionDebug() && nbSession.isConnected() == false && nbName.numberOfAddresses() > 1)
  2046. Debug.println("** Server is multi-homed, trying all addresses");
  2047. // Loop through the available addresses for the remote file server until we get a successful
  2048. // connection, or all addresses have been used
  2049. IOException lastException = null;
  2050. int addrIdx = 0;
  2051. while (nbSession.isConnected() == false && addrIdx < nbName.numberOfAddresses()) {
  2052. try {
  2053. // Get the server IP address
  2054. String ipAddr = nbName.getIPAddressString(addrIdx++);
  2055. // DEBUG
  2056. if ( Debug.EnableInfo && hasSessionDebug())
  2057. Debug.println("** Trying address " + ipAddr);
  2058. // Open the session to the remote host
  2059. nbSession.Open(toName, fromName, ipAddr);
  2060. // Check if the session is connected
  2061. if ( nbSession.isConnected() == false) {
  2062. // Close the session
  2063. try {
  2064. nbSession.Close();
  2065. }
  2066. catch (Exception ex) {
  2067. }
  2068. }
  2069. else if ( Debug.EnableInfo && hasSessionDebug() && nbSession.isConnected())
  2070. Debug.println("** Connected to address " + ipAddr);
  2071. }
  2072. catch (IOException ex) {
  2073. // Save the last exception
  2074. lastException = ex;
  2075. }
  2076. }
  2077. // Check if the session is connected
  2078. if ( nbSession.isConnected() == false) {
  2079. // If there is a saved exception rethrow it
  2080. if ( lastException != null)
  2081. throw lastException;
  2082. // Indicate that the session was not connected
  2083. return null;
  2084. }
  2085. // Return the network session
  2086. return nbSession;
  2087. }
  2088. /**
  2089. * Connect a native SMB network session
  2090. *
  2091. * @param toName Host name/address to connect to
  2092. * @param fromName Local host name/address
  2093. * @param settings Session settings
  2094. * @return NetworkSession
  2095. * @exception IOException If a network error occurs
  2096. */
  2097. private static final NetworkSession connectNativeSMBSession(String toName, String fromName, SessionSettings settings)
  2098. throws IOException {
  2099. // Connect to the requested server
  2100. TcpipSMBNetworkSession tcpSession = new TcpipSMBNetworkSession(settings.getSessionTimeout(), settings.getNativeSMBPort());
  2101. try {
  2102. // Open the session
  2103. tcpSession.Open(toName, fromName, null);
  2104. // Check if the session is connected
  2105. if ( tcpSession.isConnected() == false) {
  2106. // Close the session
  2107. try {
  2108. tcpSession.Close();
  2109. }
  2110. catch (Exception ex) {
  2111. }
  2112. // Return a null session
  2113. return null;
  2114. }
  2115. }
  2116. catch (Exception ex) {
  2117. try {
  2118. tcpSession.Close();
  2119. }
  2120. catch (Exception ex2) {
  2121. }
  2122. tcpSession = null;
  2123. }
  2124. // Return the network session
  2125. return tcpSession;
  2126. }
  2127. }