1 // NAME 2 // $RCSfile: UsmDiscoveryBean.java,v $ 3 // DESCRIPTION 4 // [given below in javadoc format] 5 // DELTA 6 // $Revision: 1.21 $ 7 // CREATED 8 // $Date: 2009/03/05 15:51:42 $ 9 // COPYRIGHT 10 // Westhawk Ltd 11 // TO DO 12 // 13 14 /* 15 * Copyright (C) 2000 - 2006 by Westhawk Ltd 16 * 17 * Permission to use, copy, modify, and distribute this software 18 * for any purpose and without fee is hereby granted, provided 19 * that the above copyright notices appear in all copies and that 20 * both the copyright notice and this permission notice appear in 21 * supporting documentation. 22 * This software is provided "as is" without express or implied 23 * warranty. 24 * author <a href="mailto:snmp@westhawk.co.uk">Tim Panton</a> 25 */ 26 27 package uk.co.westhawk.snmp.beans; 28 29 /*- 30 * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲ 31 * SNMP Java Client 32 * ჻჻჻჻჻჻ 33 * Copyright 2023 MetricsHub, Westhawk 34 * ჻჻჻჻჻჻ 35 * This program is free software: you can redistribute it and/or modify 36 * it under the terms of the GNU Lesser General Public License as 37 * published by the Free Software Foundation, either version 3 of the 38 * License, or (at your option) any later version. 39 * 40 * This program is distributed in the hope that it will be useful, 41 * but WITHOUT ANY WARRANTY; without even the implied warranty of 42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 43 * GNU General Lesser Public License for more details. 44 * 45 * You should have received a copy of the GNU General Lesser Public 46 * License along with this program. If not, see 47 * <http://www.gnu.org/licenses/lgpl-3.0.html>. 48 * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱ 49 */ 50 51 import uk.co.westhawk.snmp.stack.*; 52 import uk.co.westhawk.snmp.pdu.*; 53 import java.util.*; 54 55 /** 56 * <p> 57 * This bean performs the SNMPv3 USM discovery process. 58 * </p> 59 * 60 * <p> 61 * The process consists of two steps: first the SNMP engine ID has to be 62 * discovered, second the timeline details of the SNMP engine ID have to 63 * be discovered. For the last step the username of the principal is 64 * needed. 65 * </p> 66 * 67 * <p> 68 * See <a href="http://www.ietf.org/rfc/rfc3414.txt">SNMP-USER-BASED-SM-MIB</a>. 69 * </p> 70 * 71 * @author <a href="mailto:snmp@westhawk.co.uk">Birgit Arkesteijn</a> 72 * @version $Revision: 1.21 $ $Date: 2009/03/05 15:51:42 $ 73 */ 74 public class UsmDiscoveryBean { 75 private static final String version_id = "@(#)$Id: UsmDiscoveryBean.java,v 1.21 2009/03/05 15:51:42 birgita Exp $ Copyright Westhawk Ltd"; 76 77 private SnmpContextv3Pool context; 78 private String userName = null; 79 private String userAuthPassword = null; 80 private String userPrivPassword = null; 81 private int authProtocol, privProtocol; 82 private int retry_intervals[] = { 500, 1000, 2000, 5000, 5000 }; 83 84 /** 85 * Constructor. 86 * 87 * @param host The host to discover 88 * @param port The port to discover 89 * @see SnmpContextv3#SnmpContextv3(String, int) 90 * @see #startDiscovery() 91 */ 92 public UsmDiscoveryBean(String host, int port) 93 throws java.io.IOException { 94 this(host, port, null, SnmpContextBasisFace.STANDARD_SOCKET); 95 } 96 97 /** 98 * Constructor. 99 * 100 * @param host The host to discover 101 * @param port The port to discover 102 * @param bindAddr The local address the server will bind to 103 * @param typeSocketA The type of socket to use. 104 * 105 * @see SnmpContextv3#SnmpContextv3(String, int, String, String) 106 * @see #startDiscovery() 107 */ 108 public UsmDiscoveryBean(String host, int port, String bindAddr, String typeSocketA) 109 throws java.io.IOException { 110 context = new SnmpContextv3Pool(host, port, bindAddr, typeSocketA); 111 } 112 113 /** 114 * Sets the user's authentication details. 115 * With these details the time line details will be retrieved. 116 * If the user details are not set, only the engine ID will be 117 * discovered. 118 * 119 * <p> 120 * The time line details only need to be known when the user want to 121 * send authenticated message to this SNMP engine. 122 * </p> 123 * 124 * @param newUserName The user name 125 * @param newUserPassword The user authentication password 126 * @param protocol The user authentication protocol 127 * 128 * @see SnmpContextv3#setUserName(String) 129 * @see SnmpContextv3#setUserAuthenticationPassword(String) 130 * @see SnmpContextv3#setAuthenticationProtocol(int) 131 */ 132 public void setAuthenticationDetails(String newUserName, String newUserPassword, 133 int protocol) { 134 userName = newUserName; 135 userAuthPassword = newUserPassword; 136 authProtocol = protocol; 137 } 138 139 /** 140 * Sets the user's privacy details. 141 * With these details the time line details will be retrieved if needed. 142 * 143 * <p> 144 * The time line details only need to be known when the user want to 145 * send authenticated message to this SNMP engine. 146 * </p> 147 * 148 * @param newUserPassword The user privacy password 149 * 150 * @see SnmpContextv3#setUserPrivacyPassword(String) 151 */ 152 public void setPrivacyDetails(String newUserPassword, int protocol) { 153 userPrivPassword = newUserPassword; 154 privProtocol = protocol; 155 } 156 157 /** 158 * Sets the retry intervals of the PDU. The length of the array 159 * corresponds with the number of retries. Each entry in the array 160 * is the number of milliseconds of each try. 161 * 162 * <p> 163 * If used, please set before sending! 164 * </p> 165 * 166 * The default is {500, 1000, 2000, 5000, 5000}. 167 * It is good practice to make the interval bigger with each retry, 168 * if the numbers are the same the chance of collision is higher. 169 * 170 * @param rinterval The interval in msec of each retry 171 * @see Pdu#setRetryIntervals(int[]) 172 */ 173 public void setRetryIntervals(int rinterval[]) { 174 retry_intervals = rinterval; 175 } 176 177 /** 178 * Starts the discovery. This method will send a Pdu to discover the 179 * SNMP engine ID. Set the user details before calling this method, if 180 * you want the time line details to be discovered as well. 181 * 182 * <p> 183 * This is a blocking call! It will return when it has done the whole 184 * discovery. 185 * </p> 186 * 187 * @see #setAuthenticationDetails(String, String, int) 188 * @see #discoveryEngineId 189 * @see #discoveryTimeLine 190 */ 191 // Thanks to "Cochran, Steve A." <steve@more.net>; 192 // freeResources(); is called before throwing an exception 193 public void startDiscovery() 194 throws PduException, java.io.IOException { 195 try { 196 discoveryEngineId(); 197 } catch (PduException exc) { 198 // You shouldn't really get an exception when doing engineID 199 // discovery. 200 freeResources(); // <-- Steve 201 throw new PduException("Engine ID discovery: " 202 + exc.getMessage()); 203 } 204 205 try { 206 discoveryTimeLine(); 207 } catch (PduException exc) { 208 // You can get an exception for authPriv. I noticed that when 209 // testing against MG-SOFT. 210 // Only throw the exception if the timeline was not discovered. 211 212 TimeWindow tWindow = TimeWindow.getCurrent(); 213 String engineId = tWindow.getSnmpEngineId(context.getSendToHostAddress(), 214 context.getPort()); 215 if (tWindow.isTimeLineKnown(engineId) == false) { 216 freeResources(); // <-- Steve 217 throw new PduException("Timeline discovery: " 218 + exc.getMessage()); 219 } 220 } 221 222 if (AsnObject.debug > 4) { 223 System.out.println(getClass().getName() + ".startDiscovery(): " 224 + "Done, context " + context.toString()); 225 } 226 227 freeResources(); 228 } 229 230 /** 231 * Destroy the context in use. 232 */ 233 public void freeResources() { 234 context.destroy(); 235 context = null; 236 } 237 238 /** 239 * Starts the discovery of the SNMP engine ID. 240 * 241 * <p> 242 * This is a blocking call! It will return when it has done the whole 243 * discovery. 244 * </p> 245 * 246 * @see #startDiscovery 247 * @see #discoveryTimeLine 248 */ 249 protected void discoveryEngineId() 250 throws PduException, java.io.IOException { 251 DiscoveryPdu pdu; 252 253 TimeWindow tWindow = TimeWindow.getCurrent(); 254 String engineId = tWindow.getSnmpEngineId(context.getHost(), 255 context.getPort()); 256 257 // Just check again to be sure 258 if (engineId == null) { 259 if (AsnObject.debug > 4) { 260 System.out.println(getClass().getName() + ".discoveryEngineId(): " 261 + "Starting discovery Engine ID ..."); 262 } 263 context.setUserName(""); 264 context.setUseAuthentication(false); 265 context.setUsePrivacy(false); 266 context.setContextEngineId(new byte[0]); 267 context.setContextName(""); 268 269 pdu = new DiscoveryPdu(context); 270 pdu.setRetryIntervals(retry_intervals); 271 pdu.send(); 272 pdu.waitForSelf(); 273 varbind[] vars = pdu.getResponseVarbinds(); 274 } 275 } 276 277 /** 278 * Starts the discovery of the Time line. 279 * 280 * <p> 281 * This is a blocking call! It will return when it has done the whole 282 * discovery. 283 * </p> 284 * 285 * @see #startDiscovery 286 * @see #discoveryEngineId 287 */ 288 protected void discoveryTimeLine() 289 throws PduException, java.io.IOException { 290 DiscoveryPdu pdu; 291 292 TimeWindow tWindow = TimeWindow.getCurrent(); 293 String engineId = tWindow.getSnmpEngineId(context.getSendToHostAddress(), 294 context.getPort()); 295 296 // The engineId should be known by now. 297 // Only do timeline discovery if it is not known yet. 298 if (tWindow.isTimeLineKnown(engineId) == false && userName != null) { 299 if (AsnObject.debug > 4) { 300 System.out.println(getClass().getName() + ".discoveryTimeLine(): " 301 + "Starting discovery Timeline ..."); 302 } 303 context.setUserName(userName); 304 context.setUserAuthenticationPassword(userAuthPassword); 305 context.setUseAuthentication(true); 306 context.setAuthenticationProtocol(authProtocol); 307 context.setContextEngineId(new byte[0]); 308 context.setContextName(""); 309 310 if (userPrivPassword != null) { 311 context.setUsePrivacy(true); 312 context.setUserPrivacyPassword(userPrivPassword); 313 context.setPrivacyProtocol(privProtocol); 314 } else { 315 context.setUsePrivacy(false); 316 } 317 318 pdu = new DiscoveryPdu(context); 319 pdu.setRetryIntervals(retry_intervals); 320 pdu.send(); 321 pdu.waitForSelf(); 322 varbind[] vars = pdu.getResponseVarbinds(); 323 324 if (AsnObject.debug > 4) { 325 System.out.println("Did discovery time line"); 326 } 327 } 328 } 329 330 }