1 package jcifs.smb; 2 3 import java.security.MessageDigest ; 4 import java.security.NoSuchAlgorithmException ; 5 import java.io.IOException ; 6 import jcifs.Config; 7 import jcifs.util.LogStream; 8 import jcifs.util.Hexdump; 9 10 13 14 public class SigningDigest { 15 16 private static final int LM_COMPATIBILITY = Config.getInt( "jcifs.smb.lmCompatibility", 0); 17 18 static LogStream log = LogStream.getInstance(); 19 20 private MessageDigest digest; 21 private byte[] macSigningKey; 22 private int updates; 23 private int signSequence; 24 25 public SigningDigest( SmbTransport transport, 26 NtlmPasswordAuthentication auth ) throws SmbException { 27 try { 28 digest = MessageDigest.getInstance("MD5"); 29 } catch (NoSuchAlgorithmException ex) { 30 if( log.level > 0 ) 31 ex.printStackTrace( log ); 32 throw new SmbException( "MD5", ex ); 33 } 34 35 try { 36 switch (LM_COMPATIBILITY) { 37 case 0: 38 case 1: 39 case 2: 40 macSigningKey = new byte[40]; 41 auth.getUserSessionKey(transport.server.encryptionKey, macSigningKey, 0); 42 System.arraycopy(auth.getUnicodeHash(transport.server.encryptionKey), 43 0, macSigningKey, 16, 24); 44 break; 45 case 3: 46 case 4: 47 case 5: 48 macSigningKey = new byte[16]; 49 auth.getUserSessionKey(transport.server.encryptionKey, macSigningKey, 0); 50 break; 51 default: 52 macSigningKey = new byte[40]; 53 auth.getUserSessionKey(transport.server.encryptionKey, macSigningKey, 0); 54 System.arraycopy(auth.getUnicodeHash(transport.server.encryptionKey), 55 0, macSigningKey, 16, 24); 56 break; 57 } 58 } catch( Exception ex ) { 59 throw new SmbException( "", ex ); 60 } 61 if( log.level > 3 ) { 62 log.println( "LM_COMPATIBILITY=" + LM_COMPATIBILITY ); 63 Hexdump.hexdump( log, macSigningKey, 0, macSigningKey.length ); 64 } 65 } 66 67 public void update( byte[] input, int offset, int len ) { 68 if( log.level > 3 ) { 69 log.println( "update: " + updates + " " + offset + ":" + len ); 70 Hexdump.hexdump( log, input, offset, Math.min( len, 256 )); 71 log.flush(); 72 } 73 if( len == 0 ) { 74 return; 75 } 76 digest.update( input, offset, len ); 77 updates++; 78 } 79 public byte[] digest() { 80 byte[] b; 81 82 b = digest.digest(); 83 84 if( log.level > 3 ) { 85 log.println( "digest: " ); 86 Hexdump.hexdump( log, b, 0, b.length ); 87 log.flush(); 88 } 89 updates = 0; 90 91 return b; 92 } 93 94 104 void sign(byte[] data, int offset, int length, 105 ServerMessageBlock request, ServerMessageBlock response) { 106 request.signSeq = signSequence; 107 if( response != null ) { 108 response.signSeq = signSequence + 1; 109 response.verifyFailed = false; 110 } 111 112 try { 113 update(macSigningKey, 0, macSigningKey.length); 114 int index = offset + ServerMessageBlock.SIGNATURE_OFFSET; 115 for (int i = 0; i < 8; i++) data[index + i] = 0; 116 ServerMessageBlock.writeInt4(signSequence, data, index); 117 update(data, offset, length); 118 System.arraycopy(digest(), 0, data, index, 8); 119 } catch (Exception ex) { 120 if( log.level > 0 ) 121 ex.printStackTrace( log ); 122 } finally { 123 signSequence += 2; 124 } 125 } 126 127 135 boolean verify(byte[] data, int offset, ServerMessageBlock response) { 136 update(macSigningKey, 0, macSigningKey.length); 137 int index = offset; 138 update(data, index, ServerMessageBlock.SIGNATURE_OFFSET); 139 index += ServerMessageBlock.SIGNATURE_OFFSET; 140 byte[] sequence = new byte[8]; 141 ServerMessageBlock.writeInt4(response.signSeq, sequence, 0); 142 update(sequence, 0, sequence.length); 143 index += 8; 144 if( response.command == ServerMessageBlock.SMB_COM_READ_ANDX ) { 145 147 SmbComReadAndXResponse raxr = (SmbComReadAndXResponse)response; 148 int length = response.length - raxr.dataLength; 149 update(data, index, length - ServerMessageBlock.SIGNATURE_OFFSET - 8); 150 update(raxr.b, raxr.off, raxr.dataLength); 151 } else { 152 update(data, index, response.length - ServerMessageBlock.SIGNATURE_OFFSET - 8); 153 } 154 byte[] signature = digest(); 155 for (int i = 0; i < 8; i++) { 156 if (signature[i] != data[offset + ServerMessageBlock.SIGNATURE_OFFSET + i]) { 157 if( log.level > 2 ) { 158 log.println( "signature verification failure" ); 159 Hexdump.hexdump( log, signature, 0, 8 ); 160 Hexdump.hexdump( log, data, 161 offset + ServerMessageBlock.SIGNATURE_OFFSET, 8 ); 162 } 163 return response.verifyFailed = true; 164 } 165 } 166 167 return response.verifyFailed = false; 168 } 169 } 170 171 | Popular Tags |