jdk/src/jdk.snmp/share/classes/com/sun/jmx/snmp/SnmpV3Message.java
changeset 27193 db6241373358
parent 27175 2c33a5c73a2e
parent 27192 a16236cd61d7
child 27194 48c1741d0f2a
equal deleted inserted replaced
27175:2c33a5c73a2e 27193:db6241373358
     1 /*
       
     2  * Copyright (c) 2001, 2006, 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 package com.sun.jmx.snmp;
       
    26 
       
    27 // java imports
       
    28 //
       
    29 import java.util.Vector;
       
    30 import java.util.logging.Level;
       
    31 import java.net.InetAddress;
       
    32 
       
    33 // import debug stuff
       
    34 //
       
    35 import static com.sun.jmx.defaults.JmxProperties.SNMP_LOGGER;
       
    36 import com.sun.jmx.snmp.internal.SnmpMsgProcessingSubSystem;
       
    37 import com.sun.jmx.snmp.internal.SnmpSecurityModel;
       
    38 import com.sun.jmx.snmp.internal.SnmpDecryptedPdu;
       
    39 import com.sun.jmx.snmp.internal.SnmpSecurityCache;
       
    40 
       
    41 import com.sun.jmx.snmp.SnmpMsg;
       
    42 import com.sun.jmx.snmp.SnmpPdu;
       
    43 import com.sun.jmx.snmp.SnmpStatusException;
       
    44 import com.sun.jmx.snmp.SnmpTooBigException;
       
    45 import com.sun.jmx.snmp.SnmpScopedPduBulk;
       
    46 import com.sun.jmx.snmp.BerException;
       
    47 import com.sun.jmx.snmp.SnmpScopedPduRequest;
       
    48 import com.sun.jmx.snmp.BerDecoder;
       
    49 import com.sun.jmx.snmp.SnmpDefinitions;
       
    50 import com.sun.jmx.snmp.SnmpEngineId;
       
    51 import com.sun.jmx.snmp.SnmpScopedPduPacket;
       
    52 import com.sun.jmx.snmp.BerEncoder;
       
    53 import com.sun.jmx.snmp.SnmpPduRequestType;
       
    54 import com.sun.jmx.snmp.SnmpPduBulkType;
       
    55 
       
    56 /**
       
    57  * Is a partially decoded representation of an SNMP V3 packet.
       
    58  * <P>
       
    59  * This class can be used when developing customized manager or agent.
       
    60  * <P>
       
    61  * The <CODE>SnmpV3Message</CODE> class is directly mapped onto the
       
    62  * message syntax defined in RFC 2572.
       
    63  * <BLOCKQUOTE>
       
    64  * <PRE>
       
    65  * SNMPv3Message ::= SEQUENCE {
       
    66  *          msgVersion INTEGER ( 0 .. 2147483647 ),
       
    67  *          -- administrative parameters
       
    68  *          msgGlobalData HeaderData,
       
    69  *          -- security model-specific parameters
       
    70  *          -- format defined by Security Model
       
    71  *          msgSecurityParameters OCTET STRING,
       
    72  *          msgData  ScopedPduData
       
    73  *      }
       
    74  *     HeaderData ::= SEQUENCE {
       
    75  *         msgID      INTEGER (0..2147483647),
       
    76  *         msgMaxSize INTEGER (484..2147483647),
       
    77  *
       
    78  *         msgFlags   OCTET STRING (SIZE(1)),
       
    79  *                    --  .... ...1   authFlag
       
    80  *                    --  .... ..1.   privFlag
       
    81  *                    --  .... .1..   reportableFlag
       
    82  *                    --              Please observe:
       
    83  *                    --  .... ..00   is OK, means noAuthNoPriv
       
    84  *                    --  .... ..01   is OK, means authNoPriv
       
    85  *                    --  .... ..10   reserved, must NOT be used.
       
    86  *                    --  .... ..11   is OK, means authPriv
       
    87  *
       
    88  *         msgSecurityModel INTEGER (1..2147483647)
       
    89  *     }
       
    90  * </BLOCKQUOTE>
       
    91  * </PRE>
       
    92  * <p><b>This API is a Sun Microsystems internal API  and is subject
       
    93  * to change without notice.</b></p>
       
    94  * @since 1.5
       
    95  */
       
    96 public class SnmpV3Message extends SnmpMsg {
       
    97 
       
    98     /**
       
    99      * Message identifier.
       
   100      */
       
   101     public int msgId = 0;
       
   102 
       
   103     /**
       
   104      * Message max size the pdu sender can deal with.
       
   105      */
       
   106     public int msgMaxSize = 0;
       
   107     /**
       
   108      * Message flags. Reportable flag  and security level.</P>
       
   109      *<PRE>
       
   110      * --  .... ...1   authFlag
       
   111      * --  .... ..1.   privFlag
       
   112      * --  .... .1..   reportableFlag
       
   113      * --              Please observe:
       
   114      * --  .... ..00   is OK, means noAuthNoPriv
       
   115      * --  .... ..01   is OK, means authNoPriv
       
   116      * --  .... ..10   reserved, must NOT be used.
       
   117      * --  .... ..11   is OK, means authPriv
       
   118      *</PRE>
       
   119      */
       
   120     public byte msgFlags = 0;
       
   121     /**
       
   122      * The security model the security sub system MUST use in order to deal with this pdu (eg: User based Security Model Id = 3).
       
   123      */
       
   124     public int msgSecurityModel = 0;
       
   125     /**
       
   126      * The unmarshalled security parameters.
       
   127      */
       
   128     public byte[] msgSecurityParameters = null;
       
   129     /**
       
   130      * The context engine Id in which the pdu must be handled (Generaly the local engine Id).
       
   131      */
       
   132     public byte[] contextEngineId = null;
       
   133     /**
       
   134      * The context name in which the OID has to be interpreted.
       
   135      */
       
   136     public byte[] contextName = null;
       
   137     /** The encrypted form of the scoped pdu (Only relevant when dealing with privacy).
       
   138      */
       
   139     public byte[] encryptedPdu = null;
       
   140 
       
   141     /**
       
   142      * Constructor.
       
   143      *
       
   144      */
       
   145     public SnmpV3Message() {
       
   146     }
       
   147     /**
       
   148      * Encodes this message and puts the result in the specified byte array.
       
   149      * For internal use only.
       
   150      *
       
   151      * @param outputBytes An array to receive the resulting encoding.
       
   152      *
       
   153      * @exception ArrayIndexOutOfBoundsException If the result does not fit
       
   154      *                                           into the specified array.
       
   155      */
       
   156     public int encodeMessage(byte[] outputBytes)
       
   157         throws SnmpTooBigException {
       
   158         int encodingLength = 0;
       
   159         if (SNMP_LOGGER.isLoggable(Level.FINER)) {
       
   160             SNMP_LOGGER.logp(Level.FINER, SnmpV3Message.class.getName(),
       
   161                     "encodeMessage",
       
   162                     "Can't encode directly V3Message! Need a SecuritySubSystem");
       
   163         }
       
   164         throw new IllegalArgumentException("Can't encode");
       
   165     }
       
   166 
       
   167     /**
       
   168      * Decodes the specified bytes and initializes this message.
       
   169      * For internal use only.
       
   170      *
       
   171      * @param inputBytes The bytes to be decoded.
       
   172      *
       
   173      * @exception SnmpStatusException If the specified bytes are not a valid encoding.
       
   174      */
       
   175     public void decodeMessage(byte[] inputBytes, int byteCount)
       
   176         throws SnmpStatusException {
       
   177 
       
   178         try {
       
   179             BerDecoder bdec = new BerDecoder(inputBytes);
       
   180             bdec.openSequence();
       
   181             version = bdec.fetchInteger();
       
   182             bdec.openSequence();
       
   183             msgId = bdec.fetchInteger();
       
   184             msgMaxSize = bdec.fetchInteger();
       
   185             msgFlags = bdec.fetchOctetString()[0];
       
   186             msgSecurityModel =bdec.fetchInteger();
       
   187             bdec.closeSequence();
       
   188             msgSecurityParameters = bdec.fetchOctetString();
       
   189             if( (msgFlags & SnmpDefinitions.privMask) == 0 ) {
       
   190                 bdec.openSequence();
       
   191                 contextEngineId = bdec.fetchOctetString();
       
   192                 contextName = bdec.fetchOctetString();
       
   193                 data = bdec.fetchAny();
       
   194                 dataLength = data.length;
       
   195                 bdec.closeSequence();
       
   196             }
       
   197             else {
       
   198                 encryptedPdu = bdec.fetchOctetString();
       
   199             }
       
   200             bdec.closeSequence() ;
       
   201         }
       
   202         catch(BerException x) {
       
   203             x.printStackTrace();
       
   204             throw new SnmpStatusException("Invalid encoding") ;
       
   205         }
       
   206 
       
   207         if (SNMP_LOGGER.isLoggable(Level.FINER)) {
       
   208             final StringBuilder strb = new StringBuilder()
       
   209             .append("Unmarshalled message : \n")
       
   210             .append("version : ").append(version)
       
   211             .append("\n")
       
   212             .append("msgId : ").append(msgId)
       
   213             .append("\n")
       
   214             .append("msgMaxSize : ").append(msgMaxSize)
       
   215             .append("\n")
       
   216             .append("msgFlags : ").append(msgFlags)
       
   217             .append("\n")
       
   218             .append("msgSecurityModel : ").append(msgSecurityModel)
       
   219             .append("\n")
       
   220             .append("contextEngineId : ").append(contextEngineId == null ? null :
       
   221                 SnmpEngineId.createEngineId(contextEngineId))
       
   222             .append("\n")
       
   223             .append("contextName : ").append(contextName)
       
   224             .append("\n")
       
   225             .append("data : ").append(data)
       
   226             .append("\n")
       
   227             .append("dat len : ").append((data == null) ? 0 : data.length)
       
   228             .append("\n")
       
   229             .append("encryptedPdu : ").append(encryptedPdu)
       
   230             .append("\n");
       
   231             SNMP_LOGGER.logp(Level.FINER, SnmpV3Message.class.getName(),
       
   232                     "decodeMessage", strb.toString());
       
   233         }
       
   234     }
       
   235 
       
   236     /**
       
   237      * Returns the associated request Id.
       
   238      * @param data The flat message.
       
   239      * @return The request Id.
       
   240      */
       
   241     public int getRequestId(byte[] data) throws SnmpStatusException {
       
   242         BerDecoder bdec = null;
       
   243         int msgId = 0;
       
   244         try {
       
   245             bdec = new BerDecoder(data);
       
   246             bdec.openSequence();
       
   247             bdec.fetchInteger();
       
   248             bdec.openSequence();
       
   249             msgId = bdec.fetchInteger();
       
   250         }catch(BerException x) {
       
   251             throw new SnmpStatusException("Invalid encoding") ;
       
   252         }
       
   253         try {
       
   254             bdec.closeSequence();
       
   255         }
       
   256         catch(BerException x) {
       
   257         }
       
   258 
       
   259         return msgId;
       
   260     }
       
   261 
       
   262     /**
       
   263      * Initializes this message with the specified <CODE>pdu</CODE>.
       
   264      * <P>
       
   265      * This method initializes the data field with an array of
       
   266      * <CODE>maxDataLength</CODE> bytes. It encodes the <CODE>pdu</CODE>.
       
   267      * The resulting encoding is stored in the data field
       
   268      * and the length of the encoding is stored in <CODE>dataLength</CODE>.
       
   269      * <p>
       
   270      * If the encoding length exceeds <CODE>maxDataLength</CODE>,
       
   271      * the method throws an exception.
       
   272      *
       
   273      * @param p The PDU to be encoded.
       
   274      * @param maxDataLength The maximum length permitted for the data field.
       
   275      *
       
   276      * @exception SnmpStatusException If the specified <CODE>pdu</CODE>
       
   277      *   is not valid.
       
   278      * @exception SnmpTooBigException If the resulting encoding does not fit
       
   279      * into <CODE>maxDataLength</CODE> bytes.
       
   280      * @exception ArrayIndexOutOfBoundsException If the encoding exceeds
       
   281      *    <CODE>maxDataLength</CODE>.
       
   282      */
       
   283     public void encodeSnmpPdu(SnmpPdu p,
       
   284                               int maxDataLength)
       
   285         throws SnmpStatusException, SnmpTooBigException {
       
   286 
       
   287         SnmpScopedPduPacket pdu = (SnmpScopedPduPacket) p;
       
   288 
       
   289         if (SNMP_LOGGER.isLoggable(Level.FINER)) {
       
   290             final StringBuilder strb = new StringBuilder()
       
   291             .append("PDU to marshall: \n")
       
   292             .append("security parameters : ").append(pdu.securityParameters)
       
   293             .append("\n")
       
   294             .append("type : ").append(pdu.type)
       
   295             .append("\n")
       
   296             .append("version : ").append(pdu.version)
       
   297             .append("\n")
       
   298             .append("requestId : ").append(pdu.requestId)
       
   299             .append("\n")
       
   300             .append("msgId : ").append(pdu.msgId)
       
   301             .append("\n")
       
   302             .append("msgMaxSize : ").append(pdu.msgMaxSize)
       
   303             .append("\n")
       
   304             .append("msgFlags : ").append(pdu.msgFlags)
       
   305             .append("\n")
       
   306             .append("msgSecurityModel : ").append(pdu.msgSecurityModel)
       
   307             .append("\n")
       
   308             .append("contextEngineId : ").append(pdu.contextEngineId)
       
   309             .append("\n")
       
   310             .append("contextName : ").append(pdu.contextName)
       
   311             .append("\n");
       
   312             SNMP_LOGGER.logp(Level.FINER, SnmpV3Message.class.getName(),
       
   313                     "encodeSnmpPdu", strb.toString());
       
   314         }
       
   315 
       
   316         version = pdu.version;
       
   317         address = pdu.address;
       
   318         port = pdu.port;
       
   319         msgId = pdu.msgId;
       
   320         msgMaxSize = pdu.msgMaxSize;
       
   321         msgFlags = pdu.msgFlags;
       
   322         msgSecurityModel = pdu.msgSecurityModel;
       
   323 
       
   324         contextEngineId = pdu.contextEngineId;
       
   325         contextName = pdu.contextName;
       
   326 
       
   327         securityParameters = pdu.securityParameters;
       
   328 
       
   329         //
       
   330         // Allocate the array to receive the encoding.
       
   331         //
       
   332         data = new byte[maxDataLength];
       
   333 
       
   334         //
       
   335         // Encode the pdu
       
   336         // Reminder: BerEncoder does backward encoding !
       
   337         //
       
   338 
       
   339         try {
       
   340             BerEncoder benc = new BerEncoder(data) ;
       
   341             benc.openSequence() ;
       
   342             encodeVarBindList(benc, pdu.varBindList) ;
       
   343 
       
   344             switch(pdu.type) {
       
   345 
       
   346             case pduGetRequestPdu :
       
   347             case pduGetNextRequestPdu :
       
   348             case pduInformRequestPdu :
       
   349             case pduGetResponsePdu :
       
   350             case pduSetRequestPdu :
       
   351             case pduV2TrapPdu :
       
   352             case pduReportPdu :
       
   353                 SnmpPduRequestType reqPdu = (SnmpPduRequestType) pdu;
       
   354                 benc.putInteger(reqPdu.getErrorIndex());
       
   355                 benc.putInteger(reqPdu.getErrorStatus());
       
   356                 benc.putInteger(pdu.requestId);
       
   357                 break;
       
   358 
       
   359             case pduGetBulkRequestPdu :
       
   360                 SnmpPduBulkType bulkPdu = (SnmpPduBulkType) pdu;
       
   361                 benc.putInteger(bulkPdu.getMaxRepetitions());
       
   362                 benc.putInteger(bulkPdu.getNonRepeaters());
       
   363                 benc.putInteger(pdu.requestId);
       
   364                 break ;
       
   365 
       
   366             default:
       
   367                 throw new SnmpStatusException("Invalid pdu type " + String.valueOf(pdu.type)) ;
       
   368             }
       
   369             benc.closeSequence(pdu.type) ;
       
   370             dataLength = benc.trim() ;
       
   371         }
       
   372         catch(ArrayIndexOutOfBoundsException x) {
       
   373             throw new SnmpTooBigException() ;
       
   374         }
       
   375     }
       
   376 
       
   377 
       
   378     /**
       
   379      * Gets the PDU encoded in this message.
       
   380      * <P>
       
   381      * This method decodes the data field and returns the resulting PDU.
       
   382      *
       
   383      * @return The resulting PDU.
       
   384      * @exception SnmpStatusException If the encoding is not valid.
       
   385      */
       
   386 
       
   387     public SnmpPdu decodeSnmpPdu()
       
   388         throws SnmpStatusException {
       
   389 
       
   390         SnmpScopedPduPacket pdu = null;
       
   391 
       
   392         BerDecoder bdec = new BerDecoder(data) ;
       
   393         try {
       
   394             int type = bdec.getTag() ;
       
   395             bdec.openSequence(type) ;
       
   396             switch(type) {
       
   397 
       
   398             case pduGetRequestPdu :
       
   399             case pduGetNextRequestPdu :
       
   400             case pduInformRequestPdu :
       
   401             case pduGetResponsePdu :
       
   402             case pduSetRequestPdu :
       
   403             case pduV2TrapPdu :
       
   404             case pduReportPdu :
       
   405                 SnmpScopedPduRequest reqPdu = new SnmpScopedPduRequest() ;
       
   406                 reqPdu.requestId = bdec.fetchInteger() ;
       
   407                 reqPdu.setErrorStatus(bdec.fetchInteger());
       
   408                 reqPdu.setErrorIndex(bdec.fetchInteger());
       
   409                 pdu = reqPdu ;
       
   410                 break ;
       
   411 
       
   412             case pduGetBulkRequestPdu :
       
   413                 SnmpScopedPduBulk bulkPdu = new SnmpScopedPduBulk() ;
       
   414                 bulkPdu.requestId = bdec.fetchInteger() ;
       
   415                 bulkPdu.setNonRepeaters(bdec.fetchInteger());
       
   416                 bulkPdu.setMaxRepetitions(bdec.fetchInteger());
       
   417                 pdu = bulkPdu ;
       
   418                 break ;
       
   419             default:
       
   420                 throw new SnmpStatusException(snmpRspWrongEncoding) ;
       
   421             }
       
   422             pdu.type = type;
       
   423             pdu.varBindList = decodeVarBindList(bdec);
       
   424             bdec.closeSequence() ;
       
   425         } catch(BerException e) {
       
   426             if (SNMP_LOGGER.isLoggable(Level.FINEST)) {
       
   427                 SNMP_LOGGER.logp(Level.FINEST, SnmpV3Message.class.getName(),
       
   428                         "decodeSnmpPdu", "BerException", e);
       
   429             }
       
   430             throw new SnmpStatusException(snmpRspWrongEncoding);
       
   431         }
       
   432 
       
   433         //
       
   434         // The easy work.
       
   435         //
       
   436         pdu.address = address;
       
   437         pdu.port = port;
       
   438         pdu.msgFlags = msgFlags;
       
   439         pdu.version = version;
       
   440         pdu.msgId = msgId;
       
   441         pdu.msgMaxSize = msgMaxSize;
       
   442         pdu.msgSecurityModel = msgSecurityModel;
       
   443         pdu.contextEngineId = contextEngineId;
       
   444         pdu.contextName = contextName;
       
   445 
       
   446         pdu.securityParameters = securityParameters;
       
   447 
       
   448         if (SNMP_LOGGER.isLoggable(Level.FINER)) {
       
   449             final StringBuilder strb = new StringBuilder()
       
   450             .append("Unmarshalled PDU : \n")
       
   451             .append("type : ").append(pdu.type)
       
   452             .append("\n")
       
   453             .append("version : ").append(pdu.version)
       
   454             .append("\n")
       
   455             .append("requestId : ").append(pdu.requestId)
       
   456             .append("\n")
       
   457             .append("msgId : ").append(pdu.msgId)
       
   458             .append("\n")
       
   459             .append("msgMaxSize : ").append(pdu.msgMaxSize)
       
   460             .append("\n")
       
   461             .append("msgFlags : ").append(pdu.msgFlags)
       
   462             .append("\n")
       
   463             .append("msgSecurityModel : ").append(pdu.msgSecurityModel)
       
   464             .append("\n")
       
   465             .append("contextEngineId : ").append(pdu.contextEngineId)
       
   466             .append("\n")
       
   467             .append("contextName : ").append(pdu.contextName)
       
   468             .append("\n");
       
   469             SNMP_LOGGER.logp(Level.FINER, SnmpV3Message.class.getName(),
       
   470                     "decodeSnmpPdu", strb.toString());
       
   471         }
       
   472         return pdu ;
       
   473     }
       
   474 
       
   475     /**
       
   476      * Dumps this message in a string.
       
   477      *
       
   478      * @return The string containing the dump.
       
   479      */
       
   480     public String printMessage() {
       
   481         StringBuilder sb = new StringBuilder();
       
   482         sb.append("msgId : " + msgId + "\n");
       
   483         sb.append("msgMaxSize : " + msgMaxSize + "\n");
       
   484         sb.append("msgFlags : " + msgFlags + "\n");
       
   485         sb.append("msgSecurityModel : " + msgSecurityModel + "\n");
       
   486 
       
   487         if (contextEngineId == null) {
       
   488             sb.append("contextEngineId : null");
       
   489         }
       
   490         else {
       
   491             sb.append("contextEngineId : {\n");
       
   492             sb.append(dumpHexBuffer(contextEngineId,
       
   493                                     0,
       
   494                                     contextEngineId.length));
       
   495             sb.append("\n}\n");
       
   496         }
       
   497 
       
   498         if (contextName == null) {
       
   499             sb.append("contextName : null");
       
   500         }
       
   501         else {
       
   502             sb.append("contextName : {\n");
       
   503             sb.append(dumpHexBuffer(contextName,
       
   504                                     0,
       
   505                                     contextName.length));
       
   506             sb.append("\n}\n");
       
   507         }
       
   508         return sb.append(super.printMessage()).toString();
       
   509     }
       
   510 
       
   511 }