KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > knowgate > jcifs > smb > SigningDigest


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

14
15 public class SigningDigest {
16
17     private static final int LM_COMPATIBILITY = Config.getInt( "jcifs.smb.lmCompatibility", 0);
18
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( DebugFile.trace )
31                 new ErrorHandler(ex);
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( DebugFile.trace ) {
62             DebugFile.writeln( "LM_COMPATIBILITY=" + LM_COMPATIBILITY );
63         }
64     }
65
66     public void update( byte[] input, int offset, int len ) {
67         if( DebugFile.trace ) {
68             DebugFile.writeln( "update: " + updates + " " + offset + ":" + len );
69         }
70         if( len == 0 ) {
71             return; /* CRITICAL */
72         }
73         digest.update( input, offset, len );
74         updates++;
75     }
76     public byte[] digest() {
77         byte[] b;
78
79         b = digest.digest();
80
81         if( DebugFile.trace ) {
82             DebugFile.writeln( "digest: " );
83         }
84         updates = 0;
85
86         return b;
87     }
88
89     /**
90      * Performs MAC signing of the SMB. This is done as follows.
91      * The signature field of the SMB is overwritted with the sequence number;
92      * The MD5 digest of the MAC signing key + the entire SMB is taken;
93      * The first 8 bytes of this are placed in the signature field.
94      *
95      * @param data The data.
96      * @param offset The starting offset at which the SMB header begins.
97      * @param length The length of the SMB data starting at offset.
98      */

99     void sign(byte[] data, int offset, int length,
100                 ServerMessageBlock request, ServerMessageBlock response) {
101         request.signSeq = signSequence;
102         if( response != null ) {
103             response.signSeq = signSequence + 1;
104             response.verifyFailed = false;
105         }
106
107         try {
108             update(macSigningKey, 0, macSigningKey.length);
109             int index = offset + ServerMessageBlock.SIGNATURE_OFFSET;
110             for (int i = 0; i < 8; i++) data[index + i] = 0;
111             ServerMessageBlock.writeInt4(signSequence, data, index);
112             update(data, offset, length);
113             System.arraycopy(digest(), 0, data, index, 8);
114         } catch (Exception JavaDoc ex) {
115             if( DebugFile.trace )
116                 new ErrorHandler(ex);
117         } finally {
118             signSequence += 2;
119         }
120     }
121
122     /**
123      * Performs MAC signature verification. This calculates the signature
124      * of the SMB and compares it to the signature field on the SMB itself.
125      *
126      * @param data The data.
127      * @param offset The starting offset at which the SMB header begins.
128      * @param length The length of the SMB data starting at offset.
129      */

130     boolean verify(byte[] data, int offset, ServerMessageBlock response) {
131         update(macSigningKey, 0, macSigningKey.length);
132         int index = offset;
133         update(data, index, ServerMessageBlock.SIGNATURE_OFFSET);
134         index += ServerMessageBlock.SIGNATURE_OFFSET;
135         byte[] sequence = new byte[8];
136         ServerMessageBlock.writeInt4(response.signSeq, sequence, 0);
137         update(sequence, 0, sequence.length);
138         index += 8;
139         if( response.command == ServerMessageBlock.SMB_COM_READ_ANDX ) {
140             /* SmbComReadAndXResponse reads directly from the stream into separate byte[] b.
141              */

142             SmbComReadAndXResponse raxr = (SmbComReadAndXResponse)response;
143             int length = response.length - raxr.dataLength;
144             update(data, index, length - ServerMessageBlock.SIGNATURE_OFFSET - 8);
145             update(raxr.b, raxr.off, raxr.dataLength);
146         } else {
147             update(data, index, response.length - ServerMessageBlock.SIGNATURE_OFFSET - 8);
148         }
149         byte[] signature = digest();
150         for (int i = 0; i < 8; i++) {
151             if (signature[i] != data[offset + ServerMessageBlock.SIGNATURE_OFFSET + i]) {
152                 if( DebugFile.trace ) {
153                     DebugFile.writeln( "signature verification failure" );
154                 }
155                 return response.verifyFailed = true;
156             }
157         }
158
159         return response.verifyFailed = false;
160     }
161 }
162
163
Popular Tags