/**
   * Generates the localized key for the given password and engine id for the privacy protocol
   * specified by the supplied OID.
   *
   * @param privProtocolID an <code>OID</code> identifying the privacy protocol the key should be
   *     created for.
   * @param authProtocolID an <code>OID</code> identifying the authentication protocol to use.
   * @param passwordString the authentication pass phrase.
   * @param engineID the engine ID of the authoritative engine.
   * @return the localized privacy key.
   */
  public byte[] passwordToKey(
      OID privProtocolID, OID authProtocolID, OctetString passwordString, byte[] engineID) {

    AuthenticationProtocol authProtocol = authProtocols.get(authProtocolID);
    if (authProtocol == null) {
      return null;
    }
    PrivacyProtocol privProtocol = privProtocols.get(privProtocolID);
    if (privProtocol == null) {
      return null;
    }
    byte[] key = authProtocol.passwordToKey(passwordString, engineID);

    if (key == null) {
      return null;
    }
    if (key.length >= privProtocol.getMinKeyLength()) {
      if (key.length > privProtocol.getMaxKeyLength()) {
        // truncate key
        byte[] truncatedKey = new byte[privProtocol.getMaxKeyLength()];
        System.arraycopy(key, 0, truncatedKey, 0, privProtocol.getMaxKeyLength());
        return truncatedKey;
      }
      return key;
    }
    // extend key if necessary
    byte[] extKey = privProtocol.extendShortKey(key, passwordString, engineID, authProtocol);
    return extKey;
  }
 /** run */
 public void run() {
   long now = System.currentTimeMillis();
   if ((socketCleaner == null) || (now - entry.getLastUse() >= connectionTimeout)) {
     if (logger.isDebugEnabled()) {
       logger.debug(
           "Socket has not been used for "
               + (now - entry.getLastUse())
               + " micro seconds, closing it");
     }
     sockets.remove(entry.getPeerAddress());
     try {
       synchronized (entry) {
         entry.getSocket().close();
       }
       logger.info("Socket to " + entry.getPeerAddress() + " closed due to timeout");
     } catch (IOException ex) {
       logger.error(ex);
     }
   } else {
     if (logger.isDebugEnabled()) {
       logger.debug("Scheduling " + ((entry.getLastUse() + connectionTimeout) - now));
     }
     socketCleaner.schedule(
         new SocketTimeout(entry), (entry.getLastUse() + connectionTimeout) - now);
   }
 }
 /**
  * Add the default SecurityProtocols.
  *
  * <p>The names of the SecurityProtocols to add are read from a properties file.
  *
  * @throws InternalError if the properties file cannot be opened/read.
  */
 public synchronized void addDefaultProtocols() {
   if (SNMP4JSettings.isExtensibilityEnabled()) {
     String secProtocols =
         System.getProperty(SECURITY_PROTOCOLS_PROPERTIES, SECURITY_PROTOCOLS_PROPERTIES_DEFAULT);
     InputStream is = SecurityProtocols.class.getResourceAsStream(secProtocols);
     if (is == null) {
       throw new InternalError("Could not read '" + secProtocols + "' from classpath!");
     }
     Properties props = new Properties();
     try {
       props.load(is);
       for (Enumeration en = props.propertyNames(); en.hasMoreElements(); ) {
         String className = en.nextElement().toString();
         try {
           Class c = Class.forName(className);
           Object proto = c.newInstance();
           if (proto instanceof AuthenticationProtocol) {
             addAuthenticationProtocol((AuthenticationProtocol) proto);
           } else if (proto instanceof PrivacyProtocol) {
             addPrivacyProtocol((PrivacyProtocol) proto);
           } else {
             logger.error(
                 "Failed to register security protocol because it does "
                     + "not implement required interfaces: "
                     + className);
           }
         } catch (Exception cnfe) {
           logger.error(cnfe);
           throw new InternalError(cnfe.toString());
         }
       }
     } catch (IOException iox) {
       String txt = "Could not read '" + secProtocols + "': " + iox.getMessage();
       logger.error(txt);
       throw new InternalError(txt);
     } finally {
       try {
         is.close();
       } catch (IOException ex) {
         // ignore
         logger.warn(ex);
       }
     }
   } else {
     addAuthenticationProtocol(new AuthMD5());
     addAuthenticationProtocol(new AuthSHA());
     addPrivacyProtocol(new PrivDES());
     addPrivacyProtocol(new PrivAES128());
     addPrivacyProtocol(new PrivAES192());
     addPrivacyProtocol(new PrivAES256());
   }
 }
 private void dispatchMessage(
     TcpAddress incomingAddress, ByteBuffer byteBuffer, long bytesRead) {
   byteBuffer.flip();
   if (logger.isDebugEnabled()) {
     logger.debug(
         "Received message from "
             + incomingAddress
             + " with length "
             + bytesRead
             + ": "
             + new OctetString(byteBuffer.array(), 0, (int) bytesRead).toHexString());
   }
   ByteBuffer bis;
   if (isAsyncMsgProcessingSupported()) {
     byte[] bytes = new byte[(int) bytesRead];
     System.arraycopy(byteBuffer.array(), 0, bytes, 0, (int) bytesRead);
     bis = ByteBuffer.wrap(bytes);
   } else {
     bis = ByteBuffer.wrap(byteBuffer.array(), 0, (int) bytesRead);
   }
   fireProcessMessage(incomingAddress, bis);
 }
 /**
  * Limits the supplied key value to the specified maximum length
  *
  * @param key the key to truncate.
  * @param maxKeyLength the maximum length of the returned key.
  * @return the truncated key with a length of <code>min(key.length, maxKeyLength)</code>.
  * @since 1.9
  */
 public byte[] truncateKey(byte[] key, int maxKeyLength) {
   byte[] truncatedNewKey = new byte[Math.min(maxKeyLength, key.length)];
   System.arraycopy(key, 0, truncatedNewKey, 0, truncatedNewKey.length);
   return truncatedNewKey;
 }
 public void run() {
   DatagramSocket socketCopy = socket;
   if (socketCopy != null) {
     try {
       socketCopy.setSoTimeout(getSocketTimeout());
       if (receiveBufferSize > 0) {
         socketCopy.setReceiveBufferSize(Math.max(receiveBufferSize, maxInboundMessageSize));
       }
       if (logger.isDebugEnabled()) {
         logger.debug(
             "UDP receive buffer size for socket "
                 + getAddress()
                 + " is set to: "
                 + socketCopy.getReceiveBufferSize());
       }
     } catch (SocketException ex) {
       logger.error(ex);
       setSocketTimeout(0);
     }
   }
   while (!stop) {
     DatagramPacket packet =
         new DatagramPacket(buf, buf.length, udpAddress.getInetAddress(), udpAddress.getPort());
     try {
       socketCopy = socket;
       try {
         if (socketCopy == null) {
           stop = true;
           continue;
         }
         socketCopy.receive(packet);
       } catch (InterruptedIOException iiox) {
         if (iiox.bytesTransferred <= 0) {
           continue;
         }
       }
       if (logger.isDebugEnabled()) {
         logger.debug(
             "Received message from "
                 + packet.getAddress()
                 + "/"
                 + packet.getPort()
                 + " with length "
                 + packet.getLength()
                 + ": "
                 + new OctetString(packet.getData(), 0, packet.getLength()).toHexString());
       }
       ByteBuffer bis;
       // If messages are processed asynchronously (i.e. multi-threaded)
       // then we have to copy the buffer's content here!
       if (isAsyncMsgProcessingSupported()) {
         byte[] bytes = new byte[packet.getLength()];
         System.arraycopy(packet.getData(), 0, bytes, 0, bytes.length);
         bis = ByteBuffer.wrap(bytes);
       } else {
         bis = ByteBuffer.wrap(packet.getData());
       }
       TransportStateReference stateReference =
           new TransportStateReference(
               DefaultUdpTransportMapping.this,
               udpAddress,
               null,
               SecurityLevel.undefined,
               SecurityLevel.undefined,
               false,
               socketCopy);
       fireProcessMessage(
           new UdpAddress(packet.getAddress(), packet.getPort()), bis, stateReference);
     } catch (SocketTimeoutException stex) {
       // ignore
     } catch (PortUnreachableException purex) {
       synchronized (DefaultUdpTransportMapping.this) {
         listener = null;
       }
       logger.error(purex);
       if (logger.isDebugEnabled()) {
         purex.printStackTrace();
       }
       if (SNMP4JSettings.isFowardRuntimeExceptions()) {
         throw new RuntimeException(purex);
       }
       break;
     } catch (SocketException soex) {
       if (!stop) {
         logger.error(
             "Socket for transport mapping " + toString() + " error: " + soex.getMessage(),
             soex);
       }
       if (SNMP4JSettings.isFowardRuntimeExceptions()) {
         stop = true;
         throw new RuntimeException(soex);
       }
     } catch (IOException iox) {
       logger.warn(iox);
       if (logger.isDebugEnabled()) {
         iox.printStackTrace();
       }
       if (SNMP4JSettings.isFowardRuntimeExceptions()) {
         throw new RuntimeException(iox);
       }
     }
   }
   synchronized (DefaultUdpTransportMapping.this) {
     listener = null;
     stop = true;
     DatagramSocket closingSocket = socket;
     if ((closingSocket != null) && (!closingSocket.isClosed())) {
       closingSocket.close();
     }
   }
   if (logger.isDebugEnabled()) {
     logger.debug("Worker task stopped:" + getClass().getName());
   }
 }
 public void used() {
   lastUse = System.currentTimeMillis();
 }
 public SocketEntry(TcpAddress address, Socket socket) {
   this.peerAddress = address;
   this.socket = socket;
   this.lastUse = System.currentTimeMillis();
 }