KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snmp4j > security > SecurityProtocols


1 /*_############################################################################
2   _##
3   _## SNMP4J - SecurityProtocols.java
4   _##
5   _## Copyright 2003-2007 Frank Fock and Jochen Katz (SNMP4J.org)
6   _##
7   _## Licensed under the Apache License, Version 2.0 (the "License");
8   _## you may not use this file except in compliance with the License.
9   _## You may obtain a copy of the License at
10   _##
11   _## http://www.apache.org/licenses/LICENSE-2.0
12   _##
13   _## Unless required by applicable law or agreed to in writing, software
14   _## distributed under the License is distributed on an "AS IS" BASIS,
15   _## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   _## See the License for the specific language governing permissions and
17   _## limitations under the License.
18   _##
19   _##########################################################################*/

20
21 package org.snmp4j.security;
22
23 import java.io.Serializable JavaDoc;
24 import org.snmp4j.smi.OID;
25 import java.io.InputStream JavaDoc;
26 import java.util.Properties JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import org.snmp4j.log.*;
29 import java.io.IOException JavaDoc;
30 import java.util.Hashtable JavaDoc;
31 import org.snmp4j.smi.OctetString;
32 import org.snmp4j.SNMP4JSettings;
33
34 /**
35  * The <code>SecurityProtocols</code> class holds all authentication and
36  * privacy protocols for a SNMP entity.
37  * <p>
38  * To register security protocols other than the default, set the system
39  * property {@link #SECURITY_PROTOCOLS_PROPERTIES} to a customized version
40  * of the <code>SecurityProtocols.properties</code> file. The path has to
41  * be specified relatively to this class.
42  *
43  * @author Jochen Katz & Frank Fock
44  * @version 1.1
45  */

