1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 package uk.co.westhawk.snmp.stack;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 import uk.co.westhawk.snmp.util.SnmpUtilities;
67
68 import java.io.ByteArrayOutputStream;
69 import java.io.IOException;
70 import java.util.Enumeration;
71
72
73
74
75
76
77
78
79
80 class AsnEncoderv3 extends AsnEncoderBase {
81 private static final String version_id = "@(#)$Id: AsnEncoderv3.java,v 3.5 2009/03/05 12:48:59 birgita Exp $ Copyright Westhawk Ltd";
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 byte[] EncodeSNMPv3(SnmpContextv3Basis context, int contextMsgId, TimeWindowNode node, byte msg_type, int pduId,
97 int errstat, int errind, Enumeration ve) throws IOException, EncodingException {
98
99
100 ByteArrayOutputStream encodedSnmpMessageOutputStream;
101
102 AsnSequence asnSequence = new AsnSequence();
103
104
105 AsnSequence asnHeaderData = new AsnSequence();
106 asnHeaderData.add(new AsnInteger(contextMsgId));
107 asnHeaderData.add(new AsnInteger(context.getMaxRecvSize()));
108 asnHeaderData.add(new AsnOctets(getMessageFlags(context, msg_type)));
109 asnHeaderData.add(new AsnInteger(context.USM_Security_Model));
110
111
112 AsnSequence asnPlainScopedPdu = new AsnSequence();
113 asnPlainScopedPdu.add(new AsnOctets(context.getContextEngineId()));
114 asnPlainScopedPdu.add(new AsnOctets(context.getContextName()));
115
116 AsnObject asnPduObject = EncodePdu(msg_type, pduId, errstat, errind, ve);
117 asnPlainScopedPdu.add(asnPduObject);
118
119
120 if (AsnObject.debug > 10) {
121 System.out.println("\nEncode USM: node " + node.toString());
122 }
123 AsnSequence asnSecurityObject = new AsnSequence();
124 byte[] engineIdBytes = SnmpUtilities.toBytes(node.getSnmpEngineId());
125 asnSecurityObject.add(new AsnOctets(engineIdBytes));
126 asnSecurityObject.add(new AsnInteger(node.getSnmpEngineBoots()));
127 asnSecurityObject.add(new AsnInteger(node.getSnmpEngineTime()));
128 asnSecurityObject.add(new AsnOctets(context.getUserName()));
129 AsnOctets fingerPrintOctets;
130 int authenticationProtocol = context.getAuthenticationProtocol();
131
132 byte[] dummyFingerprint;
133 if (context.isUseAuthentication()) {
134 dummyFingerprint = SnmpUtilities.initFingerprint(authenticationProtocol);
135 fingerPrintOctets = new AsnOctets(dummyFingerprint);
136 } else {
137 fingerPrintOctets = new AsnOctets("");
138 }
139 asnSecurityObject.add(fingerPrintOctets);
140
141 AsnOctets privacyAsnOctets;
142 AsnOctets asnEncryptedScopedPdu = null;
143
144 if (context.isUsePrivacy()) {
145 int privacyProtocol = context.getPrivacyProtocol();
146
147 byte[] privacyKey = context.generatePrivacyKey(node.getSnmpEngineId(), authenticationProtocol, privacyProtocol);
148 byte[] salt = null;
149 if (SnmpContextv3Face.AES_PRIVACY_PROTOCOLS.contains(privacyProtocol)) {
150 salt = SnmpUtilities.getSaltAES();
151 } else {
152 salt = SnmpUtilities.getSaltDES(node.getSnmpEngineBoots());
153 }
154
155 privacyAsnOctets = new AsnOctets(salt);
156 encodedSnmpMessageOutputStream = new ByteArrayOutputStream();
157 asnPlainScopedPdu.write(encodedSnmpMessageOutputStream);
158
159 byte[] plaintext = encodedSnmpMessageOutputStream.toByteArray();
160 byte[] encryptedText = null;
161 if (SnmpContextv3Face.AES_PRIVACY_PROTOCOLS.contains(privacyProtocol)) {
162 encryptedText = SnmpUtilities.AESencrypt(plaintext, privacyKey, node.getSnmpEngineBoots(),
163 node.getSnmpEngineTime(), salt);
164 } else {
165 encryptedText = SnmpUtilities.DESencrypt(plaintext, privacyKey, salt);
166 }
167
168 asnEncryptedScopedPdu = new AsnOctets(encryptedText);
169 if (AsnObject.debug > 10) {
170 System.out.println("Encrypted body with " + SnmpContextv3Face.PROTOCOL_NAMES[privacyProtocol]);
171 }
172 } else {
173 privacyAsnOctets = new AsnOctets("");
174 }
175 asnSecurityObject.add(privacyAsnOctets);
176
177 ByteArrayOutputStream secOut = new ByteArrayOutputStream();
178 asnSecurityObject.write(secOut);
179 byte[] bytes = secOut.toByteArray();
180 AsnOctets asnSecurityParameters = new AsnOctets(bytes);
181
182 asnSequence.add(new AsnInteger(SnmpConstants.SNMP_VERSION_3));
183 asnSequence.add(asnHeaderData);
184 asnSequence.add(asnSecurityParameters);
185 if (context.isUsePrivacy()) {
186 asnSequence.add(asnEncryptedScopedPdu);
187 } else {
188 asnSequence.add(asnPlainScopedPdu);
189 }
190
191 if (AsnObject.debug > 10) {
192 System.out.println("\n" + getClass().getName() + ".EncodeSNMPv3(): ");
193 }
194
195 encodedSnmpMessageOutputStream = new ByteArrayOutputStream();
196 asnSequence.write(encodedSnmpMessageOutputStream);
197
198 int sz = encodedSnmpMessageOutputStream.size();
199 if (sz > context.getMaxRecvSize()) {
200 throw new EncodingException(
201 "Packet size (" + sz + ") is > maximum size (" + context.getMaxRecvSize() + ")");
202 }
203 byte[] message = encodedSnmpMessageOutputStream.toByteArray();
204
205
206 if (context.isUseAuthentication()) {
207 byte[] computedFingerprint = null;
208
209
210 computedFingerprint = context.computeFingerprint(node.getSnmpEngineId(), authenticationProtocol,
211 computedFingerprint, message);
212
213 int usmPos = asnSecurityParameters.getContentsPos();
214 int fpPos = fingerPrintOctets.getContentsPos();
215 fpPos += usmPos;
216 if (AsnObject.debug > 10) {
217 int fpLength = fingerPrintOctets.getContentsLength();
218 String str = "Pos finger print = " + fpPos + ", len = " + fpLength;
219 SnmpUtilities.dumpBytes(str, computedFingerprint);
220 }
221
222
223 SnmpUtilities.copyFingerprintToSnmpMessage(authenticationProtocol, computedFingerprint, message, fpPos);
224
225 }
226 return message;
227 }
228
229 private byte[] getMessageFlags(SnmpContextv3Basis context, byte messageType) throws EncodingException {
230 byte authMask = (byte) (0x0);
231 if (context.isUseAuthentication()) {
232 authMask = (byte) (0x1);
233 }
234 byte privMask = (byte) (0x0);
235 if (context.isUsePrivacy()) {
236 if (context.isUseAuthentication()) {
237 privMask = (byte) (0x2);
238 } else {
239 throw new EncodingException("Encryption without authentication is not allowed");
240 }
241 }
242 byte reportMask = (byte) (0x0);
243 if (context.isAuthoritative(messageType) == false) {
244 reportMask = (byte) (0x4);
245 }
246 byte[] msgFlags = new byte[1];
247 msgFlags[0] = (byte) (authMask | privMask | reportMask);
248 return msgFlags;
249 }
250 }