KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jcifs > smb > SigningDigest


1 package jcifs.smb;
2
3 import java.security.MessageDigest JavaDoc;
4 import java.security.NoSuchAlgorithmException JavaDoc;
5 import java.io.IOException JavaDoc;
6 import jcifs.Config;
7 import jcifs.util.LogStream;
8 import jcifs.util.Hexdump;
9
10 /**
11  * To filter 0 len updates and for debugging
12  */

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 JavaDoc 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 JavaDoc 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 JavaDoc 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; /* CRITICAL */
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     /**
95      * Performs MAC signing of the SMB. This is done as follows.
96      * The signature field of the SMB is overwritted with the sequence number;
97      * The MD5 digest of the MAC signing key + the entire SMB is taken;
98      * The first 8 bytes of this are placed in the signature field.
99      *
100      * @param data The data.
101      * @param offset The starting offset at which the SMB header begins.
102      * @param length The length of the SMB data starting at offset.
103      */

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 JavaDoc ex) {
120             if( log.level > 0 )
121                 ex.printStackTrace( log );
122         } finally {
123             signSequence += 2;
124         }
125     }
126
127     /**
128      * Performs MAC signature verification. This calculates the signature
129      * of the SMB and compares it to the signature field on the SMB itself.
130      *
131      * @param data The data.
132      * @param offset The starting offset at which the SMB header begins.
133      * @param length The length of the SMB data starting at offset.
134      */

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             /* SmbComReadAndXResponse reads directly from the stream into separate byte[] b.
146              */

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