46 public class SecurityProtocols implements Serializable JavaDoc {
47
48   private static final long serialVersionUID = 3800474900139635836L;
49
50   private java.util.Hashtable JavaDoc authProtocols;
51   private java.util.Hashtable JavaDoc privProtocols;
52
53   public static final String JavaDoc SECURITY_PROTOCOLS_PROPERTIES =
54       "org.snmp4j.securityProtocols";
55   private static final String JavaDoc SECURITY_PROTOCOLS_PROPERTIES_DEFAULT =
56       "SecurityProtocols.properties";
57   private static final LogAdapter logger = LogFactory.getLogger(SecurityProtocols.class);
58
59   private static SecurityProtocols instance = null;
60   private int maxAuthDigestLength = 0;
61   private int maxPrivDecryptParamsLength = 0;
62
63   protected SecurityProtocols() {
64     authProtocols = new Hashtable JavaDoc(5);
65     privProtocols = new Hashtable JavaDoc(5);
66   }
67
68   /**
69    * Get an instance of class SecurityProtocols.
70    *
71    * @return the globally used SecurityProtocols object.
72    */

73   public static SecurityProtocols getInstance() {
74     if (instance == null) {
75       instance = new SecurityProtocols();
76     }
77     return instance;
78   }
79
80   /**
81    * Set the <code>SecurityProtocols</code>
82    * @param securityProtocols SecurityProtocols
83    */

84   public static void setSecurityProtocols(SecurityProtocols securityProtocols) {
85     SecurityProtocols.instance = securityProtocols;
86   }
87
88   /**
89    * Add the default SecurityProtocols.
90    *
91    * The names of the SecurityProtocols to add are read from a
92    * properties file.
93    *
94    * @throws InternalError if the properties file cannot be opened/read.
95    */

96   public synchronized void addDefaultProtocols() {
97     if (SNMP4JSettings.isExtensibilityEnabled()) {
98       String JavaDoc secProtocols =
99           System.getProperty(SECURITY_PROTOCOLS_PROPERTIES,
100                              SECURITY_PROTOCOLS_PROPERTIES_DEFAULT);
101       InputStream JavaDoc is =
102           SecurityProtocols.class.getResourceAsStream(secProtocols);
103       if (is == null) {
104         throw new InternalError JavaDoc("Could not read '" + secProtocols +
105                                 "' from classpath!");
106       }
107       Properties JavaDoc props = new Properties JavaDoc();
108       try {
109         props.load(is);
110         for (Enumeration JavaDoc en = props.propertyNames(); en.hasMoreElements(); ) {
111           String JavaDoc className = (String JavaDoc) en.nextElement();
112           try {
113             Class JavaDoc c = Class.forName(className);
114             Object JavaDoc proto = c.newInstance();
115             if (proto instanceof AuthenticationProtocol) {
116               addAuthenticationProtocol((AuthenticationProtocol) proto);
117             }
118             else if (proto instanceof PrivacyProtocol) {
119               addPrivacyProtocol((PrivacyProtocol) proto);
120             }
121             else {
122               logger.error(
123                   "Failed to register security protocol because it does " +
124                   "not implement required interfaces: " + className);
125             }
126           }
127           catch (Exception JavaDoc cnfe) {
128             logger.error(cnfe);
129             throw new InternalError JavaDoc(cnfe.toString());
130           }
131         }
132       }
133       catch (IOException JavaDoc iox) {
134         String JavaDoc txt = "Could not read '" + secProtocols + "': " +
135             iox.getMessage();
136         logger.error(txt);
137         throw new InternalError JavaDoc(txt);
138       }
139       finally {
140         try {
141           is.close();
142         }
143         catch (IOException JavaDoc ex) {
144           // ignore
145
logger.warn(ex);
146         }
147       }
148     }
149     else {
150       addAuthenticationProtocol(new AuthMD5());
151       addAuthenticationProtocol(new AuthSHA());
152       addPrivacyProtocol(new PrivDES());
153       addPrivacyProtocol(new PrivAES128());
154       addPrivacyProtocol(new PrivAES192());
155       addPrivacyProtocol(new PrivAES256());
156     }
157   }
158
159   /**
160    * Add the given {@link AuthenticationProtocol}. If an authentication protocol
161    * with the supplied ID already exists, the supplied authentication protocol
162    * will not be added and the security protocols will not be unchang.
163    *
164    * @param auth
165    * the AuthenticationProtocol to add (an existing authentication protcol
166    * with <code>auth</code>'s ID remains unchanged).
167    */

168   public synchronized void addAuthenticationProtocol(AuthenticationProtocol auth) {
169     if (authProtocols.get(auth.getID()) == null) {
170       authProtocols.put(auth.getID(), auth);
171       if (auth.getDigestLength() > maxAuthDigestLength) {
172         maxAuthDigestLength = auth.getDigestLength();
173       }
174     }
175   }
176
177   /**
178    * Get the {@link AuthenticationProtocol} with the given ID.
179    *
180    * @param id
181    * The unique ID (specified as {@link OID}) of the AuthenticationProtocol.
182    * @return
183    * the AuthenticationProtocol object if it was added before,
184    * or null if not.
185    */

186   public AuthenticationProtocol getAuthenticationProtocol(OID id) {
187     if (id == null) {
188       return null;
189     }
190     return (AuthenticationProtocol)authProtocols.get(id);
191   }
192
193   /**
194    * Remove the given {@link AuthenticationProtocol}.
195    *
196    * @param auth The protocol to remove
197    */

198   public void removeAuthenticationProtocol(AuthenticationProtocol auth) {
199     authProtocols.remove(auth.getID());
200   }
201
202   /**
203    * Add the given {@link PrivacyProtocol}. If a privacy protocol
204    * with the supplied ID already exists, the supplied privacy protocol
205    * will not be added and the security protocols will not be changed.
206    *
207    * @param priv
208    * the PrivacyProtocol to add (an existing privacy protcol
209    * with <code>priv</code>'s ID remains unchanged).
210    */

211   public synchronized void addPrivacyProtocol(PrivacyProtocol priv) {
212     if (privProtocols.get(priv.getID()) == null) {
213       privProtocols.put(priv.getID(), priv);
214       if (priv.getDecryptParamsLength() > maxPrivDecryptParamsLength) {
215         maxPrivDecryptParamsLength = priv.getDecryptParamsLength();
216       }
217     }
218   }
219
220   /**
221    * Get the PrivacyProtocol with the given ID.
222    *
223    * @param id
224    * The unique ID (specified as {@link OID}) of the PrivacyProtocol.
225    * @return
226    * the {@link PrivacyProtocol} object if it was added before,
227    * or null if not.
228    */

229   public PrivacyProtocol getPrivacyProtocol(OID id) {
230     if (id == null) {
231       return null;
232     }
233     return (PrivacyProtocol)privProtocols.get(id);
234   }
235
236   /**
237    * Remove the given {@link PrivacyProtocol}.
238    *
239    * @param priv The protocol to remove
240    */

241   public void removePrivacyProtocol(PrivacyProtocol priv) {
242     privProtocols.remove(priv.getID());
243   }
244
245
246   /**
247    * Generates the localized key for the given password and engine id for the
248    * authentication protocol specified by the supplied OID.
249    *
250    * @param authProtocolID
251    * an <code>OID</code> identifying the authentication protocol to
252    * use.
253    * @param passwordString
254    * the authentication pass phrase.
255    * @param engineID
256    * the engine ID of the authoritative engine.
257    * @return
258    * the localized authentication key.
259    */

260   public byte[] passwordToKey(OID authProtocolID,
261                               OctetString passwordString,
262                               byte[] engineID) {
263
264     AuthenticationProtocol protocol =
265         (AuthenticationProtocol)authProtocols.get(authProtocolID);
266     if (protocol == null) {
267       return null;
268     }
269     return protocol.passwordToKey(passwordString, engineID);
270   }
271
272   /**
273    * Generates the localized key for the given password and engine id for the
274    * privacy protocol specified by the supplied OID.
275    *
276    * @param privProtocolID
277    * an <code>OID</code> identifying the privacy protocol the key should
278    * be created for.
279    * @param authProtocolID
280    * an <code>OID</code> identifying the authentication protocol to use.
281    * @param passwordString
282    * the authentication pass phrase.
283    * @param engineID
284    * the engine ID of the authoritative engine.
285    * @return
286    * the localized privacy key.
287    */

288   public byte[] passwordToKey(OID privProtocolID,
289                               OID authProtocolID,
290                               OctetString passwordString,
291                               byte[] engineID) {
292
293     AuthenticationProtocol authProtocol =
294         (AuthenticationProtocol)authProtocols.get(authProtocolID);
295     if (authProtocol == null) {
296       return null;
297     }
298     PrivacyProtocol privProtocol =
299         (PrivacyProtocol)privProtocols.get(privProtocolID);
300     if (privProtocol == null) {
301       return null;
302     }
303     byte[] key = authProtocol.passwordToKey(passwordString, engineID);
304
305     if (key == null) {
306       return null;
307     }
308     if (key.length >= privProtocol.getMinKeyLength()) {
309       if (key.length > privProtocol.getMaxKeyLength()) {
310         // truncate key
311
byte[] truncatedKey = new byte[privProtocol.getMaxKeyLength()];
312         System.arraycopy(key, 0, truncatedKey, 0, privProtocol.getMaxKeyLength());
313         return truncatedKey;
314       }
315       return key;
316     }
317     // we have to extend the key, currently only the AES draft
318
// defines this algorithm, so this may have to be changed for other
319
// privacy protocols
320
byte[] extKey = new byte[privProtocol.getMinKeyLength()];
321     int length = key.length;
322     for (int i=0; i<length; i++) {
323       extKey[i] = key[i];
324     }
325
326     while (length < extKey.length)
327     {
328       byte[] hash = authProtocol.hash(extKey, 0, length);
329
330       if (hash == null) {
331         return null;
332       }
333       int bytesToCopy = extKey.length - length;
334       if (bytesToCopy > authProtocol.getDigestLength()) {
335         bytesToCopy = authProtocol.getDigestLength();
336       }
337       for (int i=0; i<bytesToCopy; i++) {
338         extKey[length + i] = hash[i];
339       }
340
341       length += bytesToCopy;
342     }
343     return extKey;
344   }
345
346   /**
347    * Gets the maximum authentication key length of the all known
348    * authentication protocols.
349    * @return
350    * the maximum authentication key length of all authentication protocols
351    * that have been added to this <code>SecurityProtocols</code>
352    * instance.
353    */

354   public int getMaxAuthDigestLength() {
355     return maxAuthDigestLength;
356   }
357
358   /**
359    * Gets the maximum privacy key length of the currently known
360    * privacy protocols.
361    * @return
362    * the maximum privacy key length of all privacy protocols
363    * that have been added to this <code>SecurityProtocols</code>
364    * instance.
365    */

366   public int getMaxPrivDecryptParamsLength() {
367     return maxPrivDecryptParamsLength;
368   }
369 }
370
371
Popular Tags