1 /* 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package com.sun.jmx.snmp.IPAcl; 28 29 30 31 // java import 32 // 33 import java.io.Serializable; 34 import java.io.File; 35 import java.io.FileInputStream; 36 import java.io.FileNotFoundException; 37 import java.net.InetAddress; 38 import java.net.UnknownHostException; 39 import java.util.Hashtable; 40 import java.util.logging.Level; 41 import java.util.Vector; 42 import java.util.Enumeration; 43 import java.util.HashSet; 44 import java.security.acl.AclEntry; 45 import java.security.acl.NotOwnerException; 46 47 // SNMP Runtime import 48 // 49 import static com.sun.jmx.defaults.JmxProperties.SNMP_LOGGER; 50 import com.sun.jmx.snmp.InetAddressAcl; 51 52 /** 53 * Defines an implementation of the {@link com.sun.jmx.snmp.InetAddressAcl InetAddressAcl} interface. 54 * <p> 55 * In this implementation the ACL information is stored on a flat file and 56 * its default location is "$JRE/lib/snmp.acl" - See 57 * {@link #getDefaultAclFileName()} 58 * <p> 59 * <OL> 60 * 61 * <p><b>This API is a Sun Microsystems internal API and is subject 62 * to change without notice.</b></p> 63 */ 64 65 public class SnmpAcl implements InetAddressAcl, Serializable { 66 private static final long serialVersionUID = -6702287103824397063L; 67 68 static final PermissionImpl READ = new PermissionImpl("READ"); 69 static final PermissionImpl WRITE = new PermissionImpl("WRITE"); 70 71 /** 72 * Constructs the Java Dynamic Management(TM) Access Control List 73 * based on IP addresses. The ACL will take the given owner name. 74 * The current IP address will be the owner of the ACL. 75 * 76 * @param Owner The name of the ACL Owner. 77 * 78 * @exception UnknownHostException If the local host is unknown. 79 * @exception IllegalArgumentException If the ACL file doesn't exist. 80 */ 81 public SnmpAcl(String Owner) 82 throws UnknownHostException, IllegalArgumentException { 83 this(Owner,null); 84 } 85 86 /** 87 * Constructs the Java Dynamic Management(TM) Access Control List 88 * based on IP addresses. The ACL will take the given owner name. 89 * The current IP address will be the owner of the ACL. 90 * 91 * @param Owner The name of the ACL Owner. 92 * @param aclFileName The name of the ACL File. 93 * 94 * @exception UnknownHostException If the local host is unknown. 95 * @exception IllegalArgumentException If the ACL file doesn't exist. 96 */ 97 public SnmpAcl(String Owner, String aclFileName) 98 throws UnknownHostException, IllegalArgumentException { 99 trapDestList= new Hashtable<InetAddress, Vector<String>>(); 100 informDestList= new Hashtable<InetAddress, Vector<String>>(); 101 102 // PrincipalImpl() take the current host as entry 103 owner = new PrincipalImpl(); 104 try { 105 acl = new AclImpl(owner,Owner); 106 AclEntry ownEntry = new AclEntryImpl(owner); 107 ownEntry.addPermission(READ); 108 ownEntry.addPermission(WRITE); 109 acl.addEntry(owner,ownEntry); 110 } catch (NotOwnerException ex) { 111 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 112 SNMP_LOGGER.logp(Level.FINEST, SnmpAcl.class.getName(), 113 "SnmpAcl(String,String)", 114 "Should never get NotOwnerException as the owner " + 115 "is built in this constructor"); 116 } 117 } 118 if (aclFileName == null) setDefaultFileName(); 119 else setAuthorizedListFile(aclFileName); 120 readAuthorizedListFile(); 121 } 122 123 /** 124 * Returns an enumeration of the entries in this ACL. Each element in the 125 * enumeration is of type <CODE>java.security.acl.AclEntry</CODE>. 126 * 127 * @return An enumeration of the entries in this ACL. 128 */ 129 public Enumeration<AclEntry> entries() { 130 return acl.entries(); 131 } 132 133 /** 134 * Returns ann enumeration of community strings. Community strings are returned as String. 135 * @return The enumeration of community strings. 136 */ 137 public Enumeration<String> communities() { 138 HashSet<String> set = new HashSet<String>(); 139 Vector<String> res = new Vector<String>(); 140 for (Enumeration<AclEntry> e = acl.entries() ; e.hasMoreElements() ;) { 141 AclEntryImpl entry = (AclEntryImpl) e.nextElement(); 142 for (Enumeration<String> cs = entry.communities(); 143 cs.hasMoreElements() ;) { 144 set.add(cs.nextElement()); 145 } 146 } 147 String[] objs = set.toArray(new String[0]); 148 for(int i = 0; i < objs.length; i++) 149 res.addElement(objs[i]); 150 151 return res.elements(); 152 } 153 154 /** 155 * Returns the name of the ACL. 156 * 157 * @return The name of the ACL. 158 */ 159 public String getName() { 160 return acl.getName(); 161 } 162 163 /** 164 * Returns the read permission instance used. 165 * 166 * @return The read permission instance. 167 */ 168 static public PermissionImpl getREAD() { 169 return READ; 170 } 171 172 /** 173 * Returns the write permission instance used. 174 * 175 * @return The write permission instance. 176 */ 177 static public PermissionImpl getWRITE() { 178 return WRITE; 179 } 180 181 /** 182 * Get the default name for the ACL file. 183 * In this implementation this is "$JRE/lib/snmp.acl" 184 * @return The default name for the ACL file. 185 **/ 186 public static String getDefaultAclFileName() { 187 final String fileSeparator = 188 System.getProperty("file.separator"); 189 final StringBuilder defaultAclName = 190 new StringBuilder(System.getProperty("java.home")). 191 append(fileSeparator).append("lib").append(fileSeparator). 192 append("snmp.acl"); 193 return defaultAclName.toString(); 194 } 195 196 /** 197 * Sets the full path of the file containing the ACL information. 198 * 199 * @param filename The full path of the file containing the ACL information. 200 * @throws IllegalArgumentException If the passed ACL file doesn't exist. 201 */ 202 public void setAuthorizedListFile(String filename) 203 throws IllegalArgumentException { 204 File file = new File(filename); 205 if (!file.isFile() ) { 206 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 207 SNMP_LOGGER.logp(Level.FINEST, SnmpAcl.class.getName(), 208 "setAuthorizedListFile", "ACL file not found: " + filename); 209 } 210 throw new 211 IllegalArgumentException("The specified file ["+file+"] "+ 212 "doesn't exist or is not a file, "+ 213 "no configuration loaded"); 214 } 215 if (SNMP_LOGGER.isLoggable(Level.FINER)) { 216 SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), 217 "setAuthorizedListFile", "Default file set to " + filename); 218 } 219 authorizedListFile = filename; 220 } 221 222 /** 223 * Resets this ACL to the values contained in the configuration file. 224 * 225 * @exception NotOwnerException If the principal attempting the reset is not an owner of this ACL. 226 * @exception UnknownHostException If IP addresses for hosts contained in the ACL file couldn't be found. 227 */ 228 public void rereadTheFile() throws NotOwnerException, UnknownHostException { 229 alwaysAuthorized = false; 230 acl.removeAll(owner); 231 trapDestList.clear(); 232 informDestList.clear(); 233 AclEntry ownEntry = new AclEntryImpl(owner); 234 ownEntry.addPermission(READ); 235 ownEntry.addPermission(WRITE); 236 acl.addEntry(owner,ownEntry); 237 readAuthorizedListFile(); 238 } 239 240 /** 241 * Returns the full path of the file used to get ACL information. 242 * 243 * @return The full path of the file used to get ACL information. 244 */ 245 public String getAuthorizedListFile() { 246 return authorizedListFile; 247 } 248 249 /** 250 * Checks whether or not the specified host has <CODE>READ</CODE> access. 251 * 252 * @param address The host address to check. 253 * 254 * @return <CODE>true</CODE> if the host has read permission, <CODE>false</CODE> otherwise. 255 */ 256 public boolean checkReadPermission(InetAddress address) { 257 if (alwaysAuthorized) return ( true ); 258 PrincipalImpl p = new PrincipalImpl(address); 259 return acl.checkPermission(p, READ); 260 } 261 262 /** 263 * Checks whether or not the specified host and community have <CODE>READ</CODE> access. 264 * 265 * @param address The host address to check. 266 * @param community The community associated with the host. 267 * 268 * @return <CODE>true</CODE> if the pair (host, community) has read permission, <CODE>false</CODE> otherwise. 269 */ 270 public boolean checkReadPermission(InetAddress address, String community) { 271 if (alwaysAuthorized) return ( true ); 272 PrincipalImpl p = new PrincipalImpl(address); 273 return acl.checkPermission(p, community, READ); 274 } 275 276 /** 277 * Checks whether or not a community string is defined. 278 * 279 * @param community The community to check. 280 * 281 * @return <CODE>true</CODE> if the community is known, <CODE>false</CODE> otherwise. 282 */ 283 public boolean checkCommunity(String community) { 284 return acl.checkCommunity(community); 285 } 286 287 /** 288 * Checks whether or not the specified host has <CODE>WRITE</CODE> access. 289 * 290 * @param address The host address to check. 291 * 292 * @return <CODE>true</CODE> if the host has write permission, <CODE>false</CODE> otherwise. 293 */ 294 public boolean checkWritePermission(InetAddress address) { 295 if (alwaysAuthorized) return ( true ); 296 PrincipalImpl p = new PrincipalImpl(address); 297 return acl.checkPermission(p, WRITE); 298 } 299 300 /** 301 * Checks whether or not the specified host and community have <CODE>WRITE</CODE> access. 302 * 303 * @param address The host address to check. 304 * @param community The community associated with the host. 305 * 306 * @return <CODE>true</CODE> if the pair (host, community) has write permission, <CODE>false</CODE> otherwise. 307 */ 308 public boolean checkWritePermission(InetAddress address, String community) { 309 if (alwaysAuthorized) return ( true ); 310 PrincipalImpl p = new PrincipalImpl(address); 311 return acl.checkPermission(p, community, WRITE); 312 } 313 314 /** 315 * Returns an enumeration of trap destinations. 316 * 317 * @return An enumeration of the trap destinations (enumeration of <CODE>InetAddress</CODE>). 318 */ 319 public Enumeration<InetAddress> getTrapDestinations() { 320 return trapDestList.keys(); 321 } 322 323 /** 324 * Returns an enumeration of trap communities for a given host. 325 * 326 * @param i The address of the host. 327 * 328 * @return An enumeration of trap communities for a given host (enumeration of <CODE>String</CODE>). 329 */ 330 public Enumeration<String> getTrapCommunities(InetAddress i) { 331 Vector<String> list = null; 332 if ((list = trapDestList.get(i)) != null ) { 333 if (SNMP_LOGGER.isLoggable(Level.FINER)) { 334 SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), 335 "getTrapCommunities", "["+i.toString()+"] is in list"); 336 } 337 return list.elements(); 338 } else { 339 list = new Vector<>(); 340 if (SNMP_LOGGER.isLoggable(Level.FINER)) { 341 SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), 342 "getTrapCommunities", "["+i.toString()+"] is not in list"); 343 } 344 return list.elements(); 345 } 346 } 347 348 /** 349 * Returns an enumeration of inform destinations. 350 * 351 * @return An enumeration of the inform destinations (enumeration of <CODE>InetAddress</CODE>). 352 */ 353 public Enumeration<InetAddress> getInformDestinations() { 354 return informDestList.keys(); 355 } 356 357 /** 358 * Returns an enumeration of inform communities for a given host. 359 * 360 * @param i The address of the host. 361 * 362 * @return An enumeration of inform communities for a given host (enumeration of <CODE>String</CODE>). 363 */ 364 public Enumeration<String> getInformCommunities(InetAddress i) { 365 Vector<String> list = null; 366 if ((list = informDestList.get(i)) != null ) { 367 if (SNMP_LOGGER.isLoggable(Level.FINER)) { 368 SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), 369 "getInformCommunities", "["+i.toString()+"] is in list"); 370 } 371 return list.elements(); 372 } else { 373 list = new Vector<>(); 374 if (SNMP_LOGGER.isLoggable(Level.FINER)) { 375 SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), 376 "getInformCommunities", "["+i.toString()+"] is not in list"); 377 } 378 return list.elements(); 379 } 380 } 381 382 /** 383 * Converts the input configuration file into ACL. 384 */ 385 private void readAuthorizedListFile() { 386 387 alwaysAuthorized = false; 388 389 if (authorizedListFile == null) { 390 if (SNMP_LOGGER.isLoggable(Level.FINER)) { 391 SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), 392 "readAuthorizedListFile", "alwaysAuthorized set to true"); 393 } 394 alwaysAuthorized = true ; 395 } else { 396 // Read the file content 397 Parser parser = null; 398 try { 399 parser= new Parser(new FileInputStream(getAuthorizedListFile())); 400 } catch (FileNotFoundException e) { 401 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 402 SNMP_LOGGER.logp(Level.FINEST, SnmpAcl.class.getName(), 403 "readAuthorizedListFile", 404 "The specified file was not found, authorize everybody"); 405 } 406 alwaysAuthorized = true ; 407 return; 408 } 409 410 try { 411 JDMSecurityDefs n = parser.SecurityDefs(); 412 n.buildAclEntries(owner, acl); 413 n.buildTrapEntries(trapDestList); 414 n.buildInformEntries(informDestList); 415 } catch (ParseException e) { 416 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 417 SNMP_LOGGER.logp(Level.FINEST, SnmpAcl.class.getName(), 418 "readAuthorizedListFile", "Got parsing exception", e); 419 } 420 throw new IllegalArgumentException(e.getMessage()); 421 } catch (Error err) { 422 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 423 SNMP_LOGGER.logp(Level.FINEST, SnmpAcl.class.getName(), 424 "readAuthorizedListFile", "Got unexpected error", err); 425 } 426 throw new IllegalArgumentException(err.getMessage()); 427 } 428 429 for(Enumeration<AclEntry> e = acl.entries(); e.hasMoreElements();) { 430 AclEntryImpl aa = (AclEntryImpl) e.nextElement(); 431 if (SNMP_LOGGER.isLoggable(Level.FINER)) { 432 SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), 433 "readAuthorizedListFile", 434 "===> " + aa.getPrincipal().toString()); 435 } 436 for (Enumeration<java.security.acl.Permission> eee = aa.permissions();eee.hasMoreElements();) { 437 java.security.acl.Permission perm = eee.nextElement(); 438 if (SNMP_LOGGER.isLoggable(Level.FINER)) { 439 SNMP_LOGGER.logp(Level.FINER, SnmpAcl.class.getName(), 440 "readAuthorizedListFile", "perm = " + perm); 441 } 442 } 443 } 444 } 445 } 446 447 /** 448 * Set the default full path for "snmp.acl" input file. 449 * Do not complain if the file does not exists. 450 */ 451 private void setDefaultFileName() { 452 try { 453 setAuthorizedListFile(getDefaultAclFileName()); 454 } catch (IllegalArgumentException x) { 455 // OK... 456 } 457 } 458 459 460 // PRIVATE VARIABLES 461 //------------------ 462 463 /** 464 * Represents the Access Control List. 465 */ 466 private AclImpl acl = null; 467 /** 468 * Flag indicating whether the access is always authorized. 469 * <BR>This is the case if there is no flat file defined. 470 */ 471 private boolean alwaysAuthorized = false; 472 /** 473 * Represents the Access Control List flat file. 474 */ 475 private String authorizedListFile = null; 476 /** 477 * Contains the hosts list for trap destination. 478 */ 479 private Hashtable<InetAddress, Vector<String>> trapDestList = null; 480 /** 481 * Contains the hosts list for inform destination. 482 */ 483 private Hashtable<InetAddress, Vector<String>> informDestList = null; 484 485 private PrincipalImpl owner = null; 486 }